ddan-js 2.6.39 → 2.6.41
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/bin/ddan-js.esm.js +1 -1
- package/bin/ddan-js.js +1 -1
- package/bin/lib/modules/browser/ecdh.js +20 -12
- package/bin/lib/modules/node/ecdh.js +36 -23
- package/bin/lib/modules/node/socks5.js +16 -11
- package/bin/types/modules/browser/ecdh.d.ts +3 -3
- package/bin/types/modules/node/ecdh.d.ts +8 -7
- package/bin/types/modules/node/socks5.d.ts +3 -0
- package/package.json +1 -1
|
@@ -7,15 +7,15 @@ class Ecdh {
|
|
|
7
7
|
privateKey = '';
|
|
8
8
|
sharedSecret;
|
|
9
9
|
iv = '';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
__curve;
|
|
11
|
+
__algorithm;
|
|
12
|
+
__ecdh;
|
|
13
13
|
constructor(curve = 'prime256v1', algorithm = 'aes-256-gcm') {
|
|
14
|
-
this.
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
14
|
+
this.__curve = curve;
|
|
15
|
+
this.__algorithm = algorithm;
|
|
16
|
+
this.generateKeys();
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
generateKeys() {
|
|
19
19
|
// 使用 P-256 曲线
|
|
20
20
|
const ecdh = node_crypto_1.default.createECDH('prime256v1');
|
|
21
21
|
ecdh.generateKeys();
|
|
@@ -23,28 +23,38 @@ class Ecdh {
|
|
|
23
23
|
this.publicKey = ecdh.getPublicKey('base64');
|
|
24
24
|
// 私钥以 base64 格式导出
|
|
25
25
|
this.privateKey = ecdh.getPrivateKey('base64');
|
|
26
|
-
this.
|
|
26
|
+
this.__ecdh = ecdh;
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
if (!
|
|
28
|
+
setPrivateKey(privateBase64) {
|
|
29
|
+
if (!privateBase64)
|
|
30
|
+
return false;
|
|
31
|
+
if (!this.__ecdh)
|
|
30
32
|
return false;
|
|
31
|
-
this.
|
|
32
|
-
this.
|
|
33
|
+
this.__ecdh.setPrivateKey(privateBase64, 'base64');
|
|
34
|
+
this.publicKey = this.__ecdh.getPublicKey('base64');
|
|
33
35
|
return true;
|
|
34
36
|
}
|
|
35
|
-
|
|
36
|
-
if (!
|
|
37
|
+
setSharedSecret(secretBase64) {
|
|
38
|
+
if (!secretBase64)
|
|
37
39
|
return false;
|
|
38
|
-
|
|
40
|
+
this.sharedSecret = secretBase64;
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
deriveSharedSecret(otherPublicKey, iv) {
|
|
44
|
+
if (!otherPublicKey)
|
|
39
45
|
return false;
|
|
40
|
-
this.
|
|
41
|
-
this.
|
|
46
|
+
this.sharedSecret = this.__ecdh.computeSecret(otherPublicKey, 'base64').toString('base64');
|
|
47
|
+
this.iv = iv || '';
|
|
42
48
|
return true;
|
|
43
49
|
}
|
|
44
|
-
encode(data) {
|
|
45
|
-
if (!this.sharedSecret
|
|
50
|
+
encode(data, iv) {
|
|
51
|
+
if (!this.sharedSecret)
|
|
52
|
+
return '';
|
|
53
|
+
const _iv = iv || this.iv;
|
|
54
|
+
if (!_iv)
|
|
46
55
|
return '';
|
|
47
|
-
const
|
|
56
|
+
const ivBytes = convert_1.default.base64ToBytes(_iv);
|
|
57
|
+
const cipher = node_crypto_1.default.createCipheriv('aes-256-gcm', convert_1.default.base64ToBytes(this.sharedSecret), ivBytes);
|
|
48
58
|
const encrypted = Buffer.concat([
|
|
49
59
|
new Uint8Array(cipher.update(data, 'utf8')),
|
|
50
60
|
new Uint8Array(cipher.final()),
|
|
@@ -53,10 +63,11 @@ class Ecdh {
|
|
|
53
63
|
const combined = Buffer.concat([new Uint8Array(encrypted), new Uint8Array(tagBuf)]);
|
|
54
64
|
return combined.toString('base64');
|
|
55
65
|
}
|
|
56
|
-
encodeiv(data) {
|
|
57
|
-
if (!this.sharedSecret
|
|
66
|
+
encodeiv(data, iv) {
|
|
67
|
+
if (!this.sharedSecret)
|
|
58
68
|
return '';
|
|
59
|
-
const
|
|
69
|
+
const _iv = iv || this.iv;
|
|
70
|
+
const ivBytes = _iv ? convert_1.default.base64ToBytes(_iv) : convert_1.default.getRandomBytes(12);
|
|
60
71
|
const cipher = node_crypto_1.default.createCipheriv('aes-256-gcm', convert_1.default.base64ToBytes(this.sharedSecret), ivBytes);
|
|
61
72
|
const encrypted = Buffer.concat([
|
|
62
73
|
new Uint8Array(cipher.update(data, 'utf8')),
|
|
@@ -70,6 +81,8 @@ class Ecdh {
|
|
|
70
81
|
if (!encrypted || !this.sharedSecret)
|
|
71
82
|
return '';
|
|
72
83
|
const _iv = iv || this.iv;
|
|
84
|
+
if (!_iv)
|
|
85
|
+
return '';
|
|
73
86
|
const decipher = node_crypto_1.default.createDecipheriv('aes-256-gcm', convert_1.default.base64ToBytes(this.sharedSecret), convert_1.default.base64ToBytes(_iv));
|
|
74
87
|
const allBytes = convert_1.default.base64ToBytes(encrypted);
|
|
75
88
|
const authTagBytes = allBytes.slice(allBytes.length - 16);
|
|
@@ -7,6 +7,7 @@ const uuid_1 = require("../crypto/uuid");
|
|
|
7
7
|
const mapping_1 = require("../../class/mapping");
|
|
8
8
|
const index_1 = require("../qs/index");
|
|
9
9
|
const event_1 = require("../../class/event");
|
|
10
|
+
const pipeline_1 = require("../hook/modules/pipeline");
|
|
10
11
|
const Socks5Event = {
|
|
11
12
|
Error: 'error',
|
|
12
13
|
};
|
|
@@ -22,6 +23,7 @@ class Socks5 {
|
|
|
22
23
|
__uuid;
|
|
23
24
|
__port = 0;
|
|
24
25
|
__event;
|
|
26
|
+
__pipeline;
|
|
25
27
|
constructor(upstreamProxy, allowedDomains = ['*'], debug = false) {
|
|
26
28
|
this.__event = new event_1.default();
|
|
27
29
|
this.upstreamProxy = upstreamProxy;
|
|
@@ -29,6 +31,7 @@ class Socks5 {
|
|
|
29
31
|
this.__debug = debug;
|
|
30
32
|
this.__uuid = (0, uuid_1.default)();
|
|
31
33
|
this.connectionPool = new mapping_1.default();
|
|
34
|
+
this.__pipeline = new pipeline_1.default(1);
|
|
32
35
|
}
|
|
33
36
|
get id() {
|
|
34
37
|
return this.__uuid;
|
|
@@ -115,6 +118,11 @@ class Socks5 {
|
|
|
115
118
|
return 0;
|
|
116
119
|
}
|
|
117
120
|
async handleSocksConnection(clientSocket) {
|
|
121
|
+
this.__pipeline.push(() => this._handleSocksConnection(clientSocket));
|
|
122
|
+
}
|
|
123
|
+
async _handleSocksConnection(clientSocket) {
|
|
124
|
+
if (!clientSocket)
|
|
125
|
+
return;
|
|
118
126
|
this.clientSockets.add(clientSocket);
|
|
119
127
|
clientSocket.on('close', () => {
|
|
120
128
|
this.clientSockets.delete(clientSocket);
|
|
@@ -126,20 +134,21 @@ class Socks5 {
|
|
|
126
134
|
await this.performHandshake(clientSocket);
|
|
127
135
|
const destination = await this.parseClientRequest(clientSocket);
|
|
128
136
|
addrport = `${destination.addr}:${destination.port}`;
|
|
137
|
+
const clienAddrport = `${clientSocket.localAddress}:${clientSocket.localPort}`;
|
|
129
138
|
if (this.isAllowedDomain(destination.addr)) {
|
|
130
139
|
// 走上游代理
|
|
131
140
|
const upstreamSocket = await this.connectToUpstreamProxy(destination);
|
|
132
|
-
this.__debug && console.info(`[socks] handle connection upstream`, addrport);
|
|
141
|
+
this.__debug && console.info(`[socks] handle connection upstream`, addrport, clienAddrport);
|
|
133
142
|
this.setupDataForwarding(clientSocket, upstreamSocket);
|
|
134
143
|
}
|
|
135
144
|
else if (this.useSystemProxy && this.systemProxy) {
|
|
136
145
|
// 走系统代理
|
|
137
146
|
const systemSocket = await this.connectToSystemProxy(destination);
|
|
138
|
-
this.__debug && console.info(`[socks] handle connection system`, addrport);
|
|
147
|
+
this.__debug && console.info(`[socks] handle connection system`, addrport, clienAddrport);
|
|
139
148
|
this.setupDataForwarding(clientSocket, systemSocket);
|
|
140
149
|
}
|
|
141
150
|
else {
|
|
142
|
-
this.__debug && console.info(`[socks] handle connection local`, addrport);
|
|
151
|
+
this.__debug && console.info(`[socks] handle connection local`, addrport, clienAddrport);
|
|
143
152
|
// 本地连接
|
|
144
153
|
const localSocket = await this.connectToLocal(destination);
|
|
145
154
|
this.setupDataForwarding(clientSocket, localSocket);
|
|
@@ -212,10 +221,6 @@ class Socks5 {
|
|
|
212
221
|
return undefined;
|
|
213
222
|
const connection = this.connectionPool.get(key);
|
|
214
223
|
// 如果已有连接在池中,复用
|
|
215
|
-
if (this.connectionPool[key] && !this.connectionPool[key].destroyed) {
|
|
216
|
-
return this.connectionPool[key];
|
|
217
|
-
}
|
|
218
|
-
// 如果已有连接在池中,复用
|
|
219
224
|
if (connection && !connection.destroyed) {
|
|
220
225
|
return connection;
|
|
221
226
|
}
|
|
@@ -304,14 +309,14 @@ class Socks5 {
|
|
|
304
309
|
clientSocket.write(new Uint8Array([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
|
|
305
310
|
clientSocket.pipe(targetSocket);
|
|
306
311
|
targetSocket.pipe(clientSocket);
|
|
307
|
-
const
|
|
308
|
-
this.__debug && console.info(`[socks] setupDataForwarding ${
|
|
312
|
+
const addrPort = `${targetSocket.localAddress}:${targetSocket.localPort}`;
|
|
313
|
+
this.__debug && console.info(`[socks] setupDataForwarding ${addrPort}`);
|
|
309
314
|
clientSocket.on('close', () => {
|
|
310
|
-
this.__debug && console.info('[socks] client socket close',
|
|
315
|
+
this.__debug && console.info('[socks] client socket close', addrPort);
|
|
311
316
|
targetSocket.end();
|
|
312
317
|
});
|
|
313
318
|
targetSocket.on('close', () => {
|
|
314
|
-
this.__debug && console.info('[socks] target socket close',
|
|
319
|
+
this.__debug && console.info('[socks] target socket close', addrPort);
|
|
315
320
|
clientSocket.end();
|
|
316
321
|
});
|
|
317
322
|
clientSocket.on('error', (err) => {
|
|
@@ -13,9 +13,9 @@ export default class Ecdh {
|
|
|
13
13
|
exportKey(cryptoKey: CryptoKey, keyFormat?: TKeyFormat): Promise<string>;
|
|
14
14
|
importKey(keyBase64: string, keyFormat?: TKeyFormat, usages?: KeyUsage[]): Promise<CryptoKey>;
|
|
15
15
|
setPrivateKey(privateBase64: string): Promise<boolean>;
|
|
16
|
-
deriveSharedSecret(publicKeyBase64: string, iv
|
|
17
|
-
encode(data: string): Promise<string>;
|
|
18
|
-
encodeiv(data: string): Promise<string>;
|
|
16
|
+
deriveSharedSecret(publicKeyBase64: string, iv?: string): Promise<boolean>;
|
|
17
|
+
encode(data: string, iv?: string): Promise<string>;
|
|
18
|
+
encodeiv(data: string, iv?: string): Promise<string>;
|
|
19
19
|
decode(encrypted: string, iv?: string): Promise<string>;
|
|
20
20
|
decodeiv(encrypted: string): Promise<string>;
|
|
21
21
|
}
|
|
@@ -5,15 +5,16 @@ export default class Ecdh {
|
|
|
5
5
|
privateKey: string;
|
|
6
6
|
sharedSecret: string | undefined;
|
|
7
7
|
iv: string;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
__curve: string;
|
|
9
|
+
__algorithm: string;
|
|
10
|
+
__ecdh: crypto.ECDH | undefined;
|
|
11
11
|
constructor(curve?: string, algorithm?: string);
|
|
12
|
-
|
|
13
|
-
deriveSharedSecret(otherPublicKey: string, iv: string): boolean;
|
|
12
|
+
generateKeys(): void;
|
|
14
13
|
setPrivateKey(privateBase64: string): boolean;
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
setSharedSecret(secretBase64: string): boolean;
|
|
15
|
+
deriveSharedSecret(otherPublicKey: string, iv?: string): boolean;
|
|
16
|
+
encode(data: string, iv?: string): string;
|
|
17
|
+
encodeiv(data: string, iv?: string): string;
|
|
17
18
|
decode(encrypted: string, iv?: string): string;
|
|
18
19
|
decodeiv(encrypted: string): string;
|
|
19
20
|
}
|
|
@@ -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;
|
|
@@ -22,6 +23,7 @@ export declare class Socks5 {
|
|
|
22
23
|
__uuid: string;
|
|
23
24
|
__port: number;
|
|
24
25
|
__event: DEvent;
|
|
26
|
+
__pipeline: DPipeline;
|
|
25
27
|
constructor(upstreamProxy: IProxyConfig, allowedDomains?: string[] | ['*'], debug?: boolean);
|
|
26
28
|
get id(): string;
|
|
27
29
|
get port(): number;
|
|
@@ -32,6 +34,7 @@ export declare class Socks5 {
|
|
|
32
34
|
setAllowedDomains(allowedDomains?: string[]): void;
|
|
33
35
|
private findAvailablePort;
|
|
34
36
|
private handleSocksConnection;
|
|
37
|
+
private _handleSocksConnection;
|
|
35
38
|
/**
|
|
36
39
|
* 回复客户端请求响应数据
|
|
37
40
|
* VER是SOCKS版本,这里应该是0x05;
|