vpn.email.client.gfw
Version:
vpn client gfw mode
705 lines (692 loc) • 28.2 kB
JavaScript
/*!
* Copyright 2017 Vpn.Email network security technology Canada Inc. All Rights Reserved.
*
* Vpn.Email network technolog Canada Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
;
const Net = require("net");
const Http = require("http");
const Ip = require("ip");
const Nekudo = require("../util/nekudo");
const httpProxy_1 = require("./httpProxy");
const Async = require("async");
const Compress = require("./compress");
const Rfc1928 = require("./rfc1928");
const shortId = require("shortid");
const Stream = require("stream");
const Fs = require("fs");
const Path = require("path");
const whiteIpFile = 'whiteIpList.json';
Http.globalAgent.maxSockets = 1024;
const ipConnectResetTime = 1000 * 60 * 5;
const Day = 1000 * 60 * 60 * 24;
const managerPagePort = 8001;
const _HTTP_502 = `HTTP/1.1 502 Bad Gateway
Content-Length: 0
Connection: close
Proxy-Connection: close
Content-Type: text/html; charset=UTF-8
Cache-Control: private, max-age=0
`;
const _HTTP_404 = `HTTP/1.1 404 Not Found
Content-Length: 0
Connection: close
Proxy-Connection: close
Content-Type: text/html; charset=UTF-8
Cache-Control: private, max-age=0
`;
const _HTTP_599_body = 'Have not internet.\r\n無互聯網,請檢查您的網絡連結\r\nネットワークはオフラインです\r\n';
const _HTTP_599 = `HTTP/1.1 599 Have not internet
Content-Length: 100
Connection: close
Proxy-Connection: close
Content-Type: text/html; charset=UTF-8
Cache-Control: private, max-age=0
${_HTTP_599_body}
`;
const _HTTP_598_body = `Domain name can't find.\r\n無此域名\r\nこのドメイン名が見つからないです\r\n`;
const _HTTP_598 = `HTTP/1.1 598 Domain name can't find
Content-Length: 100
Connection: close
Proxy-Connection: close
Content-Type: text/html; charset=UTF-8
Cache-Control: private, max-age=0
${_HTTP_598_body}
`;
const _HTTP_200 = (body) => {
return `HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Content-Length: ${body.length}
${body}\r\n\r\n`;
};
const body_403 = '<!DOCTYPE html><html><p>This domain in proxy blacklist.</p><p>這個域名被代理服務器列入黑名單</p><p>このサイドはプロクシーの禁止リストにあります</p></html>';
const HTTP_403 = `HTTP/1.1 403 Forbidden
Content-Type: text/html; charset=UTF-8
Connection: close
Proxy-Connection: close
Content-Length: 300
${body_403}
`;
const _HTTP_PROXY_200 = `HTTP/1.1 200 Connection Established
Content-Type: text/html; charset=UTF-8
`;
const testGatewayDomainName = 'www.google.com';
// socks 5 headers
const res_NO_AUTHENTICATION_REQUIRED = new Buffer('0500', 'hex');
const respon_se = new Buffer('05000001000000000000', 'hex');
// -
const IsSslConnect = (buffer) => {
const kk = buffer.toString('hex', 0, 4);
return /^1603(01|02|03|00)|^80..0103|^(14|15|17)03(00|01)/.test(kk);
};
const checkDomain = (domainList, domain, CallBack) => {
if (Net.isIP(domain)) {
return CallBack(null, domainList.find(n => { return n === domain; }) ? true : false);
}
const domainS = domain.split('.');
return Async.some(domainList, (n, next) => {
const nS = n.split('.');
let ret = false;
for (let i = nS.length - 1, ni = domainS.length - 1; i >= 0 && ni >= 0; i--, ni--) {
const ns = nS[i];
if (domainS[ni].toLowerCase() !== nS[i].toLowerCase()) {
break;
}
if (i === 0)
ret = true;
}
return next(null, ret);
}, (err, result) => {
return CallBack(null, result);
});
};
const otherRespon = (path, host, port, UserAgent) => {
const option = {
host: host,
port: port,
path: '/' + path,
method: 'GET',
headers: {
//'Upgrade-Insecure-Requests': 1,
Host: host + ':' + port,
'Accept': '*/*',
'Accept-Language': 'en-US',
'Connection': 'keep-alive',
'Accept-Encoding': 'gzip, deflate',
'User-Agent': UserAgent || 'Mozilla/5.0',
}
};
return option;
};
const otherRequestForNet = (path, host, port, UserAgent) => {
if (path.length < 2048)
return `GET /${path} HTTP/1.1\r\n` +
`Host: ${host}:${port}\r\n` +
`Accept: */*\r\n` +
`Accept-Language: en-ca\r\n` +
`Connection: keep-alive\r\n` +
`Accept-Encoding: gzip, deflate\r\n` +
`User-Agent: ${UserAgent ? UserAgent : 'Mozilla/5.0'}\r\n\r\n`;
return `POST /${Buffer.allocUnsafe(10 + Math.random()).toString('base64')} HTTP/1.1\r\n` +
`Host: ${host}:${port}\r\n` +
`Content-Length: ${path.length}\r\n\r\n` +
path + '\r\n\r\n';
};
const testLogin = (req, loginUserList) => {
const header = new httpProxy_1.default(req);
if (header.isGet && header.Url.path === loginUserList)
return true;
return false;
};
const closeClientSocket = (socket, status, body) => {
if (!socket || !socket.writable)
return;
let stat = _HTTP_404;
switch (status) {
case 502:
stat = _HTTP_502;
break;
case 599:
stat = _HTTP_599;
break;
case 598:
stat = _HTTP_598;
break;
case -200:
stat = _HTTP_PROXY_200;
socket.write(stat);
return socket.resume();
default:
break;
}
socket.end(stat);
return socket.resume();
};
const _connect = (hostname, hostIp, port, clientSocket, data, connectHostTimeOut, CallBack) => {
const socket = new Net.Socket();
const ip = clientSocket.remoteAddress.split(':')[3];
let err = null;
const id = `[${ip}] => [${hostname}:${port}] `;
const hostInfo = `{${hostIp}:${port}}`;
let callbacked = false;
const startTime = new Date().getTime();
const callBack = (err) => {
if (callbacked)
return;
callbacked = true;
if (socket && typeof socket.unpipe === 'function')
socket.unpipe();
if (socket && typeof socket.end === 'function')
socket.end();
if (socket && typeof socket.destroy === 'function')
socket.destroy();
CallBack(err);
};
socket.on('connect', () => {
console.log(`${id} socket.on connect!`);
clearTimeout(timeout);
if (callbacked) {
const stopTime = new Date().getTime();
const connectTimeOutTime = stopTime - startTime + 500;
console.log(` connectHostTimeOut need change [${connectHostTimeOut}] => [${connectTimeOutTime}]`);
connectHostTimeOut = connectTimeOutTime;
return socket.end();
}
socket.pipe(clientSocket).pipe(socket);
if (socket && socket.writable) {
socket.write(data);
return socket.resume();
}
return callBack(null);
});
clientSocket.on('error', err => {
callBack(null);
return console.log('clientSocket on error', err.message);
});
socket.on('error', err => {
console.log('_connect socket on error', err.message);
return callBack(err);
});
socket.on('end', () => {
return callBack(null);
});
const timeout = setTimeout(() => {
err = new Error(`${id} _connect timeout!`);
return callBack(err);
}, connectHostTimeOut);
return socket.connect(port, hostIp);
};
const tryConnectHost = (hostname, hostIp, port, data, clientSocket, isSSLConnect, checkAgainTimeOut, connectTimeOut, gateway, CallBack) => {
if (isSSLConnect) {
clientSocket.once('data', (_data) => {
return tryConnectHost(hostname, hostIp, port, _data, clientSocket, false, checkAgainTimeOut, connectTimeOut, gateway, CallBack);
});
return closeClientSocket(clientSocket, -200, '');
}
if (!hostIp) {
console.log(hostname, ' tryConnectHost have not hostIp CallBack!');
return CallBack(new Error('not hostIp'), data);
}
const now = new Date().getTime();
console.log('tryConnectHost do Async.someSeries hostIp:');
console.log(hostIp);
Async.someSeries(hostIp.dns, (n, next) => {
console.log(n);
if (n.family === 6 && !this.hostGlobalIpV6) {
return next(null, false);
}
if (n.connect && n.connect.length) {
const last = n.connect[0];
if (now - last < ipConnectResetTime) {
console.log(n.address, ' cant connect in time range!');
return next(null, false);
}
}
return _connect(hostname, n.address, port, clientSocket, data, connectTimeOut, err => {
if (err) {
console.log('_connect callback error', err.message);
if (!n.connect)
n.connect = [];
n.connect.unshift(new Date().getTime());
return next(null, false);
}
return next(null, true);
});
}, (err, fin) => {
if (fin)
return CallBack();
return CallBack(new Error('all ip cant direct connect'), data);
});
};
class hostLookupResponse extends Stream.Writable {
constructor(CallBack) {
super();
this.CallBack = CallBack;
}
_write(chunk, enc, next) {
const ns = chunk.toString('utf8');
try {
const _ret = JSON.parse(ns);
const ret = {
expire: new Date().getTime() + Day,
dns: _ret
};
this.CallBack(null, ret);
next();
return this.end();
}
catch (e) {
return next(e);
}
}
}
class gateWay {
constructor(serverIp, serverPort, password) {
this.serverIp = serverIp;
this.serverPort = serverPort;
this.password = password;
this.userAgent = null;
}
request(str) {
return Buffer.from(otherRequestForNet(str, this.serverIp, this.serverPort, this.userAgent), 'utf8');
}
hostLookup(hostName, userAgent, CallBack) {
const _data = new Buffer(JSON.stringify({ hostName: hostName }), 'utf8');
const encrypt = new Compress.encryptStream(this.password, 0, (str) => {
return this.request(str);
}, err => {
if (err) {
return CallBack(err);
}
const finish = new hostLookupResponse(CallBack);
const httpBlock = new Compress.getDecryptClientStreamFromHttp();
const decrypt = new Compress.decryptStream(this.password);
const _socket = Net.connect({ port: this.serverPort, host: this.serverIp }, () => {
httpBlock.on('error', err => {
_socket.end(_HTTP_502);
return CallBack(err);
});
encrypt.pipe(_socket).pipe(httpBlock).pipe(decrypt).pipe(finish);
encrypt.write(_data);
});
});
}
requestGetWay(id, uuuu, userAgent, socket) {
this.userAgent = userAgent;
const decrypt = new Compress.decryptStream(this.password);
const encrypt = new Compress.encryptStream(this.password, 0, (str) => {
return this.request(str);
}, err => {
if (err) {
return console.log('requestGetWay new Compress.encryptStream got ERROR: ', err.message);
}
const httpBlock = new Compress.getDecryptClientStreamFromHttp();
httpBlock.on('error', err => {
socket.end(_HTTP_404);
});
const _socket = Net.connect({ port: this.serverPort, host: this.serverIp }, () => {
console.log('requestGetWay connect:', uuuu.host, uuuu.port);
encrypt.pipe(_socket).pipe(httpBlock).pipe(decrypt).pipe(socket).pipe(encrypt);
encrypt.write(Buffer.from(JSON.stringify(uuuu), 'utf8'));
});
});
}
requestGetWayTest(id, uuuu, userAgent, socket) {
console.log('connect to test port!');
const _socket = Net.createConnection({ port: this.serverPort + 1, host: this.serverIp });
_socket.on('connect', () => {
const ls = new Compress.printStream('>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
const ls1 = new Compress.printStream('<<<<<<<<<<<<<<<<<<<<<<<<<<<<');
_socket.pipe(socket).pipe(_socket);
const _buf = Buffer.from(otherRequestForNet(Buffer.from(JSON.stringify(uuuu), 'utf8').toString('base64'), this.serverIp, this.serverPort, this.userAgent), 'utf8');
_socket.write(_buf);
});
_socket.on('end', () => {
return console.log('test gateway END');
});
_socket.on('error', error => {
return console.log('test gateway ERROR:', error.message);
});
}
}
const isAllBlackedByFireWall = (hostName, ip6, checkAgainTime, gatway, userAgent, domainListPool, CallBack) => {
const hostIp = domainListPool.get(hostName);
const now = new Date().getTime();
if (!hostIp || hostIp.expire < now)
return gatway.hostLookup(hostName, userAgent, CallBack);
return CallBack(null, hostIp);
};
class socks5 {
constructor(socket) {
this.socket = socket;
this.keep = false;
this.socket.once('data', (chunk) => {
return this.connectStat2(chunk);
});
this.socket.write(res_NO_AUTHENTICATION_REQUIRED);
}
closeSocks5(buffer) {
if (this.socket) {
if (this.socket.writable) {
this.socket.end(buffer);
}
if (typeof this.socket.removeAllListeners === 'function')
this.socket.removeAllListeners();
}
}
connectStat2_after(retBuffer, cmd) {
if (this.keep) {
this.socket.once('data', (data) => {
/*
const header = new HttpProxyHeader.httpProxy ( data )
if ( this.hostList.putListSock5 ( this.host, IsSslConnect ? null : header ))
return this.closeSocks5 ( HTTP_403 )
if ( header.cachePath && this.cacheKeepTime ) {
return this.proxyCacheSave ( header, ( err, data1: Buffer ) => {
if ( !data1 ) {
this.mainSsWrite = new mainSSWrite ( this.vpnServerSocket, this.masterPassword, IsSslConnect ( data ), this.id, 0 )
this.socket.pipe ( this.mainSsWrite )
if ( this.savePath )
return this.save ( header.BufferWithOutKeepAlife )
return this.save ( data )
}
this.ending = true
return this.endConnect ( data1 )
})
}
*/
});
return this.socket.write(retBuffer.buffer);
}
return this.closeSocks5(retBuffer.buffer);
}
connectStat2(data) {
const req = new Rfc1928.Requests(data);
this.ATYP = req.ATYP;
this.host = req.host;
this.port = req.port;
this.cmd = req.cmd;
const localIp = this.socket.localAddress.split(':')[3];
const retBuffer = new Rfc1928.Requests(respon_se);
retBuffer.ATYP_IP4Address = localIp;
let cmd = '';
switch (this.cmd) {
case Rfc1928.CMD.CONNECT:
this.keep = true;
console.log('got Rfc1928.CMD.CONNECT', this.ATYP);
break;
case Rfc1928.CMD.BIND:
cmd = 'Rfc1928.CMD.BIND';
console.log('Rfc1928.CMD.BIND request');
retBuffer.REP = Rfc1928.Replies.COMMAND_NOT_SUPPORTED_or_PROTOCOL_ERROR;
break;
case Rfc1928.CMD.UDP_ASSOCIATE:
cmd = 'Rfc1928.CMD.UDP_ASSOCIATE';
console.log('Rfc1928.CMD.UDP_ASSOCIATE');
retBuffer.REP = Rfc1928.Replies.COMMAND_NOT_SUPPORTED_or_PROTOCOL_ERROR;
break;
default:
retBuffer.REP = Rfc1928.Replies.COMMAND_NOT_SUPPORTED_or_PROTOCOL_ERROR;
break;
}
return this.connectStat2_after(retBuffer, cmd);
}
}
const httpProxy = (clientSocket, buffer, useGatWay, ip6, connectTimeOut, domainListPool, gatway, checkAgainTime, blackDomainList) => {
const httpHead = new httpProxy_1.default(buffer);
const hostName = httpHead.Url.hostname;
const userAgent = httpHead.headers['user-agent'];
const CallBack = (err, _data) => {
if (err) {
if (useGatWay && _data && _data.length && clientSocket.writable) {
const uuuu = {
uuid: shortId.generate(),
host: hostName,
buffer: _data.toString('base64'),
cmd: Rfc1928.CMD.CONNECT,
ATYP: Rfc1928.ATYP.IP_V4,
port: parseInt(httpHead.Url.port || httpHead.isHttps ? '443' : '80')
};
const id = `[${clientSocket.remoteAddress.split(':')[3]}:${clientSocket.remotePort}][${uuuu.uuid}] `;
console.log(` ${id} [${hostName}]`, 'try use gateway\n');
return gatway.requestGetWay(id, uuuu, userAgent, clientSocket);
}
return clientSocket.end(HTTP_403);
}
return;
};
return checkDomain(blackDomainList, hostName, (err, result) => {
if (result) {
return clientSocket.end(HTTP_403);
}
const port = parseInt(httpHead.Url.port || httpHead.isHttps ? '443' : '80');
const isIp = Net.isIP(hostName);
const hostIp = !isIp ? domainListPool.get(hostName) : { dns: [{ family: isIp, address: hostName, expire: null, connect: [] }], expire: null };
if (!hostIp) {
return isAllBlackedByFireWall(hostName, ip6, checkAgainTime, gatway, userAgent, domainListPool, (err, _hostIp) => {
if (err) {
return closeClientSocket(clientSocket, 504, null);
}
if (!_hostIp) {
console.log('isAllBlackedByFireWall back no _hostIp');
return CallBack(new Error('have not host info'));
}
domainListPool.set(hostName, _hostIp);
return tryConnectHost(hostName, _hostIp, port, buffer, clientSocket, httpHead.isConnect, checkAgainTime, connectTimeOut, useGatWay, CallBack);
});
}
return tryConnectHost(hostName, hostIp, port, buffer, clientSocket, httpHead.isConnect, checkAgainTime, connectTimeOut, useGatWay, CallBack);
});
};
const httpProxyTest = (socket, data, gateway) => {
const httpHead = new httpProxy_1.default(data);
const port = parseInt(httpHead.Url.port || httpHead.isHttps ? '443' : '80');
const hostName = httpHead.Url.hostname;
const userAgent = httpHead.headers['user-agent'];
let first = true;
const localrequest = (buf) => {
if (httpHead.isHttps && first) {
first = false;
console.log('https connect!');
socket.once('data', _data => {
return localrequest(_data);
});
return closeClientSocket(socket, -200, '');
}
const net = Net.createConnection(port, hostName, () => {
const ls = new Compress.printStream('>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
const ls1 = new Compress.printStream('<<<<<<<<<<<<<<<<<<<<<<<<<<<<');
net.pipe(socket).pipe(ls).pipe(net);
net.write(buf);
});
};
const connectTestPort = (buf) => {
if (httpHead.isHttps && first) {
first = false;
console.log('https connect!');
socket.once('data', _data => {
return connectTestPort(_data);
});
return closeClientSocket(socket, -200, '');
}
const uuuu = {
uuid: shortId.generate(),
host: hostName,
buffer: buf.toString('base64'),
cmd: Rfc1928.CMD.CONNECT,
ATYP: Rfc1928.ATYP.IP_V4,
port: port
};
const id = `[${socket.remoteAddress.split(':')[3]}:${socket.remotePort}][${uuuu.uuid}]`;
console.log(uuuu.buffer);
return gateway.requestGetWayTest(id, uuuu, userAgent, socket);
};
return connectTestPort(data);
};
class proxyServer {
constructor(whiteIpList, domainListPool, port, securityPath, serverIp, serverPort, password, checkAgainTimeOut, connectHostTimeOut, useGatWay, domainBlackList) {
this.whiteIpList = whiteIpList;
this.domainListPool = domainListPool;
this.port = port;
this.securityPath = securityPath;
this.serverIp = serverIp;
this.serverPort = serverPort;
this.password = password;
this.checkAgainTimeOut = checkAgainTimeOut;
this.connectHostTimeOut = connectHostTimeOut;
this.hostLocalIpv4 = null;
this.hostLocalIpv6 = null;
this.hostGlobalIpV4 = null;
this.hostGlobalIpV6 = null;
this.network = false;
this.getGlobalIpRunning = false;
this.getGlobalIp = (gateWay) => {
if (this.getGlobalIpRunning)
return;
this.getGlobalIpRunning = true;
const reqult = Nekudo.localNetInterFace();
this.hostLocalIpv4 = reqult.PrivateIp4;
this.hostLocalIpv6 = reqult.PrivateIp6;
this.hostGlobalIpV4 = reqult.PublicIp4;
this.hostGlobalIpV6 = reqult.publicIp6;
gateWay.hostLookup(testGatewayDomainName, null, (err, data) => {
if (err)
return console.log('getGlobalIp ERROR:', err.message);
this.network = true;
this.hostLocalIpv6 ? console.log(`LocalIpv6[ ${this.hostLocalIpv6} ]`) : null;
this.hostLocalIpv4.forEach(n => {
return console.log(`LocalIpv4[ ${n.address}]`);
});
this.hostGlobalIpV6 ? console.log(`GlobalIpv6[ ${this.hostGlobalIpV6} ]`) : null;
this.hostGlobalIpV4 ? console.log(`GlobalIpv4[ ${this.hostGlobalIpV4} ]`) : null;
const domain = data;
if (!domain)
return console.log(`[${gateWay.serverIp} : ${gateWay.serverPort}] Gateway connect Error!`);
console.log(`[${gateWay.serverIp} : ${gateWay.serverPort}] Gateway connect success!`);
console.log('****************************************');
});
};
const gateway = new gateWay(serverIp, serverPort, password);
this.getGlobalIp(gateway);
const server = Net.createServer(socket => {
const ip = socket.remoteAddress;
const isWhiteIp = this.whiteIpList.find(n => { return n === ip; }) ? true : false;
const isLocalIp = Ip.isPrivate(ip);
socket.once('data', (data) => {
if (!isWhiteIp) {
console.log('! isWhiteIp', data.toString('utf8'));
if (testLogin(data, this.securityPath)) {
this.whiteIpList.push(ip);
this.saveWhiteIpList();
return socket.end(this.getPac(ip, port.toString()));
}
return socket.end();
}
switch (data.readUInt8(0)) {
case 0x4:
return console.log('SOCK4 connect');
case 0x5:
console.log('socks5 connect');
return new socks5(socket);
default:
return httpProxy(socket, data, useGatWay, this.hostGlobalIpV6 ? true : false, connectHostTimeOut, domainListPool, gateway, checkAgainTimeOut, domainBlackList);
}
});
socket.on('error', err => {
console.log(`[${ip}] socket.on error`, err.message);
});
});
server.on('error', err => {
console.log('proxy server :', err);
return process.exit(1);
});
server.listen(port, () => {
console.log('****************************************');
return console.log('proxy start success on port :', port, 'security path = ', securityPath);
});
const serverTest = Net.createServer(socket => {
const ip = socket.remoteAddress;
const isWhiteIp = this.whiteIpList.find(n => { return n === ip; }) ? true : false;
const isLocalIp = Ip.isPrivate(ip);
socket.once('data', (data) => {
if (!isLocalIp && !isWhiteIp) {
if (testLogin(data, this.securityPath)) {
this.whiteIpList.push(ip);
this.saveWhiteIpList();
return socket.end(this.getPac(ip, port.toString()));
}
return socket.end();
}
console.log('new connect from test port!');
switch (data.readUInt8(0)) {
case 0x4:
return console.log('SOCK4 connect');
case 0x5:
console.log('socks5 connect');
return new socks5(socket);
default:
return httpProxyTest(socket, data, gateway);
}
});
socket.on('error', err => {
console.log(`[${ip}] test socket.on error`, err.message);
});
});
serverTest.on('error', err => {
console.log('test proxy server :', err);
return process.exit(1);
});
serverTest.listen(port + 1, () => {
console.log('****************************************');
return console.log('proxy start success on port :', port + 1, 'security path = ', securityPath);
});
}
saveWhiteIpList() {
if (this.whiteIpList.length > 0)
Fs.writeFile(Path.join(__dirname, whiteIpFile), JSON.stringify(this.whiteIpList), { encoding: 'utf8' }, err => {
if (err) {
return console.log(`saveWhiteIpList save file error : ${err.message}`);
}
});
}
isHostIp(ip) {
if (Net.isIPv4(ip)) {
if (Ip.address) {
}
}
}
isLocalRequest(buffer, path) {
const header = new httpProxy_1.default(buffer);
const ip = header.Url.hostname;
if (Net.isIP(ip)) {
if (!Ip.isPrivate(ip) || !this.isHostIp(ip)) {
return false;
}
if (testLogin(header.buffer, path)) {
return true;
}
return null;
}
return false;
}
getPac(remoteIp, port) {
const ip6 = Net.isIP(remoteIp);
const hostIp = Ip.isPrivate(remoteIp) ? ip6 === 6 ? this.hostLocalIpv6 : Nekudo.getLocalNetWorkIp(this.hostLocalIpv4, remoteIp) : ip6 === 6 ? this.hostGlobalIpV6 : this.hostGlobalIpV4;
const FindProxyForURL = `function FindProxyForURL ( url, host ) {return SOCKS5 ${hostIp}:${port};}`;
return _HTTP_200(FindProxyForURL);
}
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = proxyServer;