Created
August 1, 2017 17:55
-
-
Save markis/7ccba4285655e087022277b0d6196195 to your computer and use it in GitHub Desktop.
Automatic vpn using openconnect
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const proc = require('child_process'); | |
const crypto = require('crypto'); | |
const config = require('./config'); | |
connect() | |
function connect() { | |
var step = 0; | |
const ps = proc.spawn('sudo', ['-S', 'openconnect', config.host, '-u', config.user]); | |
ps.stdout.on('data', listener); | |
ps.stderr.on('data', listener); | |
function listener(chunk) { | |
process.stdout.write(chunk.toString('utf8').trim() + '\n'); | |
if (step === 0 && chunk.indexOf('sudo') > -1) { | |
ps.stdin.write(config.sudopass + '\n'); | |
step = 1; | |
} | |
else if ((step === 0 || step === 1) && chunk.indexOf('Password:') > -1) { | |
ps.stdin.write(config.pass + '\n'); | |
step = 2; | |
} | |
else if (step === 2 && chunk.indexOf('Response:') > -1) { | |
const googleAuth = getGoogleAuthenticatorCode(config.authenticatorSecret); | |
ps.stdin.write(googleAuth + '\n'); | |
step = 0; | |
} | |
else if (chunk.indexOf('dead peer') > -1) { | |
try { ps.kill(); } catch(e) {} | |
ps = null; | |
connect(); | |
} | |
}; | |
} | |
function getGoogleAuthenticatorCode(secret) { | |
const byteTable = [ | |
0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | |
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, | |
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | |
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, | |
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, | |
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, | |
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | |
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, | |
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff | |
]; | |
var plainChar; | |
var shiftIndex = 0; | |
var encodedByte = 0; | |
var pos = 0; | |
const encoded = new Buffer(secret); | |
const decoded = new Buffer(Math.ceil(5 * encoded.length / 8)); | |
for (var i = 0; i < encoded.length && 0x3d !== encoded[i]; i++) { | |
encodedByte = byteTable[encoded[i] - 0x30]; | |
shiftIndex > 3 ? | |
(decoded[pos] = plainChar |= 0xff & encodedByte >>> (shiftIndex = (shiftIndex + 5) % 8), pos++, plainChar = 0xff & encodedByte << 8 - shiftIndex) : | |
shiftIndex = (shiftIndex + 5) % 8, 0 === shiftIndex ? | |
(decoded[pos] = plainChar |= encodedByte, pos++, plainChar = 0) : | |
plainChar |= 0xff & encodedByte << 8 - shiftIndex | |
} | |
var counter = Math.floor(Date.now() / 30000); | |
const res = []; | |
while (res.length < 8) { | |
res.unshift(counter & 0xFF); | |
counter = counter >> 8; | |
} | |
const u64Counter = new Buffer(res); | |
const sha1hmac = crypto.createHmac('sha1', new Buffer(decoded.slice(0, pos))); | |
const counterHex = sha1hmac.update(u64Counter).digest('hex'); | |
const hmac = new Buffer(counterHex, 'hex'); | |
const offset = hmac[19] & 0xf; | |
const code = String((hmac[offset] & 0x7f) << 24 | (hmac[offset + 1] & 0xff) << 16 | (hmac[offset + 2] & 0xff) << 8 | (hmac[offset + 3] & 0xff)); | |
return ('000000' + code).slice(-6); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment