ddan-js 2.6.40 → 2.6.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -7
- package/README.md +10 -10
- package/bin/ddan-js.esm.js +1 -1
- package/bin/ddan-js.js +1 -1
- package/bin/lib/modules/node/ecdh.js +2 -2
- package/bin/lib/modules/node/socks5.js +26 -70
- package/bin/lib/modules/rule/async-validator/rule/url.js +11 -11
- package/bin/types/modules/node/ecdh.d.ts +1 -1
- package/bin/types/modules/node/socks5.d.ts +4 -3
- package/bin/types/modules/rule/async-validator/index.d.ts +0 -6
- package/package.json +1 -1
|
@@ -4,9 +4,9 @@ exports.Socks5 = void 0;
|
|
|
4
4
|
const net_1 = require("net");
|
|
5
5
|
const socks_1 = require("socks");
|
|
6
6
|
const uuid_1 = require("../crypto/uuid");
|
|
7
|
-
const mapping_1 = require("../../class/mapping");
|
|
8
7
|
const index_1 = require("../qs/index");
|
|
9
8
|
const event_1 = require("../../class/event");
|
|
9
|
+
const pipeline_1 = require("../hook/modules/pipeline");
|
|
10
10
|
const Socks5Event = {
|
|
11
11
|
Error: 'error',
|
|
12
12
|
};
|
|
@@ -15,20 +15,20 @@ class Socks5 {
|
|
|
15
15
|
server = null;
|
|
16
16
|
clientSockets = new Set();
|
|
17
17
|
allowedDomains;
|
|
18
|
-
connectionPool;
|
|
19
18
|
systemProxy = null;
|
|
20
19
|
useSystemProxy = false;
|
|
21
20
|
__debug = false;
|
|
22
21
|
__uuid;
|
|
23
22
|
__port = 0;
|
|
24
23
|
__event;
|
|
24
|
+
__pipeline;
|
|
25
25
|
constructor(upstreamProxy, allowedDomains = ['*'], debug = false) {
|
|
26
26
|
this.__event = new event_1.default();
|
|
27
27
|
this.upstreamProxy = upstreamProxy;
|
|
28
28
|
this.allowedDomains = new Set(allowedDomains);
|
|
29
29
|
this.__debug = debug;
|
|
30
30
|
this.__uuid = (0, uuid_1.default)();
|
|
31
|
-
this.
|
|
31
|
+
this.__pipeline = new pipeline_1.default(1);
|
|
32
32
|
}
|
|
33
33
|
get id() {
|
|
34
34
|
return this.__uuid;
|
|
@@ -61,7 +61,7 @@ class Socks5 {
|
|
|
61
61
|
}
|
|
62
62
|
const port = await this.findAvailablePort(startPort);
|
|
63
63
|
if (!port)
|
|
64
|
-
return
|
|
64
|
+
return 0;
|
|
65
65
|
this.__port = port;
|
|
66
66
|
this.server = net_1.default.createServer((socket) => this.handleSocksConnection(socket));
|
|
67
67
|
this.server.listen(port, () => {
|
|
@@ -115,6 +115,18 @@ class Socks5 {
|
|
|
115
115
|
return 0;
|
|
116
116
|
}
|
|
117
117
|
async handleSocksConnection(clientSocket) {
|
|
118
|
+
const id = (0, uuid_1.default)();
|
|
119
|
+
this.__pipeline.push(async () => {
|
|
120
|
+
this.__debug &&
|
|
121
|
+
console.info(`[socks] pipeline ${clientSocket.remoteAddress}:${clientSocket.remotePort} ${id}`);
|
|
122
|
+
await this._handleSocksConnection(clientSocket);
|
|
123
|
+
}, () => {
|
|
124
|
+
console.info(`[socks] pipeline ${id} end`);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async _handleSocksConnection(clientSocket) {
|
|
128
|
+
if (!clientSocket)
|
|
129
|
+
return;
|
|
118
130
|
this.clientSockets.add(clientSocket);
|
|
119
131
|
clientSocket.on('close', () => {
|
|
120
132
|
this.clientSockets.delete(clientSocket);
|
|
@@ -122,7 +134,6 @@ class Socks5 {
|
|
|
122
134
|
});
|
|
123
135
|
let addrport = '';
|
|
124
136
|
try {
|
|
125
|
-
this.connectionPool.clean(100, (kv) => kv?.destroy());
|
|
126
137
|
await this.performHandshake(clientSocket);
|
|
127
138
|
const destination = await this.parseClientRequest(clientSocket);
|
|
128
139
|
addrport = `${destination.addr}:${destination.port}`;
|
|
@@ -207,26 +218,8 @@ class Socks5 {
|
|
|
207
218
|
});
|
|
208
219
|
});
|
|
209
220
|
}
|
|
210
|
-
getPoolConnection(key) {
|
|
211
|
-
if (!key)
|
|
212
|
-
return undefined;
|
|
213
|
-
const connection = this.connectionPool.get(key);
|
|
214
|
-
// 如果已有连接在池中,复用
|
|
215
|
-
if (this.connectionPool[key] && !this.connectionPool[key].destroyed) {
|
|
216
|
-
return this.connectionPool[key];
|
|
217
|
-
}
|
|
218
|
-
// 如果已有连接在池中,复用
|
|
219
|
-
if (connection && !connection.destroyed) {
|
|
220
|
-
return connection;
|
|
221
|
-
}
|
|
222
|
-
return undefined;
|
|
223
|
-
}
|
|
224
221
|
// 上游代理连接
|
|
225
222
|
async connectToUpstreamProxy(destination) {
|
|
226
|
-
const destKey = `${destination.addr}:${destination.port}`;
|
|
227
|
-
const cacheConnection = this.getPoolConnection(destKey);
|
|
228
|
-
if (cacheConnection)
|
|
229
|
-
return cacheConnection;
|
|
230
223
|
const options = {
|
|
231
224
|
proxy: { ...this.upstreamProxy, type: 5 },
|
|
232
225
|
command: 'connect',
|
|
@@ -236,15 +229,7 @@ class Socks5 {
|
|
|
236
229
|
},
|
|
237
230
|
};
|
|
238
231
|
try {
|
|
239
|
-
|
|
240
|
-
// this.connectionPool[destKey] = upstreamSocket
|
|
241
|
-
this.connectionPool.set(destKey, upstreamSocket);
|
|
242
|
-
upstreamSocket.on('close', () => {
|
|
243
|
-
// delete this.connectionPool[destKey]
|
|
244
|
-
this.__debug && console.info('[socks] connection pool delete', destKey);
|
|
245
|
-
this.connectionPool.delete(destKey);
|
|
246
|
-
});
|
|
247
|
-
return upstreamSocket;
|
|
232
|
+
return await this.connectToProxy(options);
|
|
248
233
|
}
|
|
249
234
|
catch (err) {
|
|
250
235
|
throw new Error('Failed to connect to upstream proxy: ' + err);
|
|
@@ -252,10 +237,6 @@ class Socks5 {
|
|
|
252
237
|
}
|
|
253
238
|
// 系统代理连接
|
|
254
239
|
async connectToSystemProxy(destination) {
|
|
255
|
-
const destKey = `${destination.addr}:${destination.port}`;
|
|
256
|
-
const cacheConnection = this.getPoolConnection(destKey);
|
|
257
|
-
if (cacheConnection)
|
|
258
|
-
return cacheConnection;
|
|
259
240
|
const options = {
|
|
260
241
|
proxy: { ...this.systemProxy, type: 5 },
|
|
261
242
|
command: 'connect',
|
|
@@ -265,36 +246,22 @@ class Socks5 {
|
|
|
265
246
|
},
|
|
266
247
|
};
|
|
267
248
|
try {
|
|
268
|
-
|
|
269
|
-
this.connectionPool.set(destKey, systemSocket);
|
|
270
|
-
systemSocket.on('close', () => {
|
|
271
|
-
// delete this.connectionPool[destKey]
|
|
272
|
-
this.__debug && console.info('[socks] connection pool delete', destKey);
|
|
273
|
-
this.connectionPool.delete(destKey);
|
|
274
|
-
});
|
|
275
|
-
return systemSocket;
|
|
249
|
+
return await this.connectToProxy(options);
|
|
276
250
|
}
|
|
277
251
|
catch (err) {
|
|
278
252
|
throw new Error('Failed to connect to system proxy: ' + err);
|
|
279
253
|
}
|
|
280
254
|
}
|
|
255
|
+
async connectToProxy(options) {
|
|
256
|
+
const { socket } = await socks_1.SocksClient.createConnection(options);
|
|
257
|
+
return socket;
|
|
258
|
+
}
|
|
281
259
|
// 本地连接
|
|
282
260
|
async connectToLocal(destination) {
|
|
283
|
-
const destKey = `${destination.addr}:${destination.port}`;
|
|
284
|
-
const cacheConnection = this.getPoolConnection(destKey);
|
|
285
|
-
if (cacheConnection)
|
|
286
|
-
return cacheConnection;
|
|
287
261
|
return new Promise((resolve, reject) => {
|
|
288
262
|
const localSocket = net_1.default.createConnection(destination.port, destination.addr, () => {
|
|
289
263
|
resolve(localSocket);
|
|
290
264
|
});
|
|
291
|
-
// this.connectionPool[destKey] = localSocket
|
|
292
|
-
this.connectionPool.set(destKey, localSocket);
|
|
293
|
-
localSocket.on('close', () => {
|
|
294
|
-
// delete this.connectionPool[destKey]
|
|
295
|
-
this.__debug && console.info('[socks] connection pool delete', destKey);
|
|
296
|
-
this.connectionPool.delete(destKey);
|
|
297
|
-
});
|
|
298
265
|
localSocket.on('error', (err) => {
|
|
299
266
|
reject(err);
|
|
300
267
|
});
|
|
@@ -304,14 +271,14 @@ class Socks5 {
|
|
|
304
271
|
clientSocket.write(new Uint8Array([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
|
|
305
272
|
clientSocket.pipe(targetSocket);
|
|
306
273
|
targetSocket.pipe(clientSocket);
|
|
307
|
-
const
|
|
308
|
-
this.__debug && console.info(`[socks] setupDataForwarding ${
|
|
274
|
+
const addrPort = `${targetSocket.localAddress}:${targetSocket.localPort}`;
|
|
275
|
+
this.__debug && console.info(`[socks] setupDataForwarding ${addrPort}`);
|
|
309
276
|
clientSocket.on('close', () => {
|
|
310
|
-
this.__debug && console.info('[socks] client socket close',
|
|
277
|
+
this.__debug && console.info('[socks] client socket close', addrPort);
|
|
311
278
|
targetSocket.end();
|
|
312
279
|
});
|
|
313
280
|
targetSocket.on('close', () => {
|
|
314
|
-
this.__debug && console.info('[socks] target socket close',
|
|
281
|
+
this.__debug && console.info('[socks] target socket close', addrPort);
|
|
315
282
|
clientSocket.end();
|
|
316
283
|
});
|
|
317
284
|
clientSocket.on('error', (err) => {
|
|
@@ -349,8 +316,6 @@ class Socks5 {
|
|
|
349
316
|
this.clientSockets.clear();
|
|
350
317
|
// 销毁所有连接池中的 socket
|
|
351
318
|
// Object.values(this.connectionPool).forEach((socket) => socket?.destroy())
|
|
352
|
-
this.connectionPool.values.forEach((kv) => kv?.value?.destroy());
|
|
353
|
-
this.connectionPool.clear();
|
|
354
319
|
this.server = null;
|
|
355
320
|
this.__port = 0;
|
|
356
321
|
}
|
|
@@ -358,15 +323,6 @@ class Socks5 {
|
|
|
358
323
|
this.__debug && console.error('[socks] close errot:', error);
|
|
359
324
|
}
|
|
360
325
|
}
|
|
361
|
-
showPools() {
|
|
362
|
-
this.connectionPool.values.forEach((kv) => {
|
|
363
|
-
const socket = kv?.value;
|
|
364
|
-
const key = kv?.key;
|
|
365
|
-
if (key && socket) {
|
|
366
|
-
console.info(`[socks] ${key} ${socket.localAddress}:${socket.localPort}`);
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
326
|
on(name, listener) {
|
|
371
327
|
if (!name || !listener)
|
|
372
328
|
return;
|
|
@@ -12,17 +12,17 @@ exports.default = () => {
|
|
|
12
12
|
: '';
|
|
13
13
|
const v4 = '(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}';
|
|
14
14
|
const v6seg = '[a-fA-F\\d]{1,4}';
|
|
15
|
-
const v6 = `
|
|
16
|
-
(?:
|
|
17
|
-
(?:${v6seg}:){7}(?:${v6seg}|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8
|
|
18
|
-
(?:${v6seg}:){6}(?:${v4}|:${v6seg}|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4
|
|
19
|
-
(?:${v6seg}:){5}(?::${v4}|(?::${v6seg}){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4
|
|
20
|
-
(?:${v6seg}:){4}(?:(?::${v6seg}){0,1}:${v4}|(?::${v6seg}){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4
|
|
21
|
-
(?:${v6seg}:){3}(?:(?::${v6seg}){0,2}:${v4}|(?::${v6seg}){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4
|
|
22
|
-
(?:${v6seg}:){2}(?:(?::${v6seg}){0,3}:${v4}|(?::${v6seg}){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4
|
|
23
|
-
(?:${v6seg}:){1}(?:(?::${v6seg}){0,4}:${v4}|(?::${v6seg}){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4
|
|
24
|
-
(?::(?:(?::${v6seg}){0,5}:${v4}|(?::${v6seg}){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4
|
|
25
|
-
)(?:%[0-9a-zA-Z]{1,})? // %eth0 %1
|
|
15
|
+
const v6 = `
|
|
16
|
+
(?:
|
|
17
|
+
(?:${v6seg}:){7}(?:${v6seg}|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8
|
|
18
|
+
(?:${v6seg}:){6}(?:${v4}|:${v6seg}|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4
|
|
19
|
+
(?:${v6seg}:){5}(?::${v4}|(?::${v6seg}){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4
|
|
20
|
+
(?:${v6seg}:){4}(?:(?::${v6seg}){0,1}:${v4}|(?::${v6seg}){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4
|
|
21
|
+
(?:${v6seg}:){3}(?:(?::${v6seg}){0,2}:${v4}|(?::${v6seg}){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4
|
|
22
|
+
(?:${v6seg}:){2}(?:(?::${v6seg}){0,3}:${v4}|(?::${v6seg}){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4
|
|
23
|
+
(?:${v6seg}:){1}(?:(?::${v6seg}){0,4}:${v4}|(?::${v6seg}){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4
|
|
24
|
+
(?::(?:(?::${v6seg}){0,5}:${v4}|(?::${v6seg}){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4
|
|
25
|
+
)(?:%[0-9a-zA-Z]{1,})? // %eth0 %1
|
|
26
26
|
`
|
|
27
27
|
.replace(/\s*\/\/.*$/gm, '')
|
|
28
28
|
.replace(/\n/g, '')
|
|
@@ -9,7 +9,7 @@ export default class Ecdh {
|
|
|
9
9
|
__algorithm: string;
|
|
10
10
|
__ecdh: crypto.ECDH | undefined;
|
|
11
11
|
constructor(curve?: string, algorithm?: string);
|
|
12
|
-
|
|
12
|
+
generateKeys(): void;
|
|
13
13
|
setPrivateKey(privateBase64: string): boolean;
|
|
14
14
|
setSharedSecret(secretBase64: string): boolean;
|
|
15
15
|
deriveSharedSecret(otherPublicKey: string, iv?: string): boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import DEvent from '../../class/event';
|
|
2
|
+
import DPipeline from '../hook/modules/pipeline';
|
|
2
3
|
interface IProxyConfig {
|
|
3
4
|
ipaddress: string;
|
|
4
5
|
port: number;
|
|
@@ -15,13 +16,13 @@ export declare class Socks5 {
|
|
|
15
16
|
private server;
|
|
16
17
|
private clientSockets;
|
|
17
18
|
private allowedDomains;
|
|
18
|
-
private connectionPool;
|
|
19
19
|
private systemProxy;
|
|
20
20
|
private useSystemProxy;
|
|
21
21
|
__debug: boolean;
|
|
22
22
|
__uuid: string;
|
|
23
23
|
__port: number;
|
|
24
24
|
__event: DEvent;
|
|
25
|
+
__pipeline: DPipeline;
|
|
25
26
|
constructor(upstreamProxy: IProxyConfig, allowedDomains?: string[] | ['*'], debug?: boolean);
|
|
26
27
|
get id(): string;
|
|
27
28
|
get port(): number;
|
|
@@ -32,6 +33,7 @@ export declare class Socks5 {
|
|
|
32
33
|
setAllowedDomains(allowedDomains?: string[]): void;
|
|
33
34
|
private findAvailablePort;
|
|
34
35
|
private handleSocksConnection;
|
|
36
|
+
private _handleSocksConnection;
|
|
35
37
|
/**
|
|
36
38
|
* 回复客户端请求响应数据
|
|
37
39
|
* VER是SOCKS版本,这里应该是0x05;
|
|
@@ -50,14 +52,13 @@ export declare class Socks5 {
|
|
|
50
52
|
/** */
|
|
51
53
|
private performHandshake;
|
|
52
54
|
private parseClientRequest;
|
|
53
|
-
private getPoolConnection;
|
|
54
55
|
private connectToUpstreamProxy;
|
|
55
56
|
private connectToSystemProxy;
|
|
57
|
+
private connectToProxy;
|
|
56
58
|
private connectToLocal;
|
|
57
59
|
private setupDataForwarding;
|
|
58
60
|
private isAllowedDomain;
|
|
59
61
|
close(): void;
|
|
60
|
-
showPools(): void;
|
|
61
62
|
on(name: Socks5EventType, listener: (...args: any[]) => void): void;
|
|
62
63
|
off(name: Socks5EventType, listener: (...args: any[]) => void): void;
|
|
63
64
|
private _emit;
|
|
@@ -14,12 +14,6 @@ declare class Schema {
|
|
|
14
14
|
string: import("./interface").ExecuteValidator;
|
|
15
15
|
method: import("./interface").ExecuteValidator;
|
|
16
16
|
number: import("./interface").ExecuteValidator;
|
|
17
|
-
/**
|
|
18
|
-
* Encapsulates a validation schema.
|
|
19
|
-
*
|
|
20
|
-
* @param descriptor An object declaring validation rules
|
|
21
|
-
* for this schema.
|
|
22
|
-
*/
|
|
23
17
|
boolean: import("./interface").ExecuteValidator;
|
|
24
18
|
regexp: import("./interface").ExecuteValidator;
|
|
25
19
|
integer: import("./interface").ExecuteValidator;
|