UNPKG

portmp

Version:

port mapping. A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet. support TCP & UDP

1,453 lines (1,407 loc) 144 kB
#!/usr/bin/env node 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var require$$3 = require('fs'); var require$$0 = require('events'); var require$$1 = require('net'); var require$$0$1 = require('dgram'); var require$$1$1 = require('child_process'); var require$$2 = require('path'); var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; var cli = {}; var Server = {}; var TCPPacket$1 = {}; // 处理TCP粘包的问题 Object.defineProperty(TCPPacket$1, "__esModule", { value: true }); TCPPacket$1.TCPDataPacket = TCPPacket$1.TCPBufferHandler = TCPPacket$1.TCPPacket = void 0; class TCPPacket { GenTCPBuffer() { let l = 8; if (this.Data != null) { l += this.Data.length; } let buffer = Buffer.allocUnsafe(l); buffer.writeUInt32LE(l, 0); buffer.writeUInt32LE(this.Cmd, 4); if (this.Data != null) { this.Data.copy(buffer, 8, 0); } return buffer; } GetJsonData() { if (this.Data) { let jsonStr = this.Data.toString('utf8'); return JSON.parse(jsonStr); } return null; } SetJsonData(obj) { let jsonStr = JSON.stringify(obj); this.Data = Buffer.from(jsonStr, 'utf8'); } } TCPPacket$1.TCPPacket = TCPPacket; class TCPBufferHandler { constructor() { this.recvdBuffer = null; } put(buffer) { if (this.recvdBuffer != null) { this.recvdBuffer = Buffer.concat([this.recvdBuffer, buffer], this.recvdBuffer.length + buffer.length); } else { this.recvdBuffer = buffer; } } tryGetTCPPacket() { if (this.recvdBuffer == null || this.recvdBuffer.length == 0) { return null; } if (this.recvdBuffer.length < 4) { return null; } var packetDataLength = this.recvdBuffer.readUInt32LE(0); if (this.recvdBuffer.length < packetDataLength) { return null; } let packet = new TCPPacket(); packet.Length = packetDataLength; packet.Cmd = this.recvdBuffer.readUInt32LE(4); let dataLength = packetDataLength - 8; if (dataLength > 0) { let data = this.recvdBuffer.subarray(8, 8 + dataLength); packet.Data = data; } let remainLength = this.recvdBuffer.length - packetDataLength; if (remainLength == 0) { this.recvdBuffer = null; } else { let data = this.recvdBuffer.subarray(packetDataLength); this.recvdBuffer = data; } return packet; } } TCPPacket$1.TCPBufferHandler = TCPBufferHandler; class TCPDataPacket { UnSerialize(data) { if (data.length >= 8) { this.mappingId = data.readUInt32LE(0); this.pipeId = data.readUInt32LE(4); if (data.length > 8) { this.buffer = data.subarray(8); } } } Serialize() { let length = 8; if (this.buffer) { length += this.buffer.length; } let data = Buffer.allocUnsafe(length); data.writeUint32LE(this.mappingId, 0); data.writeUint32LE(this.pipeId, 4); if (this.buffer && this.buffer.length > 0) { this.buffer.copy(data, 8, 0); } return data; } } TCPPacket$1.TCPDataPacket = TCPDataPacket; var TCPServer$1 = {}; var once$1 = {exports: {}}; // Returns a wrapper function that returns a wrapped callback // The wrapper function should do some stuff, and return a // presumably different callback function. // This makes sure that own properties are retained, so that // decorations and such are not lost along the way. var wrappy_1 = wrappy$1; function wrappy$1 (fn, cb) { if (fn && cb) return wrappy$1(fn)(cb) if (typeof fn !== 'function') throw new TypeError('need wrapper function') Object.keys(fn).forEach(function (k) { wrapper[k] = fn[k]; }); return wrapper function wrapper() { var args = new Array(arguments.length); for (var i = 0; i < args.length; i++) { args[i] = arguments[i]; } var ret = fn.apply(this, args); var cb = args[args.length-1]; if (typeof ret === 'function' && ret !== cb) { Object.keys(cb).forEach(function (k) { ret[k] = cb[k]; }); } return ret } } var wrappy = wrappy_1; once$1.exports = wrappy(once); once$1.exports.strict = wrappy(onceStrict); once.proto = once(function () { Object.defineProperty(Function.prototype, 'once', { value: function () { return once(this) }, configurable: true }); Object.defineProperty(Function.prototype, 'onceStrict', { value: function () { return onceStrict(this) }, configurable: true }); }); function once (fn) { var f = function () { if (f.called) return f.value f.called = true; return f.value = fn.apply(this, arguments) }; f.called = false; return f } function onceStrict (fn) { var f = function () { if (f.called) throw new Error(f.onceError) f.called = true; return f.value = fn.apply(this, arguments) }; var name = fn.name || 'Function wrapped with `once`'; f.onceError = name + " shouldn't be called more than once"; f.called = false; return f } var onceExports = once$1.exports; var __awaiter$9 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault$7 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(TCPServer$1, "__esModule", { value: true }); TCPServer$1.TCPSession = TCPServer$1.TCPServer = TCPServer$1.TCPOptions = void 0; const events_1$4 = __importDefault$7(require$$0); const net_1$1 = __importDefault$7(require$$1); const once_1$2 = __importDefault$7(onceExports); const TCPPacket_1$5 = TCPPacket$1; class TCPOptions { constructor() { this.usePacket = false; } } TCPServer$1.TCPOptions = TCPOptions; class TCPServer extends events_1$4.default { constructor(options) { super(); this.options = options; } setServer(port) { this.port = port; } start() { return __awaiter$9(this, void 0, void 0, function* () { let promise = new Promise((resolve, reject) => { resolve = (0, once_1$2.default)(resolve); let server = this.server = new net_1$1.default.Server(); server.on('listening', () => { // 监听成功 resolve(true); }); server.on('error', (err) => { // 监听发生错误 resolve(false); }); server.on('close', () => { // 关闭的时候 this.emit('close'); }); server.on('connection', (socket) => { // 新连接 let session = new TCPSession(this.options, socket); this.emit('newConnect', session); }); // server.on('drop', (data?: net.DropArgument) => { // // 新连接被丢弃 什么都不处理 // }); server.listen(this.port); }); return promise; }); } close() { if (this.server) { let server = this.server; this.server = null; server.close(); } } on(...args) { super.on.call(this, ...args); return this; } } TCPServer$1.TCPServer = TCPServer; class TCPSession extends events_1$4.default { constructor(options, socket) { super(); this.isAuthed = false; this.socket = socket; this.options = options; if (this.options.usePacket) { this.initTCPBufferHandler(); } socket.on("error", (error) => { // 发生错误了 this.close(); }); socket.on("close", () => { // 关闭了 this.close(); }); socket.on("end", () => { // 对方说结束了 this.close(); }); socket.on("timeout", () => { // 超时了 需要手动关闭链接 this.close(); }); socket.on("data", (data) => { // 有数据来了 this.onReceiveData(data); }); } initTCPBufferHandler() { this.bufferHandler = new TCPPacket_1$5.TCPBufferHandler(); } start() { return __awaiter$9(this, void 0, void 0, function* () { return true; }); } close() { if (this.socket) { let socket = this.socket; this.socket = null; socket.end(); socket.destroy(); this.emit('close'); } } write(buffer) { if (buffer) if (this.socket) this.socket.write(buffer); } writePacket(packet) { if (packet) this.write(packet.GenTCPBuffer()); } onReceiveData(data) { this.emit('data', data); if (this.bufferHandler) { this.bufferHandler.put(data); while (true) { let packet = this.bufferHandler.tryGetTCPPacket(); if (packet) this.emit('packet', packet); else break; } } } on(...args) { super.on.call(this, ...args); return this; } } TCPServer$1.TCPSession = TCPSession; var PortMappingManager$1 = {}; var Pipe$1 = {}; var __awaiter$8 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault$6 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(Pipe$1, "__esModule", { value: true }); Pipe$1.Pipe = void 0; const events_1$3 = __importDefault$6(require$$0); var EventSide; (function (EventSide) { EventSide[EventSide["Left"] = 1] = "Left"; EventSide[EventSide["Right"] = 2] = "Right"; })(EventSide || (EventSide = {})); class EventInfo { } class EventQueue { constructor() { this.queue = []; } get length() { return this.queue.length; } EnQueue(evnet) { this.queue.push(evnet); } DeQueue() { return this.queue.shift(); } Clear() { this.queue = []; } } class Pipe extends events_1$3.default { constructor(left, right) { super(); this.isReady = false; this.eventQueue = new EventQueue(); this.left = left; this.right = right; } link() { return __awaiter$8(this, void 0, void 0, function* () { this.left.on('close', () => { let eventInfo = new EventInfo(); eventInfo.side = EventSide.Left; eventInfo.name = 'close'; this.enQueue(eventInfo); }); this.left.on('data', (buffer) => { let eventInfo = new EventInfo(); eventInfo.side = EventSide.Left; eventInfo.name = 'data'; eventInfo.buffer = buffer; this.enQueue(eventInfo); }); this.right.on('close', () => { let eventInfo = new EventInfo(); eventInfo.side = EventSide.Right; eventInfo.name = 'close'; this.enQueue(eventInfo); }); this.right.on('data', (buffer) => { let eventInfo = new EventInfo(); eventInfo.side = EventSide.Right; eventInfo.name = 'data'; eventInfo.buffer = buffer; this.enQueue(eventInfo); }); let leftSucc = yield this.left.start(); if (leftSucc) { let rightSucc = yield this.right.start(); if (rightSucc) { this.isReady = true; this.onReady(); return true; } } this.close(); return false; }); } onReady() { this.tryExecQueue(); } enQueue(evnet) { this.eventQueue.EnQueue(evnet); this.tryExecQueue(); } tryExecQueue() { while (true) { if (this.eventQueue.length == 0) { break; } if (!this.isReady) { break; } if (!this.left || !this.right) { break; } let evnet = this.eventQueue.DeQueue(); if (evnet.side == EventSide.Left) { if (evnet.name == 'close') { this.close(); } else if (evnet.name == 'data') { this.right.write(evnet.buffer); } } else if (evnet.side == EventSide.Right) { if (evnet.name == 'close') { this.close(); } else if (evnet.name == 'data') { this.left.write(evnet.buffer); } } } } close() { let left = this.left; let right = this.right; if (left && right) { this.left = null; this.right = null; left.close(); right.close(); this.emit('close'); } } onReceiveTunnleData(buffer) { let tunnleWrapper = this.tunnleWrapper; tunnleWrapper.onReceiveData(buffer); } } Pipe$1.Pipe = Pipe; var TCPClient$1 = {}; var __awaiter$7 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault$5 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(TCPClient$1, "__esModule", { value: true }); TCPClient$1.TCPClient = void 0; const events_1$2 = __importDefault$5(require$$0); const net_1 = __importDefault$5(require$$1); const once_1$1 = __importDefault$5(onceExports); const TCPPacket_1$4 = TCPPacket$1; class TCPClient extends events_1$2.default { constructor(options) { super(); this.isAuthed = false; this.connected = false; this.socket = new net_1.default.Socket(); this.options = options; if (this.options.usePacket) { this.initTCPBufferHandler(); } } setClient(port, address = '127.0.0.1') { this.port = port; this.address = address; } initTCPBufferHandler() { this.bufferHandler = new TCPPacket_1$4.TCPBufferHandler(); } start() { return __awaiter$7(this, void 0, void 0, function* () { let promise = new Promise((resolve, reject) => { resolve = (0, once_1$1.default)(resolve); if (this.connected) { resolve(false); return; } if (!this.socket) { resolve(false); return; } this.connected = true; let socket = this.socket; socket.on("error", (error) => { // 发生错误了 this.close(); resolve(false); }); socket.on("close", () => { // 关闭了 this.close(); }); socket.on("end", () => { // 对方说结束了 this.close(); }); socket.on("timeout", () => { // 超时了 需要手动关闭链接 this.close(); }); socket.on("data", (data) => { // 有数据来了 this.onReceiveData(data); }); socket.on("ready", () => { // 连接成功 resolve(true); }); socket.connect(this.port, this.address); }); return promise; }); } close() { if (this.socket) { let socket = this.socket; this.socket = null; socket.end(); socket.destroy(); this.emit('close'); } } write(buffer) { if (buffer) if (this.socket) this.socket.write(buffer); } writePacket(packet) { if (packet) this.write(packet.GenTCPBuffer()); } onReceiveData(data) { this.emit('data', data); if (this.bufferHandler) { this.bufferHandler.put(data); while (true) { let packet = this.bufferHandler.tryGetTCPPacket(); if (packet) this.emit('packet', packet); else break; } } } on(...args) { super.on.call(this, ...args); return this; } } TCPClient$1.TCPClient = TCPClient; var CMD$1 = {}; Object.defineProperty(CMD$1, "__esModule", { value: true }); CMD$1.CMD = void 0; var CMD; (function (CMD) { CMD[CMD["Hello"] = 1] = "Hello"; CMD[CMD["Ping"] = 2] = "Ping"; CMD[CMD["Heartbeat"] = 3] = "Heartbeat"; CMD[CMD["New_PortMapping"] = 4] = "New_PortMapping"; CMD[CMD["TCP_Connected"] = 5] = "TCP_Connected"; CMD[CMD["TCP_Data"] = 6] = "TCP_Data"; CMD[CMD["TCP_Closed"] = 7] = "TCP_Closed"; })(CMD || (CMD$1.CMD = CMD = {})); var UDPSocket = {}; var __awaiter$6 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault$4 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(UDPSocket, "__esModule", { value: true }); UDPSocket.UDPServer = UDPSocket.UDPSessionManager = UDPSocket.UDPSession = UDPSocket.UDPClient = void 0; const events_1$1 = __importDefault$4(require$$0); const once_1 = __importDefault$4(onceExports); class UDPClient extends events_1$1.default { constructor(socket) { super(); this.socket = socket; } setClient(port, address = '127.0.0.1') { this.port = port; this.address = address; } start() { return __awaiter$6(this, void 0, void 0, function* () { if (!this.socket) { return false; } let promise = new Promise((resolve, reject) => { resolve = (0, once_1.default)(resolve); reject = (0, once_1.default)(reject); let socket = this.socket; socket.on("error", (error) => { console.error(error); this.close(); resolve(false); }); socket.on("listening", () => { resolve(true); }); socket.on("close", () => { this.close(); }); socket.on("message", (data, rinfo) => { this.onData(data, rinfo); }); socket.bind(0); // 让系统分配localport }); return promise; }); } onData(buffer, rinfo) { if (rinfo.address == this.address && rinfo.port == this.port) { this.onReceiveData(buffer); } } onReceiveData(buffer) { if (buffer) this.emit('data', buffer); } write(buffer) { if (buffer && this.socket) this.socket.send(buffer, this.port, this.address); } close() { let socket = this.socket; if (socket) { this.socket = null; socket.close(); this.emit('close'); } } on(...args) { super.on.call(this, ...args); return this; } once(...args) { super.once.call(this, ...args); return this; } } UDPSocket.UDPClient = UDPClient; class UDPSession extends events_1$1.default { constructor() { super(...arguments); this.closed = false; } start() { return __awaiter$6(this, void 0, void 0, function* () { return true; }); } onReceiveData(buffer) { if (!this.closed) { this.activeTime = Date.now(); this.emit('data', buffer); } } write(buffer) { if (!this.closed) { this.activeTime = Date.now(); this.server.write(buffer, this.port, this.address); } } close() { if (!this.closed) { this.closed = true; this.emit('close'); } } on(...args) { super.on.call(this, ...args); return this; } once(...args) { super.once.call(this, ...args); return this; } } UDPSocket.UDPSession = UDPSession; class UDPSessionManager { constructor() { this.mapByStr = new Map(); this.intervalTimer = null; } AddNew(udpSession) { this.mapByStr.set(udpSession.ipPort, udpSession); } GetByIPPort(ipPort) { return this.mapByStr.get(ipPort); } Del(udpSession) { this.mapByStr.delete(udpSession.ipPort); } startCheck() { this.intervalTimer = setInterval(() => { this.checkDeadSession(); }, 1000); } stopCheck() { if (this.intervalTimer) { clearInterval(this.intervalTimer); this.intervalTimer = null; } } checkDeadSession() { let toCloses = []; let now = Date.now(); for (const session of this.mapByStr.values()) { let dt = now - session.activeTime; if (dt > 10) { // 5s toCloses.push(session); } } for (const session of toCloses) { session.close(); } } } UDPSocket.UDPSessionManager = UDPSessionManager; class UDPServer extends events_1$1.default { constructor(socket) { super(); this.sessionManager = new UDPSessionManager(); this.socket = socket; } setServer(port) { this.port = port; } start() { return __awaiter$6(this, void 0, void 0, function* () { let promise = new Promise((resolve, reject) => { resolve = (0, once_1.default)(resolve); reject = (0, once_1.default)(reject); let socket = this.socket; socket.on("error", (error) => { console.error(error); this.close(); resolve(false); }); socket.on("listening", () => { this.onReady(); resolve(true); }); socket.on("close", () => { this.close(); }); socket.on("message", (data, rinfo) => { this.onData(data, rinfo); }); socket.bind(this.port); }); return promise; }); } onReady() { this.sessionManager.startCheck(); this.emit('ready'); } onData(buffer, rinfo) { let ipPort = rinfo.address + rinfo.port; let session = this.sessionManager.GetByIPPort(ipPort); if (!session) { session = new UDPSession(); session.server = this; session.ipPort = ipPort; session.address = rinfo.address; session.port = rinfo.port; session.once('close', () => { this.sessionManager.Del(session); }); this.sessionManager.AddNew(session); this.emit('newConnect', session); } session.onReceiveData(buffer); this.emit('data', session, buffer, rinfo); } write(buffer, port, address) { if (buffer && this.socket) this.socket.send(buffer, port, address); } close() { if (!this.socket) { let socket = this.socket; this.socket = null; socket.close(); this.sessionManager.stopCheck(); this.emit('close'); } } on(...args) { super.on.call(this, ...args); return this; } once(...args) { super.once.call(this, ...args); return this; } } UDPSocket.UDPServer = UDPServer; var TCPTunnleWrapper$1 = {}; var __awaiter$5 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault$3 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(TCPTunnleWrapper$1, "__esModule", { value: true }); TCPTunnleWrapper$1.TCPTunnleWrapper = void 0; const events_1 = __importDefault$3(require$$0); const CMD_1$3 = CMD$1; const TCPPacket_1$3 = TCPPacket$1; class TCPTunnleWrapper extends events_1.default { constructor(packetable, mappingId, pipeId) { super(); this.packetable = packetable; this.mappingId = mappingId; this.pipeId = pipeId; } onReceiveData(buffer) { if (this.packetable) { this.emit('data', buffer); } } write(buffer) { if (buffer && this.packetable) { if (typeof buffer === 'string') { buffer = Buffer.from(buffer); } let packet = new TCPPacket_1$3.TCPPacket(); packet.Cmd = CMD_1$3.CMD.TCP_Data; let dataPacket = new TCPPacket_1$3.TCPDataPacket(); dataPacket.mappingId = this.mappingId; dataPacket.pipeId = this.pipeId; dataPacket.buffer = buffer; packet.Data = dataPacket.Serialize(); this.packetable.writePacket(packet); } } close() { if (this.packetable) { let packetable = this.packetable; this.packetable = null; this.emitCloseEvent(packetable); } } emitCloseEvent(packetable) { let packet = new TCPPacket_1$3.TCPPacket(); packet.Cmd = CMD_1$3.CMD.TCP_Closed; let dataPacket = new TCPPacket_1$3.TCPDataPacket(); dataPacket.mappingId = this.mappingId; dataPacket.pipeId = this.pipeId; packet.Data = dataPacket.Serialize(); packetable.writePacket(packet); this.emit('close'); } start() { return __awaiter$5(this, void 0, void 0, function* () { return true; }); } on(...args) { super.on.call(this, ...args); return this; } } TCPTunnleWrapper$1.TCPTunnleWrapper = TCPTunnleWrapper; var __awaiter$4 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault$2 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(PortMappingManager$1, "__esModule", { value: true }); PortMappingManager$1.PortMappingManager = PortMappingManager$1.PortMapping = PortMappingManager$1.UID = void 0; const dgram_1$1 = __importDefault$2(require$$0$1); const TCPServer_1$3 = TCPServer$1; const Pipe_1$1 = Pipe$1; const TCPClient_1$2 = TCPClient$1; const CMD_1$2 = CMD$1; const TCPPacket_1$2 = TCPPacket$1; const UDPSocket_1$1 = UDPSocket; const TCPTunnleWrapper_1 = TCPTunnleWrapper$1; class UID { static GetUID() { return UID.uid++; } } PortMappingManager$1.UID = UID; UID.uid = 1; class PortMapping { constructor(isServer, tunnel, forwardInfo) { this.map = new Map(); this.isServer = isServer; this.tunnel = tunnel; this.forwardInfo = forwardInfo; } start() { return __awaiter$4(this, void 0, void 0, function* () { if (!this.isServer) { return true; } if (this.forwardInfo.type == 'tcp') { let options = new TCPServer_1$3.TCPOptions(); options.usePacket = false; let tcpServer = new TCPServer_1$3.TCPServer(options); tcpServer.setServer(this.forwardInfo.fromPort); let succ = yield tcpServer.start(); if (!succ) { console.error('本地代理启动失败!'); } else { this.tcpServer = tcpServer; console.log(`tcp proxy server port:${this.forwardInfo.fromPort}`); tcpServer.on('newConnect', (rometeSession) => { this.onServerNewConnect(rometeSession); }); } return succ; } else { let udpServer = new UDPSocket_1$1.UDPServer(dgram_1$1.default.createSocket('udp4')); udpServer.setServer(this.forwardInfo.fromPort); let succ = yield udpServer.start(); if (!succ) { console.error('本地代理启动失败!'); } else { this.udpServer = udpServer; console.log(`udp proxy server port:${this.forwardInfo.fromPort}`); udpServer.on('newConnect', (rometeSession) => { this.onServerNewConnect(rometeSession); }); } return succ; } }); } onServerNewConnect(rometeSession) { return __awaiter$4(this, void 0, void 0, function* () { let pipeId = UID.GetUID(); let tcpPacket = new TCPPacket_1$2.TCPPacket(); tcpPacket.Cmd = CMD_1$2.CMD.TCP_Connected; let dataPacket = new TCPPacket_1$2.TCPDataPacket(); dataPacket.mappingId = this.forwardInfo.mappingId; dataPacket.pipeId = pipeId; tcpPacket.Data = dataPacket.Serialize(); this.tunnel.writePacket(tcpPacket); let tcpTunnleWrapper = new TCPTunnleWrapper_1.TCPTunnleWrapper(this.tunnel, this.forwardInfo.mappingId, pipeId); let pipe = new Pipe_1$1.Pipe(tcpTunnleWrapper, rometeSession); pipe.tunnleWrapper = tcpTunnleWrapper; pipe.on('close', () => { this.connectionClose(pipeId); }); this.map.set(pipeId, pipe); let succ = yield pipe.link(); if (!succ) { console.error(`远程代理 本地session创建失败! pipeId=${pipeId}`); } }); } onClientNewConnect(mappingId, pipeId) { return __awaiter$4(this, void 0, void 0, function* () { if (this.isServer) { return false; } if (this.map.has(pipeId)) { return false; } if (this.forwardInfo.type == 'tcp') { let options = new TCPServer_1$3.TCPOptions(); options.usePacket = false; let leftSession = new TCPClient_1$2.TCPClient(options); leftSession.setClient(this.forwardInfo.targetPort, this.forwardInfo.targetAddr); let tcpTunnleWrapper = new TCPTunnleWrapper_1.TCPTunnleWrapper(this.tunnel, mappingId, pipeId); let pipe = new Pipe_1$1.Pipe(leftSession, tcpTunnleWrapper); pipe.tunnleWrapper = tcpTunnleWrapper; pipe.on('close', () => { this.connectionClose(pipeId); }); this.map.set(pipeId, pipe); let succ = yield pipe.link(); if (!succ) { console.error(`远程代理 本地session创建失败! id=${pipeId}`); } return succ; } else { let leftSession = new UDPSocket_1$1.UDPClient(dgram_1$1.default.createSocket('udp4')); leftSession.setClient(this.forwardInfo.targetPort, this.forwardInfo.targetAddr); let tcpTunnleWrapper = new TCPTunnleWrapper_1.TCPTunnleWrapper(this.tunnel, mappingId, pipeId); let pipe = new Pipe_1$1.Pipe(leftSession, tcpTunnleWrapper); pipe.tunnleWrapper = tcpTunnleWrapper; pipe.on('close', () => { this.connectionClose(pipeId); }); this.map.set(pipeId, pipe); let succ = yield pipe.link(); if (!succ) { console.error(`远程代理 本地session创建失败! id=${pipeId}`); } return succ; } }); } connectionClose(pipeId) { this.map.delete(pipeId); } onReceiveTunnleData(buffer, pipeId) { if (this.map.has(pipeId)) { var pipe = this.map.get(pipeId); pipe.onReceiveTunnleData(buffer); } } onReceiveTunnleClose(pipeId) { if (this.map.has(pipeId)) { var pipe = this.map.get(pipeId); pipe.close(); } } close() { let pipes = []; for (const item of this.map.values()) { pipes.push(item); } this.map = new Map(); // clear for (const item of pipes) { item.close(); } if (this.tcpServer) { let server = this.tcpServer; this.tcpServer = null; server.close(); } if (this.udpServer) { let server = this.udpServer; this.udpServer = null; server.close(); } } } PortMappingManager$1.PortMapping = PortMapping; class PortMappingManager { constructor() { this.portMappingMap = new Map(); } newPortMapping(tcpSession, mappingId, portMapping) { return __awaiter$4(this, void 0, void 0, function* () { if (!this.portMappingMap.has(tcpSession)) { this.portMappingMap.set(tcpSession, new Map()); } this.portMappingMap.get(tcpSession).set(mappingId, portMapping); let succ = yield portMapping.start(); return succ; }); } onRecvTunnleConnect(tcpSession, mappingId, pipeId) { let map = this.portMappingMap.get(tcpSession); if (map) { let portMapping = map.get(mappingId); if (portMapping) { portMapping.onClientNewConnect(mappingId, pipeId); } } } onRecvTunnleClose(tcpSession, mappingId, pipeId) { let map = this.portMappingMap.get(tcpSession); if (map) { let portMapping = map.get(mappingId); if (portMapping) { portMapping.onReceiveTunnleClose(pipeId); } } } onRecvTunnleData(tcpSession, mappingId, pipeId, buffer) { let map = this.portMappingMap.get(tcpSession); if (map) { let portMapping = map.get(mappingId); if (portMapping) { portMapping.onReceiveTunnleData(buffer, pipeId); } } } close(tcpSession) { let map = this.portMappingMap.get(tcpSession); if (map) { this.portMappingMap.delete(tcpSession); for (const portMapping of map.values()) { portMapping.close(); } } } } PortMappingManager$1.PortMappingManager = PortMappingManager; var ForwardInfo$1 = {}; var Utils = {}; Object.defineProperty(Utils, "__esModule", { value: true }); Utils.hashCode = void 0; function hashCode(strKey) { var hash = 0; if (strKey != null) { for (var i = 0; i < strKey.length; i++) { hash = hash * 31 + strKey.charCodeAt(i); hash = uintValue(hash); } } return hash; } Utils.hashCode = hashCode; function uintValue(num) { // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators#bitwise_shift_operators // 位运算符规则 // 1.浮点数去掉小数后变成整数 // 2.将整数取低32位变成int32 // 3.>>> 无符号右移 返回的结果是uint32 // 4.其他位运算符 返回的结果是int32 num &= 0xFFFFFFFF; // int32 return num >>> 0; // uint32 } Object.defineProperty(ForwardInfo$1, "__esModule", { value: true }); ForwardInfo$1.ForwardInfo = void 0; const Utils_1 = Utils; class ForwardInfo { constructor(jsonObj) { this.mappingId = 0; this.isLocalForward = false; this.from(jsonObj); } from(jsonObj) { if (jsonObj) { Object.assign(this, jsonObj); this.mappingId = (0, Utils_1.hashCode)(this.type + this.targetAddr + this.targetPort + this.fromPort); } } static From(jsonObj) { return new ForwardInfo(jsonObj); } } ForwardInfo$1.ForwardInfo = ForwardInfo; var __awaiter$3 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(Server, "__esModule", { value: true }); Server.startServer = void 0; const TCPPacket_1$1 = TCPPacket$1; const TCPServer_1$2 = TCPServer$1; const PortMappingManager_1$1 = PortMappingManager$1; const CMD_1$1 = CMD$1; const ForwardInfo_1$1 = ForwardInfo$1; let startServer = (port = 7666, validKeys = []) => __awaiter$3(void 0, void 0, void 0, function* () { let mappingManager = new PortMappingManager_1$1.PortMappingManager(); let options = new TCPServer_1$2.TCPOptions(); options.usePacket = true; let tcpServer = new TCPServer_1$2.TCPServer(options); tcpServer.setServer(port); tcpServer.on("newConnect", (tcpSession) => { tcpSession.on('packet', (packet) => { if (packet.Cmd == CMD_1$1.CMD.Hello) { if (validKeys.length > 0) { let hello = packet.GetJsonData(); if (hello && hello.authKey) { if (validKeys.includes(hello.authKey)) { tcpSession.isAuthed = true; } else { tcpSession.isAuthed = false; } } } else { tcpSession.isAuthed = true; } let resPacket = new TCPPacket_1$1.TCPPacket(); resPacket.Cmd = CMD_1$1.CMD.Hello; resPacket.SetJsonData({ isAuthed: tcpSession.isAuthed }); tcpSession.writePacket(resPacket); } if (!tcpSession.isAuthed) { tcpSession.close(); return; } if (packet.Cmd == CMD_1$1.CMD.New_PortMapping) { let forwardInfos = packet.GetJsonData(); forwardInfos = forwardInfos.map((v) => ForwardInfo_1$1.ForwardInfo.From(v)); let isServer = true; for (const forwardInfo of forwardInfos) { let portMapping = new PortMappingManager_1$1.PortMapping(isServer, tcpSession, forwardInfo); mappingManager.newPortMapping(tcpSession, forwardInfo.mappingId, portMapping); } } else if (packet.Cmd == CMD_1$1.CMD.TCP_Closed) { let dataPacket = new TCPPacket_1$1.TCPDataPacket(); dataPacket.UnSerialize(packet.Data); mappingManager.onRecvTunnleClose(tcpSession, dataPacket.mappingId, dataPacket.pipeId); } else if (packet.Cmd == CMD_1$1.CMD.TCP_Data) { let dataPacket = new TCPPacket_1$1.TCPDataPacket(); dataPacket.UnSerialize(packet.Data); mappingManager.onRecvTunnleData(tcpSession, dataPacket.mappingId, dataPacket.pipeId, dataPacket.buffer); } }); tcpSession.on('close', () => { mappingManager.close(tcpSession); }); }); return yield tcpServer.start(); }); Server.startServer = startServer; var Client = {}; var __awaiter$2 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(Client, "__esModule", { value: true }); Client.startClient = void 0; const CMD_1 = CMD$1; const TCPPacket_1 = TCPPacket$1; const TCPServer_1$1 = TCPServer$1; const TCPClient_1$1 = TCPClient$1; const PortMappingManager_1 = PortMappingManager$1; let startClient = (forwardInfos, remotePort = 7666, remoteAddr = '127.0.0.1', authKey = '') => __awaiter$2(void 0, void 0, void 0, function* () { let mappingManager = new PortMappingManager_1.PortMappingManager(); let options = new TCPServer_1$1.TCPOptions(); options.usePacket = true; let tcpClient = new TCPClient_1$1.TCPClient(options); tcpClient.setClient(remotePort, remoteAddr); { tcpClient.on('close', () => { mappingManager.close(tcpClient); }); tcpClient.on('packet', (packet) => { if (packet.Cmd == CMD_1.CMD.Hello) { let hello = packet.GetJsonData(); if (hello && hello.isAuthed) { tcpClient.isAuthed = true; } else { tcpClient.isAuthed = false; } if (tcpClient.isAuthed) { let packet = new TCPPacket_1.TCPPacket(); packet.Cmd = CMD_1.CMD.New_PortMapping; packet.SetJsonData(forwardInfos); tcpClient.writePacket(packet); let isServer = false; for (const forwardInfo of forwardInfos) { let portMapping = new PortMappingManager_1.PortMapping(isServer, tcpClient, forwardInfo); mappingManager.newPortMapping(tcpClient, forwardInfo.mappingId, portMapping); } } } if (!tcpClient.isAuthed) { tcpClient.close(); return; } if (packet.Cmd == CMD_1.CMD.New_PortMapping) { packet.GetJsonData(); } else if (packet.Cmd == CMD_1.CMD.TCP_Connected) { let dataPacket = new TCPPacket_1.TCPDataPacket(); dataPacket.UnSerialize(packet.Data); mappingManager.onRecvTunnleConnect(tcpClient, dataPacket.mappingId, dataPacket.pipeId); } else if (packet.Cmd == CMD_1.CMD.TCP_Closed) { let dataPacket = new TCPPacket_1.TCPDataPacket(); dataPacket.UnSerialize(packet.Data); mappingManager.onRecvTunnleClose(tcpClient, dataPacket.mappingId, dataPacket.pipeId); } else if (packet.Cmd == CMD_1.CMD.TCP_Data) { let dataPacket = new TCPPacket_1.TCPDataPacket(); dataPacket.UnSerialize(packet.Data); mappingManager.onRecvTunnleData(tcpClient, dataPacket.mappingId, dataPacket.pipeId, dataPacket.buffer); } }); } let succ = yield tcpClient.start(); if (succ) { let packet = new TCPPacket_1.TCPPacket(); packet.Cmd = CMD_1.CMD.Hello; packet.SetJsonData({ authKey: authKey }); tcpClient.writePacket(packet); let intervalTimer = setInterval(() => { let packet = new TCPPacket_1.TCPPacket(); packet.Cmd = CMD_1.CMD.Heartbeat; packet.SetJsonData({ authKey: authKey }); tcpClient.writePacket(packet); }, 1000); tcpClient.on('close', () => { clearInterval(intervalTimer); }); } return succ; }); Client.startClient = startClient; var commander = {exports: {}}; var argument = {}; var error = {}; // @ts-check /** * CommanderError class * @class */ let CommanderError$1 = class CommanderError extends Error { /** * Constructs the CommanderError class * @param {number} exitCode suggested exit code which could be used with process.exit * @param {string} code an id string representing the error * @param {string} message human-readable description of the error * @constructor */ constructor(exitCode, code, message) { super(message); // properly capture stack trace in Node.js Error.captureStackTrace(this, this.constructor); this.name = this.constructor.name; this.code = code; this.exitCode = exitCode; this.nestedError = undefined; } }; /** * InvalidArgumentError class * @class */ let InvalidArgumentError$2 = class InvalidArgumentError extends CommanderError$1 { /** * Constructs the InvalidArgumentError class * @param {string} [message] explanation of why argument is invalid * @constructor */ constructor(message) { super(1, 'commander.invalidArgument', message); // properly capture stack trace in Node.js Error.captureSt