UNPKG

@kloak-it/tq-proxy

Version:
212 lines (209 loc) 6.74 kB
"use strict"; /*! * 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. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.socket4Requests = exports.Requests = exports.Replies = exports.ATYP = exports.CMD = void 0; // ======================================================================= /* +----+-----+-------+------+----------+----------+ |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | X'00' | 1 | Variable | 2 | +----+-----+-------+------+----------+----------+ Where: o VER protocol version: X'05' o CMD o CONNECT X'01' o BIND X'02' o UDP ASSOCIATE X'03' o RSV RESERVED o ATYP address type of following address o IP V4 address: X'01' o DOMAINNAME: X'03' o IP V6 address: X'04' o DST.ADDR desired destination address o DST.PORT desired destination port in network octet order */ const connectRequest = Buffer.from('050100', 'hex'); exports.CMD = { CONNECT: 0x1, BIND: 0x2, UDP_ASSOCIATE: 0x3 }; exports.ATYP = { IP_V4: 0x1, DOMAINNAME: 0x03, IP_V6: 0x4 }; exports.Replies = { GRANTED: 0x0, GENERAL_FAILURE: 0x1, CONNECTION_NOT_ALLOWED_BY_RULESET: 0x2, NETWORK_UNREACHABLE: 0x3, HOST_UNREACHABLE: 0x4, CONNECTION_REFUSED_BY_DESTINATION_HOST: 0x5, TTL_EXPIRED: 0x6, COMMAND_NOT_SUPPORTED_or_PROTOCOL_ERROR: 0x7, ADDRESS_TYPE_NOT_SUPPORTED: 0x8 }; // state const STATE_VERSION = 0; const STATE_METHOD = 1; const STATE_REP_STATUS = 2; const STATE_REP_RSV = 3; const STATE_REP_ATYP = 4; const STATE_REP_BNDADDR = 5; const STATE_REP_BNDADDR_VARLEN = 6; const STATE_REP_BNDPORT = 7; // end stats // reply Buffer const reply_NO_AUTHENTICATION_REQUIRED = Buffer.from('0500', 'hex'); const reply_GSSAPI = Buffer.from('0501', 'hex'); const reply_USERNAME_PASSWORD = Buffer.from('0502', 'hex'); const reply_to_x7F_IANA_ASSIGNED = Buffer.from('0503', 'hex'); const reply_to_xFE_RESERVED_FOR_PRIVATE_METHODS = Buffer.from('0580', 'hex'); const reply_NO_ACCEPTABLE_METHODS = Buffer.from('05ff', 'hex'); // end reply Buffer class Requests { constructor(buffer) { this.buffer = buffer; } get socketVersion() { return this.buffer.readUInt8(0); } get IsSocket5() { return this.buffer.readUInt8(0) === 0x05; } get isRequests() { return this.buffer.length > 3; } get domainLength() { return this.buffer.readUInt8(4); } get domainName() { if (this.ATYP !== exports.ATYP.DOMAINNAME) { return null; } return this.buffer.toString('utf8', 5, 5 + this.domainLength); } get ATYP() { return this.buffer.readInt8(3); } set_V5() { this.buffer.writeUInt8(5, 0); } set status(n) { this.buffer.writeUInt8(n, 1); } get ATYP_IP4Address() { if (this.ATYP !== exports.ATYP.IP_V4) { return null; } return `${this.buffer.readUInt8(4).toString()}.${this.buffer.readUInt8(5).toString()}.${this.buffer.readUInt8(6).toString()}.${this.buffer.readUInt8(7).toString()}`; } get port() { if (this.ATYP === exports.ATYP.DOMAINNAME) { const length = this.buffer.readUInt8(4); return this.buffer.readUInt16BE(5 + length); } if (this.ATYP === exports.ATYP.IP_V6) { return this.buffer.readUInt16BE(19); } return this.buffer.readUInt16BE(8); } get IPv6() { if (this.ATYP !== exports.ATYP.IP_V6) return null; return `${this.buffer.readUInt32BE(4).toString(16)}:${this.buffer.readUInt32BE(8).toString(16)}:${this.buffer.readUInt32BE(12).toString(16)}:${this.buffer.readUInt32BE(16).toString(16)}`; } get cmd() { return this.buffer.readUInt8(1); } set serverIP(n) { this.buffer = Buffer.alloc(22); this.set_V5(); this.buffer.writeUInt8(1, 3); const y = n.split('.'); for (let i = 0, j = 4; i < 4; i++, j++) { const k = parseInt(y[i]); if (isNaN(k) || k < 0 || k > 255) { console.log(`serverIP ERROR! k = [${k}] ip[${n}]`); break; } this.buffer.writeUInt8(k, j); } console.log(`setup serverIP: buffer [${this.buffer.toString('hex')}]`); } set REP(n) { this.buffer.writeUInt8(n, 1); } get hostAddress() { return this.ATYP_IP4Address || this.IPv6; } get host() { return this.domainName || this.IPv6 || this.ATYP_IP4Address; } set port(port) { this.buffer.writeUInt16BE(port, 20); } } exports.Requests = Requests; class socket4Requests { constructor(buffer) { this.buffer = buffer; } get socketVersion() { return this.buffer.readUInt8(0); } get IsSocket4() { return this.buffer.readUInt8(0) === 0x04; } get cmd() { return this.buffer.readUInt8(1); } get port() { return this.buffer.readUInt16BE(2); } get targetIp() { const uu = `${this.buffer.readUInt8(4).toString()}.${this.buffer.readUInt8(5).toString()}.${this.buffer.readUInt8(6).toString()}.${this.buffer.readUInt8(7).toString()}`; if (/^0.0.0/.test(uu)) return null; return uu; } get domainName() { if (!this.targetIp) { return this.buffer.slice(9).toString(); } return null; } request_4_granted(targetIp, targetPort) { if (!targetIp) { return Buffer.from('005a000000000000', 'hex'); } const ret = Buffer.from('005a000000000000', 'hex'); ret.writeUInt16BE(targetPort, 2); const u = targetIp.split('.'); for (let i = 4, l = 0; i < 8; i++, l++) { ret.writeUInt8(parseInt(u[l]), i); } return ret; } get request_failed() { return Buffer.from('005b000000', 'hex'); } } exports.socket4Requests = socket4Requests;