node-vpn-client
Version:
Controls a instance of OpenVpn Client through the manager interface
102 lines (95 loc) • 2.9 kB
text/typescript
import Manager from 'node-vpn-manager'
import * as path from 'path'
import fetch from 'node-fetch'
import { Address4 } from 'ip-address'
const appRoot = require('app-root-path')
type ClientConstructorProps = {
sudoPasswd: string
ovpnFiles: string[]
ovpnFilePath?: string
vpnUsername: string
vpnPasswd: string
timeout: number
onDisconnected?: () => void
}
class Client {
sudoPasswd: string
state: 'connecting' | 'connected' | 'disconnected' | undefined
ovpnFiles: string[]
ovpnFilePath?: string
vpnUsername: string
vpnPasswd: string
timeout: number
onDisconnected?: () => void
constructor({
sudoPasswd,
ovpnFiles,
ovpnFilePath,
vpnUsername,
vpnPasswd,
onDisconnected,
timeout
}: ClientConstructorProps) {
this.sudoPasswd = sudoPasswd
this.ovpnFiles = ovpnFiles
this.ovpnFilePath = ovpnFilePath
this.vpnUsername = vpnUsername
this.vpnPasswd = vpnPasswd
this.onDisconnected = onDisconnected
this.timeout = timeout
}
connect() {
return new Promise(async (resolve, reject) => {
let connectionTimeout = 0
const monitorConnectionTimeout = setInterval(async () => {
connectionTimeout++
if (connectionTimeout > this.timeout) {
await vpn.kill()
this.state = 'disconnected'
clearInterval(monitorConnectionTimeout)
await vpn.kill()
reject('Connection Timeout')
}
}, 1000)
const vpn = new Manager({
sudoPasswd: this.sudoPasswd,
ovpnFile: path.normalize(
path.resolve(
appRoot +
this.ovpnFiles[Math.floor(Math.random() * this.ovpnFiles.length)]
)
),
username: this.vpnUsername,
password: this.vpnPasswd,
onStateChange: async (state: string) => {
if (state === 'CONNECTED' && this.state !== 'connected') {
this.state = 'connected'
const res = await fetch('http://icanhazip.com/')
const remoteIp = await res.text()
console.log(remoteIp)
const address = new Address4(remoteIp.replace('\n', ''))
if (address.isValid()) {
clearInterval(monitorConnectionTimeout)
resolve(remoteIp)
}
clearInterval(monitorConnectionTimeout)
reject('Error getting ip address')
}
if (
state === 'EXITING' &&
this.onDisconnected &&
this.state !== 'disconnected'
) {
this.state = 'disconnected'
await vpn.kill()
clearInterval(monitorConnectionTimeout)
this.onDisconnected()
}
}
})
await vpn.init()
await vpn.connect()
})
}
}
export default Client