@kloak-it/tq-proxy
Version:
QT PROXY Server/Client
214 lines (213 loc) • 9.67 kB
JavaScript
;
/*!
* Copyright 2018 CoNET Technology Inc. All Rights Reserved.
*
* 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.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Compress = __importStar(require("./compressClient"));
const Net = __importStar(require("net"));
const res = __importStar(require("./res"));
const Stream = __importStar(require("stream"));
const Crypto = __importStar(require("crypto"));
const log_1 = require("../GateWay/log");
const safe_1 = __importDefault(require("colors/safe"));
const util_1 = require("util");
const Day = 1000 * 60 * 60 * 24;
const otherRequestForNet = (path, host, port, UserAgent) => {
if (path.length < 1024 + Math.round(Math.random() * 4000))
return `GET /${path} HTTP/1.1\r\n` +
`Host: ${host}${port !== 80 ? ':' + 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 /${Crypto.randomBytes(10 + Math.round(Math.random() * 1500)).toString('base64')} HTTP/1.1\r\n` +
`Host: ${host}${port !== 80 ? ':' + port : ''}\r\n` +
`User-Agent: ${UserAgent ? UserAgent : 'Mozilla/5.0'}\r\n\r\n` +
`Content-Length: ${path.length}\r\n\r\n` +
path + '\r\n\r\n';
};
class hostLookupResponse extends Stream.Writable {
constructor(CallBack) {
super();
this.CallBack = CallBack;
}
_write(chunk, enc, next) {
//console.log ( `hostLookupResponse _write come [${ chunk.toString()}]`)
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 {
request(str, gateway) {
return Buffer.from(otherRequestForNet(str, gateway.gateWayIpAddress, gateway.gateWayPort, this.userAgent));
}
getCurrentGateway() {
if (this.multipleGateway.length === 1) {
return this.multipleGateway[0];
}
if (++this.currentGatewayPoint > this.multipleGateway.length - 1) {
this.currentGatewayPoint = 0;
}
return this.multipleGateway[this.currentGatewayPoint];
}
constructor(multipleGateway, debug) {
this.multipleGateway = multipleGateway;
this.debug = debug;
this.userAgent = null;
this.currentGatewayPoint = 0;
this.RemoteServerDistroyed = false;
}
hostLookup(hostName, userAgent, CallBack) {
const _data = Buffer.from(JSON.stringify({ hostName: hostName }));
const gateway = this.getCurrentGateway();
const id = safe_1.default.blue(`hostLookup`);
const encrypt = new Compress.encryptStream(id, gateway.randomPassword, 3000, (str) => {
return this.request(str, gateway);
}, this.debug);
const finish = new hostLookupResponse(CallBack);
const httpBlock = new Compress.getDecryptClientStreamHttp(this.debug, id);
const decrypt = new Compress.decryptStream(gateway.randomPassword, id, this.debug);
(0, log_1.logger)(`try connect gateway server: [${gateway.gateWayIpAddress}:${gateway.gateWayPort}] password[${gateway.randomPassword}]`);
const _socket = Net.createConnection(gateway.gateWayPort, gateway.gateWayIpAddress, () => {
(0, log_1.logger)(`connected Gateway [${gateway.gateWayIpAddress}: ${gateway.gateWayPort}] doing encrypt.write ( _data )`);
encrypt.write(_data);
});
_socket.once('end', () => {
//console.log ( `_socket.once end!` )
});
_socket.once('error', err => {
return CallBack(err);
});
httpBlock.once('error', err => {
(0, log_1.logger)(`hostLookup httpBlock.on error`, err);
_socket.end(res._HTTP_502);
return CallBack(err);
});
decrypt.once('err', err => {
CallBack(err);
});
encrypt.pipe(_socket).pipe(httpBlock).pipe(decrypt).pipe(finish);
}
requestGetWay(requestObj, uuuu, userAgent, socket) {
// remote server was stoped
if (this.RemoteServerDistroyed) {
console.log(`requestGetWay this.RemoteServerDistroyed === true !`);
return socket.end(res._HTTP_404);
}
this.userAgent = userAgent;
const gateway = this.getCurrentGateway();
// remote gateway error
if (!gateway) {
return socket.end(res._HTTP_404);
}
let id = safe_1.default.yellow(`[${uuuu.uuid}]${uuuu.host}:${uuuu.port}->[Gateway ${gateway.gateWayIpAddress}:${gateway.gateWayPort}]`);
const decrypt = new Compress.decryptStream(gateway.randomPassword, id, this.debug);
const encrypt = new Compress.encryptStream(id, gateway.randomPassword, Math.random() * 500, (str) => {
return this.request(str, gateway);
}, this.debug);
const httpBlock = new Compress.getDecryptClientStreamHttp(this.debug, id);
httpBlock.once('error', err => {
socket.end(res._HTTP_404);
});
decrypt.once('error', err => {
(0, log_1.logger)(safe_1.default.red(`requestGetWay decrypt [${id}] on error [${err.message}]`));
socket.end(res._HTTP_404);
});
encrypt.once('end', () => {
//console.log (`encrypt.once end` )
socket.end(res._HTTP_404);
});
encrypt.once('error', err => {
console.log(`requestGetWay [${id}] encrypt.once error`, err);
socket.end(res._HTTP_404);
});
if (this.debug) {
(0, log_1.logger)(safe_1.default.red(`requestGetWay to [${gateway.gateWayIpAddress}:${gateway.gateWayPort}] for [${(0, util_1.inspect)(requestObj, false, 3, true)}]`));
(0, log_1.hexDebug)(Buffer.from(uuuu.buffer, 'base64'));
}
const connect = () => {
if (!encrypt.writable) {
return setTimeout(() => {
(0, log_1.logger)(`!encrypt.writable waiting 200ms`, (0, util_1.inspect)(requestObj, false, 3, true));
return connect();
}, 200);
}
const _socket = Net.createConnection(gateway.gateWayPort || 80, gateway.gateWayIpAddress, () => {
id = safe_1.default.blue(`[${_socket.localAddress}:${_socket.localPort}] `) + id;
if (encrypt && encrypt.writable) {
if (this.debug) {
(0, log_1.logger)(safe_1.default.red(`${id} success to Gateway! send data now.`));
(0, log_1.hexDebug)(Buffer.from(uuuu.buffer, 'base64'));
}
return encrypt.write(Buffer.from(JSON.stringify(uuuu), 'utf8'), () => {
socket.resume();
});
}
(0, log_1.logger)(safe_1.default.red(`encryptStream writable false!`), (0, util_1.inspect)(requestObj, false, 3, true));
return socket.end(res._HTTP_404);
});
_socket.once('error', err => {
(0, log_1.logger)(safe_1.default.red(`Gateway server [${gateway.gateWayIpAddress}] on error ${safe_1.default.grey(err.message)}`));
socket.end(res._HTTP_404);
});
_socket.once('end', () => {
(0, log_1.logger)(safe_1.default.blue(`Gateway ${uuuu.uuid} on end()`));
socket.destroy();
});
socket.pipe(encrypt).pipe(_socket).pipe(httpBlock).pipe(decrypt).pipe(socket);
};
return connect();
}
}
exports.default = gateWay;