ddan-js 2.7.5 → 2.7.7
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/proxy.js +22 -1
- package/bin/lib/modules/node/socks5.js +17 -17
- package/bin/lib/modules/rsa.js +37 -20
- package/bin/lib/modules/rule/async-validator/rule/url.js +11 -11
- package/bin/types/index.d.ts +7 -2
- package/bin/types/modules/node/index.d.ts +5 -0
- package/bin/types/modules/node/proxy.d.ts +5 -0
- package/bin/types/modules/rsa.d.ts +1 -1
- package/bin/types/modules/rule/async-validator/index.d.ts +6 -0
- package/package.json +1 -1
|
@@ -63,7 +63,7 @@ class Socks5 {
|
|
|
63
63
|
if (this.validateProxyConfig())
|
|
64
64
|
return 0;
|
|
65
65
|
if (this.server) {
|
|
66
|
-
this.__debug && console.info(`[
|
|
66
|
+
this.__debug && console.info(`[socks5] server is already running`);
|
|
67
67
|
return this.__port;
|
|
68
68
|
}
|
|
69
69
|
const port = await this.findAvailablePort(startPort);
|
|
@@ -72,10 +72,10 @@ class Socks5 {
|
|
|
72
72
|
this.__port = port;
|
|
73
73
|
this.server = net_1.default.createServer((socket) => this.handleSocksConnection(socket));
|
|
74
74
|
this.server.listen(port, () => {
|
|
75
|
-
this.__debug && this.__logger?.info(`[
|
|
75
|
+
this.__debug && this.__logger?.info(`[socks5] server is running on port ${port}`);
|
|
76
76
|
});
|
|
77
77
|
this.server.on('error', (err) => {
|
|
78
|
-
this.__logger?.error('[
|
|
78
|
+
this.__logger?.error('[socks5] server error:', err);
|
|
79
79
|
this.close();
|
|
80
80
|
});
|
|
81
81
|
return port;
|
|
@@ -124,7 +124,7 @@ class Socks5 {
|
|
|
124
124
|
port++; // 尝试下一个端口
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
-
this.__debug && this.__logger?.warn('[
|
|
127
|
+
this.__debug && this.__logger?.warn('[socks5] findAvailablePort failed');
|
|
128
128
|
return 0;
|
|
129
129
|
}
|
|
130
130
|
async handleSocksConnection(clientSocket) {
|
|
@@ -141,28 +141,28 @@ class Socks5 {
|
|
|
141
141
|
const destination = await this.parseClientRequest(clientSocket);
|
|
142
142
|
const addr = destination.addr;
|
|
143
143
|
addrport = `${addr}:${destination.port}`;
|
|
144
|
-
this.__debug && this.__logger?.info(`[
|
|
144
|
+
this.__debug && this.__logger?.info(`[socks5] handle connection`, addrport);
|
|
145
145
|
if (this.isAllowedDomain(addr)) {
|
|
146
146
|
// 走上游代理
|
|
147
147
|
const upstreamSocket = await this.connectToUpstreamProxy(destination);
|
|
148
|
-
this.__logger?.info(`[
|
|
148
|
+
this.__logger?.info(`[socks5] handle connection upstream`, addrport);
|
|
149
149
|
this.setupDataForwarding(clientSocket, upstreamSocket);
|
|
150
150
|
}
|
|
151
151
|
else if (this.useSystemProxy && this.systemProxy && !index_1.default.isLocalIpAddress(addr)) {
|
|
152
152
|
// 走系统代理
|
|
153
153
|
const systemSocket = await this.connectToSystemProxy(destination);
|
|
154
|
-
this.__debug && console.info(`[
|
|
154
|
+
this.__debug && console.info(`[socks5] handle connection system`, addrport);
|
|
155
155
|
this.setupDataForwarding(clientSocket, systemSocket);
|
|
156
156
|
}
|
|
157
157
|
else {
|
|
158
|
-
this.__debug && console.info(`[
|
|
158
|
+
this.__debug && console.info(`[socks5] handle connection local`, addrport);
|
|
159
159
|
// 本地连接
|
|
160
160
|
const localSocket = await this.connectToLocal(destination);
|
|
161
161
|
this.setupDataForwarding(clientSocket, localSocket);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
catch (err) {
|
|
165
|
-
this.__debug && this.__logger?.error('[
|
|
165
|
+
this.__debug && this.__logger?.error('[socks5] connection failed:', err);
|
|
166
166
|
// this.__event.emit(Socks5Event.Error, err, addrport)
|
|
167
167
|
clientSocket.end(new Uint8Array([0x05, 0x01]));
|
|
168
168
|
this._emit('error', err, addrport);
|
|
@@ -286,21 +286,21 @@ class Socks5 {
|
|
|
286
286
|
clientSocket.pipe(targetSocket);
|
|
287
287
|
targetSocket.pipe(clientSocket);
|
|
288
288
|
const addrPort = `${targetSocket.localAddress}:${targetSocket.localPort}`;
|
|
289
|
-
this.__debug && console.info(`[
|
|
289
|
+
this.__debug && console.info(`[socks5] setupDataForwarding ${addrPort}`);
|
|
290
290
|
clientSocket.on('close', () => {
|
|
291
|
-
this.__debug && console.info('[
|
|
291
|
+
this.__debug && console.info('[socks5] client socket close', addrPort);
|
|
292
292
|
targetSocket.end();
|
|
293
293
|
});
|
|
294
294
|
targetSocket.on('close', () => {
|
|
295
|
-
this.__debug && console.info('[
|
|
295
|
+
this.__debug && console.info('[socks5] target socket close', addrPort);
|
|
296
296
|
clientSocket.end();
|
|
297
297
|
});
|
|
298
298
|
clientSocket.on('error', (err) => {
|
|
299
|
-
this.__debug && console.error('[
|
|
299
|
+
this.__debug && console.error('[socks5] client socket error:', err?.message);
|
|
300
300
|
targetSocket.end();
|
|
301
301
|
});
|
|
302
302
|
targetSocket.on('error', (err) => {
|
|
303
|
-
this.__debug && console.error('[
|
|
303
|
+
this.__debug && console.error('[socks5] target socket error:', err?.message);
|
|
304
304
|
clientSocket.end();
|
|
305
305
|
});
|
|
306
306
|
}
|
|
@@ -319,10 +319,10 @@ class Socks5 {
|
|
|
319
319
|
try {
|
|
320
320
|
if (!this.server)
|
|
321
321
|
return;
|
|
322
|
-
this.__debug && this.__logger?.info('[
|
|
322
|
+
this.__debug && this.__logger?.info('[socks5] closing SOCKS5 proxy server...');
|
|
323
323
|
this.server.close((err) => {
|
|
324
324
|
if (err) {
|
|
325
|
-
this.__debug && this.__logger?.error('[
|
|
325
|
+
this.__debug && this.__logger?.error('[socks5] closing the server failed:', err);
|
|
326
326
|
}
|
|
327
327
|
});
|
|
328
328
|
// 销毁客户端 socket
|
|
@@ -334,7 +334,7 @@ class Socks5 {
|
|
|
334
334
|
this.__port = 0;
|
|
335
335
|
}
|
|
336
336
|
catch (error) {
|
|
337
|
-
this.__debug && this.__logger?.error('[
|
|
337
|
+
this.__debug && this.__logger?.error('[socks5] close error:', error);
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
on(name, listener) {
|
package/bin/lib/modules/rsa.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const __1 = require("..");
|
|
3
4
|
const convert_1 = require("./convert");
|
|
4
5
|
const generateKeys = async () => {
|
|
5
6
|
try {
|
|
@@ -29,10 +30,10 @@ const generateKeys = async () => {
|
|
|
29
30
|
catch (err) {
|
|
30
31
|
console.error('generateKeys failed:', err);
|
|
31
32
|
return {
|
|
32
|
-
publicKey:
|
|
33
|
-
publicKeyPem:
|
|
34
|
-
privateKey:
|
|
35
|
-
privateKeyPem:
|
|
33
|
+
publicKey: '',
|
|
34
|
+
publicKeyPem: '',
|
|
35
|
+
privateKey: '',
|
|
36
|
+
privateKeyPem: '',
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
};
|
|
@@ -48,35 +49,51 @@ const format_pem_content = (buffer) => {
|
|
|
48
49
|
const format_pem_key = (pemContent = '', label = 'PUBLIC KEY') => {
|
|
49
50
|
return `-----BEGIN ${label}-----\n${pemContent}\n-----END ${label}-----`;
|
|
50
51
|
};
|
|
52
|
+
// SHA256: 256 - 2 - 2*32 = 190
|
|
53
|
+
// SHA1: 256 - 2 - 2*20 = 214
|
|
54
|
+
const maxChunkSize = 190;
|
|
51
55
|
const encrypt = async (data, publicKey) => {
|
|
52
56
|
try {
|
|
53
|
-
const
|
|
54
|
-
const key = await window.crypto.subtle.importKey('spki',
|
|
57
|
+
const bytes = new TextEncoder().encode(data);
|
|
58
|
+
const key = await window.crypto.subtle.importKey('spki', __1.dHook.str2ab(window.atob(publicKey)), {
|
|
55
59
|
name: 'RSA-OAEP',
|
|
56
60
|
hash: 'SHA-256',
|
|
57
61
|
}, true, ['encrypt']);
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
const encryptedChunks = [];
|
|
63
|
+
for (let i = 0; i < bytes.length; i += maxChunkSize) {
|
|
64
|
+
let chunk = bytes.slice(i, i + maxChunkSize);
|
|
65
|
+
let encryptedChunk = await window.crypto.subtle.encrypt({
|
|
66
|
+
name: 'RSA-OAEP',
|
|
67
|
+
}, key, chunk);
|
|
68
|
+
encryptedChunks.push(new Uint8Array(encryptedChunk));
|
|
69
|
+
}
|
|
70
|
+
const enctryptedBytes = __1.dHook.concatBytes(...encryptedChunks);
|
|
71
|
+
return __1.dHook.bytesToBase64(enctryptedBytes);
|
|
62
72
|
}
|
|
63
|
-
catch (
|
|
64
|
-
console.error(
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error(`[debug] encrypt`, error);
|
|
65
75
|
return '';
|
|
66
76
|
}
|
|
67
77
|
};
|
|
68
|
-
const decrypt = async (
|
|
78
|
+
const decrypt = async (encryptedBase64, privateKey) => {
|
|
69
79
|
try {
|
|
70
|
-
const encrypted =
|
|
71
|
-
const key = await window.crypto.subtle.importKey('pkcs8',
|
|
80
|
+
const encrypted = __1.dHook.base64ToBytes(encryptedBase64);
|
|
81
|
+
const key = await window.crypto.subtle.importKey('pkcs8', __1.dHook.str2ab(privateKey, true), {
|
|
72
82
|
name: 'RSA-OAEP',
|
|
73
83
|
hash: 'SHA-256',
|
|
74
84
|
}, true, ['decrypt']);
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
85
|
+
const decryptedChunks = [];
|
|
86
|
+
const chunkSize = 256; // 每个加密块的大小(2048位 RSA 的加密输出为 256 字节)
|
|
87
|
+
for (let i = 0; i < encrypted.length; i += chunkSize) {
|
|
88
|
+
let chunk = encrypted.slice(i, i + chunkSize);
|
|
89
|
+
let decryptedChunk = await window.crypto.subtle.decrypt({
|
|
90
|
+
name: 'RSA-OAEP',
|
|
91
|
+
}, key, chunk);
|
|
92
|
+
// 添加解密后的数据
|
|
93
|
+
decryptedChunks.push(new Uint8Array(decryptedChunk));
|
|
94
|
+
}
|
|
95
|
+
const encryptedBytes = __1.dHook.concatBytes(...decryptedChunks);
|
|
96
|
+
return __1.dHook.bytesToStr(encryptedBytes);
|
|
80
97
|
}
|
|
81
98
|
catch (err) {
|
|
82
99
|
console.error('decrypt failed:', err);
|
|
@@ -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, '')
|
package/bin/types/index.d.ts
CHANGED
|
@@ -560,7 +560,7 @@ declare const dWeb: {
|
|
|
560
560
|
format_pem_key: (pemContent?: string, label?: string) => string;
|
|
561
561
|
format_pem_content: (buffer: ArrayBuffer) => string;
|
|
562
562
|
encrypt: (data: string, publicKey: string) => Promise<string>;
|
|
563
|
-
decrypt: (
|
|
563
|
+
decrypt: (encryptedBase64: string, privateKey: string) => Promise<string>;
|
|
564
564
|
};
|
|
565
565
|
};
|
|
566
566
|
declare const dNode: {
|
|
@@ -576,6 +576,11 @@ declare const dNode: {
|
|
|
576
576
|
type?: "PROXY" | "SOCKS5" | "ALL" | undefined;
|
|
577
577
|
direct?: boolean | undefined;
|
|
578
578
|
} | undefined) => string;
|
|
579
|
+
pacScript: (host: string, port: number, options?: {
|
|
580
|
+
rules?: string[] | undefined;
|
|
581
|
+
type?: "PROXY" | "SOCKS5" | "ALL" | undefined;
|
|
582
|
+
useSystem?: boolean | undefined;
|
|
583
|
+
} | undefined) => Promise<string>;
|
|
579
584
|
child_exec: (cmd: string) => Promise<[any, string]>;
|
|
580
585
|
brotliCompress: typeof import("./modules/node/brotli").brotliCompress;
|
|
581
586
|
brotliDecompress: typeof import("./modules/node/brotli").brotliDecompress;
|
|
@@ -966,7 +971,7 @@ declare const _default: {
|
|
|
966
971
|
format_pem_key: (pemContent?: string, label?: string) => string;
|
|
967
972
|
format_pem_content: (buffer: ArrayBuffer) => string;
|
|
968
973
|
encrypt: (data: string, publicKey: string) => Promise<string>;
|
|
969
|
-
decrypt: (
|
|
974
|
+
decrypt: (encryptedBase64: string, privateKey: string) => Promise<string>;
|
|
970
975
|
};
|
|
971
976
|
};
|
|
972
977
|
export default _default;
|
|
@@ -14,6 +14,11 @@ declare const _default: {
|
|
|
14
14
|
type?: "PROXY" | "SOCKS5" | "ALL" | undefined;
|
|
15
15
|
direct?: boolean | undefined;
|
|
16
16
|
} | undefined) => string;
|
|
17
|
+
pacScript: (host: string, port: number, options?: {
|
|
18
|
+
rules?: string[] | undefined;
|
|
19
|
+
type?: "PROXY" | "SOCKS5" | "ALL" | undefined;
|
|
20
|
+
useSystem?: boolean | undefined;
|
|
21
|
+
} | undefined) => Promise<string>;
|
|
17
22
|
child_exec: (cmd: string) => Promise<[any, string]>;
|
|
18
23
|
brotliCompress: typeof import("./brotli").brotliCompress;
|
|
19
24
|
brotliDecompress: typeof import("./brotli").brotliDecompress;
|
|
@@ -8,5 +8,10 @@ declare const _default_1: {
|
|
|
8
8
|
type?: "PROXY" | "SOCKS5" | "ALL" | undefined;
|
|
9
9
|
direct?: boolean | undefined;
|
|
10
10
|
} | undefined) => string;
|
|
11
|
+
pacScript: (host: string, port: number, options?: {
|
|
12
|
+
rules?: string[] | undefined;
|
|
13
|
+
type?: "PROXY" | "SOCKS5" | "ALL" | undefined;
|
|
14
|
+
useSystem?: boolean | undefined;
|
|
15
|
+
} | undefined) => Promise<string>;
|
|
11
16
|
};
|
|
12
17
|
export default _default_1;
|
|
@@ -8,6 +8,6 @@ declare const _default: {
|
|
|
8
8
|
format_pem_key: (pemContent?: string, label?: string) => string;
|
|
9
9
|
format_pem_content: (buffer: ArrayBuffer) => string;
|
|
10
10
|
encrypt: (data: string, publicKey: string) => Promise<string>;
|
|
11
|
-
decrypt: (
|
|
11
|
+
decrypt: (encryptedBase64: string, privateKey: string) => Promise<string>;
|
|
12
12
|
};
|
|
13
13
|
export default _default;
|
|
@@ -14,6 +14,12 @@ 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
|
+
*/
|
|
17
23
|
boolean: import("./interface").ExecuteValidator;
|
|
18
24
|
regexp: import("./interface").ExecuteValidator;
|
|
19
25
|
integer: import("./interface").ExecuteValidator;
|