1 | "use strict";
|
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3 | if (k2 === undefined) k2 = k;
|
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
|
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6 | desc = { enumerable: true, get: function() { return m[k]; } };
|
7 | }
|
8 | Object.defineProperty(o, k2, desc);
|
9 | }) : (function(o, m, k, k2) {
|
10 | if (k2 === undefined) k2 = k;
|
11 | o[k2] = m[k];
|
12 | }));
|
13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15 | }) : function(o, v) {
|
16 | o["default"] = v;
|
17 | });
|
18 | var __importStar = (this && this.__importStar) || function (mod) {
|
19 | if (mod && mod.__esModule) return mod;
|
20 | var result = {};
|
21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22 | __setModuleDefault(result, mod);
|
23 | return result;
|
24 | };
|
25 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
26 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
27 | };
|
28 | Object.defineProperty(exports, "__esModule", { value: true });
|
29 | exports.SocksProxyAgent = void 0;
|
30 | const socks_1 = require("socks");
|
31 | const agent_base_1 = require("agent-base");
|
32 | const debug_1 = __importDefault(require("debug"));
|
33 | const dns = __importStar(require("dns"));
|
34 | const tls = __importStar(require("tls"));
|
35 | const url_1 = require("url");
|
36 | const debug = (0, debug_1.default)('socks-proxy-agent');
|
37 | function parseSocksURL(url) {
|
38 | let lookup = false;
|
39 | let type = 5;
|
40 | const host = url.hostname;
|
41 |
|
42 |
|
43 | const port = parseInt(url.port, 10) || 1080;
|
44 |
|
45 |
|
46 | switch (url.protocol.replace(':', '')) {
|
47 | case 'socks4':
|
48 | lookup = true;
|
49 | type = 4;
|
50 | break;
|
51 |
|
52 | case 'socks4a':
|
53 | type = 4;
|
54 | break;
|
55 | case 'socks5':
|
56 | lookup = true;
|
57 | type = 5;
|
58 | break;
|
59 |
|
60 | case 'socks':
|
61 | type = 5;
|
62 | break;
|
63 | case 'socks5h':
|
64 | type = 5;
|
65 | break;
|
66 | default:
|
67 | throw new TypeError(`A "socks" protocol must be specified! Got: ${String(url.protocol)}`);
|
68 | }
|
69 | const proxy = {
|
70 | host,
|
71 | port,
|
72 | type,
|
73 | };
|
74 | if (url.username) {
|
75 | Object.defineProperty(proxy, 'userId', {
|
76 | value: decodeURIComponent(url.username),
|
77 | enumerable: false,
|
78 | });
|
79 | }
|
80 | if (url.password != null) {
|
81 | Object.defineProperty(proxy, 'password', {
|
82 | value: decodeURIComponent(url.password),
|
83 | enumerable: false,
|
84 | });
|
85 | }
|
86 | return { lookup, proxy };
|
87 | }
|
88 | class SocksProxyAgent extends agent_base_1.Agent {
|
89 | constructor(uri, opts) {
|
90 | super(opts);
|
91 | const url = typeof uri === 'string' ? new url_1.URL(uri) : uri;
|
92 | const { proxy, lookup } = parseSocksURL(url);
|
93 | this.shouldLookup = lookup;
|
94 | this.proxy = proxy;
|
95 | this.timeout = opts?.timeout ?? null;
|
96 | this.socketOptions = opts?.socketOptions ?? null;
|
97 | }
|
98 | |
99 |
|
100 |
|
101 |
|
102 | async connect(req, opts) {
|
103 | const { shouldLookup, proxy, timeout } = this;
|
104 | if (!opts.host) {
|
105 | throw new Error('No `host` defined!');
|
106 | }
|
107 | let { host } = opts;
|
108 | const { port, lookup: lookupFn = dns.lookup } = opts;
|
109 | if (shouldLookup) {
|
110 |
|
111 | host = await new Promise((resolve, reject) => {
|
112 |
|
113 | lookupFn(host, {}, (err, res) => {
|
114 | if (err) {
|
115 | reject(err);
|
116 | }
|
117 | else {
|
118 | resolve(res);
|
119 | }
|
120 | });
|
121 | });
|
122 | }
|
123 | const socksOpts = {
|
124 | proxy,
|
125 | destination: {
|
126 | host,
|
127 | port: typeof port === 'number' ? port : parseInt(port, 10),
|
128 | },
|
129 | command: 'connect',
|
130 | timeout: timeout ?? undefined,
|
131 |
|
132 |
|
133 | socket_options: this.socketOptions ?? undefined,
|
134 | };
|
135 | const cleanup = (tlsSocket) => {
|
136 | req.destroy();
|
137 | socket.destroy();
|
138 | if (tlsSocket)
|
139 | tlsSocket.destroy();
|
140 | };
|
141 | debug('Creating socks proxy connection: %o', socksOpts);
|
142 | const { socket } = await socks_1.SocksClient.createConnection(socksOpts);
|
143 | debug('Successfully created socks proxy connection');
|
144 | if (timeout !== null) {
|
145 | socket.setTimeout(timeout);
|
146 | socket.on('timeout', () => cleanup());
|
147 | }
|
148 | if (opts.secureEndpoint) {
|
149 |
|
150 |
|
151 | debug('Upgrading socket connection to TLS');
|
152 | const servername = opts.servername || opts.host;
|
153 | const tlsSocket = tls.connect({
|
154 | ...omit(opts, 'host', 'path', 'port'),
|
155 | socket,
|
156 | servername,
|
157 | });
|
158 | tlsSocket.once('error', (error) => {
|
159 | debug('Socket TLS error', error.message);
|
160 | cleanup(tlsSocket);
|
161 | });
|
162 | return tlsSocket;
|
163 | }
|
164 | return socket;
|
165 | }
|
166 | }
|
167 | SocksProxyAgent.protocols = [
|
168 | 'socks',
|
169 | 'socks4',
|
170 | 'socks4a',
|
171 | 'socks5',
|
172 | 'socks5h',
|
173 | ];
|
174 | exports.SocksProxyAgent = SocksProxyAgent;
|
175 | function omit(obj, ...keys) {
|
176 | const ret = {};
|
177 | let key;
|
178 | for (key in obj) {
|
179 | if (!keys.includes(key)) {
|
180 | ret[key] = obj[key];
|
181 | }
|
182 | }
|
183 | return ret;
|
184 | }
|
185 |
|
\ | No newline at end of file |