ddan-js 2.9.4 → 2.9.6
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/types/browser.d.ts +1 -1
- package/bin/types/index.d.ts +1 -1
- package/bin/types/modules/node/aliyun.d.ts +1 -1
- package/bin/types/upload.d.ts +2 -0
- package/bin/upload.js +1 -0
- package/package.json +18 -13
- package/bin/lib/browser.js +0 -111
- package/bin/lib/class/event.js +0 -104
- package/bin/lib/class/getset.js +0 -12
- package/bin/lib/class/icon.js +0 -94
- package/bin/lib/class/joker.js +0 -121
- package/bin/lib/class/kvalue.js +0 -29
- package/bin/lib/class/mapping.js +0 -82
- package/bin/lib/class/persist.js +0 -65
- package/bin/lib/class/pipeTask.js +0 -42
- package/bin/lib/class/pipeparallel.js +0 -24
- package/bin/lib/class/store.js +0 -87
- package/bin/lib/class/tracker.js +0 -125
- package/bin/lib/class/watermark.js +0 -63
- package/bin/lib/common/_Symbol.js +0 -5
- package/bin/lib/common/_freeGlobal.js +0 -5
- package/bin/lib/common/_object.js +0 -40
- package/bin/lib/common/_root.js +0 -10
- package/bin/lib/common/internal/asciiToArray.js +0 -13
- package/bin/lib/common/internal/castSlice.js +0 -18
- package/bin/lib/common/internal/createCaseFirst.js +0 -30
- package/bin/lib/common/internal/hasUnicode.js +0 -26
- package/bin/lib/common/internal/nodeTypes.js +0 -26
- package/bin/lib/common/internal/slice.js +0 -46
- package/bin/lib/common/internal/stringToArray.js +0 -18
- package/bin/lib/common/internal/unicodeToArray.js +0 -40
- package/bin/lib/common/internal/unicodeWords.js +0 -67
- package/bin/lib/index.js +0 -114
- package/bin/lib/modules/browser/ecdh.js +0 -124
- package/bin/lib/modules/browser/index.js +0 -4
- package/bin/lib/modules/cdn.js +0 -62
- package/bin/lib/modules/convert/base.js +0 -125
- package/bin/lib/modules/convert/base64.js +0 -114
- package/bin/lib/modules/convert/index.js +0 -99
- package/bin/lib/modules/convert/md5.js +0 -222
- package/bin/lib/modules/convert/pkcs.js +0 -16
- package/bin/lib/modules/convert/utf8.js +0 -106
- package/bin/lib/modules/crypto/base64.js +0 -14
- package/bin/lib/modules/crypto/const.js +0 -7
- package/bin/lib/modules/crypto/index.js +0 -30
- package/bin/lib/modules/crypto/rsa.js +0 -143
- package/bin/lib/modules/crypto/tea.js +0 -79
- package/bin/lib/modules/crypto/uuid.js +0 -34
- package/bin/lib/modules/css.js +0 -137
- package/bin/lib/modules/decorator.js +0 -14
- package/bin/lib/modules/fetch.js +0 -82
- package/bin/lib/modules/gbk.js +0 -46
- package/bin/lib/modules/hook/base.js +0 -60
- package/bin/lib/modules/hook/hooker.js +0 -39
- package/bin/lib/modules/hook/index.js +0 -49
- package/bin/lib/modules/hook/log.js +0 -54
- package/bin/lib/modules/hook/modules/bezier.js +0 -121
- package/bin/lib/modules/hook/modules/debounce.js +0 -127
- package/bin/lib/modules/hook/modules/mutex.js +0 -22
- package/bin/lib/modules/hook/modules/pipeline.js +0 -59
- package/bin/lib/modules/hook/modules/polling.js +0 -20
- package/bin/lib/modules/hook/modules/safeTask.js +0 -25
- package/bin/lib/modules/hook/modules/throttle.js +0 -30
- package/bin/lib/modules/html.js +0 -293
- package/bin/lib/modules/http/index.js +0 -171
- package/bin/lib/modules/http/interceptor.js +0 -22
- package/bin/lib/modules/list/base.js +0 -37
- package/bin/lib/modules/list/index.js +0 -90
- package/bin/lib/modules/logger.js +0 -55
- package/bin/lib/modules/math/index.js +0 -118
- package/bin/lib/modules/mini/diff.js +0 -97
- package/bin/lib/modules/mini/http/index.js +0 -155
- package/bin/lib/modules/mini/index.js +0 -71
- package/bin/lib/modules/node/aliyun.js +0 -156
- package/bin/lib/modules/node/brotli.js +0 -46
- package/bin/lib/modules/node/child.js +0 -18
- package/bin/lib/modules/node/ecdh-web.js +0 -11
- package/bin/lib/modules/node/ecdh.js +0 -115
- package/bin/lib/modules/node/file.js +0 -25
- package/bin/lib/modules/node/index.js +0 -11
- package/bin/lib/modules/node/proxy.js +0 -147
- package/bin/lib/modules/node/rsa-web.js +0 -19
- package/bin/lib/modules/node/socks5.js +0 -424
- package/bin/lib/modules/obj/index.js +0 -184
- package/bin/lib/modules/qs/base.js +0 -5
- package/bin/lib/modules/qs/decode.js +0 -45
- package/bin/lib/modules/qs/encode.js +0 -53
- package/bin/lib/modules/qs/index.js +0 -152
- package/bin/lib/modules/regex.js +0 -16
- package/bin/lib/modules/rsa.js +0 -18
- package/bin/lib/modules/rule/async-validator/index.js +0 -306
- package/bin/lib/modules/rule/async-validator/interface.js +0 -2
- package/bin/lib/modules/rule/async-validator/messages.js +0 -59
- package/bin/lib/modules/rule/async-validator/rule/enum.js +0 -13
- package/bin/lib/modules/rule/async-validator/rule/index.js +0 -16
- package/bin/lib/modules/rule/async-validator/rule/pattern.js +0 -27
- package/bin/lib/modules/rule/async-validator/rule/range.js +0 -54
- package/bin/lib/modules/rule/async-validator/rule/required.js +0 -12
- package/bin/lib/modules/rule/async-validator/rule/type.js +0 -98
- package/bin/lib/modules/rule/async-validator/rule/url.js +0 -55
- package/bin/lib/modules/rule/async-validator/rule/whitespace.js +0 -20
- package/bin/lib/modules/rule/async-validator/util.js +0 -255
- package/bin/lib/modules/rule/async-validator/validator/any.js +0 -16
- package/bin/lib/modules/rule/async-validator/validator/array.js +0 -19
- package/bin/lib/modules/rule/async-validator/validator/boolean.js +0 -20
- package/bin/lib/modules/rule/async-validator/validator/date.js +0 -31
- package/bin/lib/modules/rule/async-validator/validator/enum.js +0 -20
- package/bin/lib/modules/rule/async-validator/validator/float.js +0 -20
- package/bin/lib/modules/rule/async-validator/validator/index.js +0 -36
- package/bin/lib/modules/rule/async-validator/validator/integer.js +0 -20
- package/bin/lib/modules/rule/async-validator/validator/method.js +0 -19
- package/bin/lib/modules/rule/async-validator/validator/number.js +0 -23
- package/bin/lib/modules/rule/async-validator/validator/object.js +0 -19
- package/bin/lib/modules/rule/async-validator/validator/pattern.js +0 -19
- package/bin/lib/modules/rule/async-validator/validator/regexp.js +0 -19
- package/bin/lib/modules/rule/async-validator/validator/required.js +0 -10
- package/bin/lib/modules/rule/async-validator/validator/string.js +0 -24
- package/bin/lib/modules/rule/async-validator/validator/type.js +0 -20
- package/bin/lib/modules/rule/index.js +0 -67
- package/bin/lib/modules/string/index.js +0 -121
- package/bin/lib/modules/string/words.js +0 -33
- package/bin/lib/modules/time/const.js +0 -11
- package/bin/lib/modules/time/dtime.js +0 -132
- package/bin/lib/modules/time/frame.js +0 -49
- package/bin/lib/modules/time/index.js +0 -84
- package/bin/lib/typings/index.js +0 -2
- package/bin/lib/util/function.js +0 -33
- package/bin/lib/util/includes.js +0 -96
- package/bin/lib/util/index.js +0 -26
- package/bin/lib/util/is.js +0 -148
- package/bin/lib/util/to.js +0 -47
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const child_1 = require("./child");
|
|
4
|
-
const convert_1 = require("../convert");
|
|
5
|
-
const getSystemProxy = () => {
|
|
6
|
-
try {
|
|
7
|
-
if (process.platform === 'win32') {
|
|
8
|
-
return getWindowsSystemProxy();
|
|
9
|
-
}
|
|
10
|
-
else if (process.platform === 'darwin') {
|
|
11
|
-
return getMacOSSystemProxy();
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
const getWindowsSystemProxy = async () => {
|
|
22
|
-
do {
|
|
23
|
-
let err, text;
|
|
24
|
-
[err, text] = await child_1.default.child_exec(`reg query "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"`);
|
|
25
|
-
if (err)
|
|
26
|
-
break;
|
|
27
|
-
const proxyEnabledLine = text.split('\n').find((line) => line.includes('ProxyEnable'));
|
|
28
|
-
const ProxyEnable = proxyEnabledLine && proxyEnabledLine.trim().endsWith('1');
|
|
29
|
-
if (!ProxyEnable)
|
|
30
|
-
break;
|
|
31
|
-
const proxyServerLine = text.split('\n').find((line) => line.includes('ProxyServer'));
|
|
32
|
-
const proxyServer = proxyServerLine ? proxyServerLine.split(' ').filter(Boolean).pop() : '';
|
|
33
|
-
if (!proxyServer)
|
|
34
|
-
break;
|
|
35
|
-
// 解析 IP 和端口
|
|
36
|
-
const proxyParts = proxyServer.split(':');
|
|
37
|
-
if (proxyParts.length <= 1)
|
|
38
|
-
break;
|
|
39
|
-
const ipaddress = proxyParts[0];
|
|
40
|
-
const port = +(proxyParts[1] || '');
|
|
41
|
-
if (!ipaddress || !port)
|
|
42
|
-
break;
|
|
43
|
-
return { ipaddress, port };
|
|
44
|
-
} while (false);
|
|
45
|
-
return undefined;
|
|
46
|
-
};
|
|
47
|
-
const getMacOSSystemProxy = async () => {
|
|
48
|
-
do {
|
|
49
|
-
let err, text;
|
|
50
|
-
[err, text] = await child_1.default.child_exec(`networksetup -getwebproxy "Wi-Fi"`);
|
|
51
|
-
if (err)
|
|
52
|
-
break;
|
|
53
|
-
const outputLines = text.split('\n');
|
|
54
|
-
const proxyEnabledLine = outputLines.find((line) => line.includes('Enabled'));
|
|
55
|
-
const isEnabled = proxyEnabledLine && proxyEnabledLine.includes('Yes');
|
|
56
|
-
if (!isEnabled)
|
|
57
|
-
break;
|
|
58
|
-
const proxyServerLine = outputLines.find((line) => line.includes('Server'));
|
|
59
|
-
const proxyPortLine = outputLines.find((line) => line.includes('Port'));
|
|
60
|
-
const ipaddress = proxyServerLine ? proxyServerLine.split(':')[1]?.trim() : null;
|
|
61
|
-
const proxyPort = proxyPortLine ? proxyPortLine.split(':')[1]?.trim() : null;
|
|
62
|
-
const port = +(proxyPort || '');
|
|
63
|
-
if (!ipaddress || !port)
|
|
64
|
-
break;
|
|
65
|
-
return { ipaddress, port };
|
|
66
|
-
} while (false);
|
|
67
|
-
return undefined;
|
|
68
|
-
};
|
|
69
|
-
// { proxy = 'DIRECT'; default = 'DIRECT', rules: string[]
|
|
70
|
-
const toPacScript = (proxy, rules = ['*'], defaultProxy = 'DIRECT') => {
|
|
71
|
-
const _proxy = proxy || defaultProxy || 'DIRECT';
|
|
72
|
-
const _default = defaultProxy || 'DIRECT';
|
|
73
|
-
const content = `
|
|
74
|
-
function FindProxyForURL(url, host) {
|
|
75
|
-
if (host === "127.0.0.1" || host === "localhost") {
|
|
76
|
-
return "DIRECT";
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (isInNet(host, "10.0.0.0", "255.0.0.0") ||
|
|
80
|
-
isInNet(host, "172.16.0.0", "255.240.0.0") ||
|
|
81
|
-
isInNet(host, "192.168.0.0", "255.255.0.0")) {
|
|
82
|
-
return "DIRECT";
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
var _rules = ${JSON.stringify(rules)};
|
|
86
|
-
var _proxy = "${_proxy}";
|
|
87
|
-
var _default = "${_default}";
|
|
88
|
-
|
|
89
|
-
for (var i = 0; i < _rules.length; i++) {
|
|
90
|
-
if (shExpMatch(host, _rules[i])) {
|
|
91
|
-
return _proxy;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return _default;
|
|
96
|
-
}
|
|
97
|
-
`;
|
|
98
|
-
return convert_1.default.toDataUrl(content, 'application/x-ns-proxy-autoconfig');
|
|
99
|
-
};
|
|
100
|
-
const toPacProxy = (ipaddress, port, options) => {
|
|
101
|
-
if (!ipaddress || !port)
|
|
102
|
-
return '';
|
|
103
|
-
const { type = 'ALL', direct = false } = options || {};
|
|
104
|
-
let text = '';
|
|
105
|
-
const _type = type ? type.toUpperCase() : '';
|
|
106
|
-
switch (_type) {
|
|
107
|
-
case 'ALL':
|
|
108
|
-
text = `SOCKS5 ${ipaddress}:${port};PROXY ${ipaddress}:${port}`;
|
|
109
|
-
break;
|
|
110
|
-
case 'PROXY':
|
|
111
|
-
text = `PROXY ${ipaddress}:${port}`;
|
|
112
|
-
break;
|
|
113
|
-
case 'SOCKS5':
|
|
114
|
-
text = `SOCKS5 ${ipaddress}:${port}`;
|
|
115
|
-
break;
|
|
116
|
-
default:
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
if (!text && !direct)
|
|
120
|
-
return '';
|
|
121
|
-
const temps = [];
|
|
122
|
-
text && temps.push(text);
|
|
123
|
-
direct && temps.push('DIRECT');
|
|
124
|
-
return temps.join(';');
|
|
125
|
-
};
|
|
126
|
-
/**
|
|
127
|
-
* 生成 pac script 内容
|
|
128
|
-
* @param host
|
|
129
|
-
* @param port
|
|
130
|
-
* @param options
|
|
131
|
-
* @returns
|
|
132
|
-
*/
|
|
133
|
-
const pacScript = async (host, port, options) => {
|
|
134
|
-
const { type = "SOCKS5", rules = ['*'], useSystem } = options || {};
|
|
135
|
-
const pac_proxy = toPacProxy(host, port, { type });
|
|
136
|
-
if (!pac_proxy)
|
|
137
|
-
return "";
|
|
138
|
-
let pac_default = undefined;
|
|
139
|
-
if (useSystem) {
|
|
140
|
-
const sysproxy = await getSystemProxy();
|
|
141
|
-
if (sysproxy) {
|
|
142
|
-
pac_default = toPacProxy(sysproxy?.ipaddress || '', sysproxy?.port || 0, { direct: true });
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return toPacScript(pac_proxy, rules || [], pac_default);
|
|
146
|
-
};
|
|
147
|
-
exports.default = { getSystemProxy, toPacScript, toPacProxy, pacScript };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const rsa_1 = require("../crypto/rsa");
|
|
4
|
-
const crypto_1 = require("crypto");
|
|
5
|
-
const getSubtle = () => crypto_1.default.webcrypto.subtle;
|
|
6
|
-
const generateKeys = () => rsa_1.default.generateKeys(getSubtle());
|
|
7
|
-
// SHA256: 256 - 2 - 2*32 = 190
|
|
8
|
-
// SHA1: 256 - 2 - 2*20 = 214
|
|
9
|
-
const encrypt = async (data, publicKey) => rsa_1.default.encrypt(getSubtle(), data, publicKey);
|
|
10
|
-
const decrypt = async (encryptedBase64, privateKey) => rsa_1.default.decrypt(getSubtle(), encryptedBase64, privateKey);
|
|
11
|
-
const encode = async (data) => rsa_1.default.encrypt(getSubtle(), data, rsa_1.default.RSAPublicKey);
|
|
12
|
-
const decode = async (encryptedBase64) => rsa_1.default.decrypt(getSubtle(), encryptedBase64, rsa_1.default.RSAPrivateKey);
|
|
13
|
-
exports.default = {
|
|
14
|
-
generateKeys,
|
|
15
|
-
encrypt,
|
|
16
|
-
decrypt,
|
|
17
|
-
encode,
|
|
18
|
-
decode,
|
|
19
|
-
};
|
|
@@ -1,424 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Socks5 = void 0;
|
|
4
|
-
const net_1 = require("net");
|
|
5
|
-
const socks_1 = require("socks");
|
|
6
|
-
const uuid_1 = require("../crypto/uuid");
|
|
7
|
-
const index_1 = require("../qs/index");
|
|
8
|
-
const list_1 = require("../list");
|
|
9
|
-
const event_1 = require("../../class/event");
|
|
10
|
-
const pipeline_1 = require("../hook/modules/pipeline");
|
|
11
|
-
const Socks5Event = {
|
|
12
|
-
Error: 'error',
|
|
13
|
-
};
|
|
14
|
-
class Socks5 {
|
|
15
|
-
upstreamProxy;
|
|
16
|
-
server = null;
|
|
17
|
-
clientSockets = new Set();
|
|
18
|
-
systemProxy = null;
|
|
19
|
-
useSystemProxy = false;
|
|
20
|
-
__debug = false;
|
|
21
|
-
__uuid;
|
|
22
|
-
__port = 0;
|
|
23
|
-
__event;
|
|
24
|
-
__pipeline;
|
|
25
|
-
__logger;
|
|
26
|
-
__totalReceived = 0;
|
|
27
|
-
__totalSent = 0;
|
|
28
|
-
__rules = [];
|
|
29
|
-
constructor(upstreamProxy, debug = false, logger) {
|
|
30
|
-
this.__event = new event_1.default();
|
|
31
|
-
this.upstreamProxy = this.filterProxyConfigs(upstreamProxy);
|
|
32
|
-
this._updateRules();
|
|
33
|
-
this.__debug = debug;
|
|
34
|
-
this.__uuid = (0, uuid_1.default)();
|
|
35
|
-
this.__pipeline = new pipeline_1.default(1);
|
|
36
|
-
this.__logger = logger || console;
|
|
37
|
-
}
|
|
38
|
-
get id() {
|
|
39
|
-
return this.__uuid;
|
|
40
|
-
}
|
|
41
|
-
get port() {
|
|
42
|
-
return this.__port;
|
|
43
|
-
}
|
|
44
|
-
get url() {
|
|
45
|
-
if (!this.__port)
|
|
46
|
-
return '';
|
|
47
|
-
return `socks5://127.0.0.1:${this.__port}`;
|
|
48
|
-
}
|
|
49
|
-
get totalReceived() {
|
|
50
|
-
return this.__totalReceived;
|
|
51
|
-
}
|
|
52
|
-
get totalSent() {
|
|
53
|
-
return this.__totalSent;
|
|
54
|
-
}
|
|
55
|
-
get rules() {
|
|
56
|
-
return this.__rules;
|
|
57
|
-
}
|
|
58
|
-
validateProxyConfig(proxyConfig) {
|
|
59
|
-
const { ipaddress, port, userId, password } = proxyConfig || {};
|
|
60
|
-
if (!ipaddress || typeof ipaddress !== 'string') {
|
|
61
|
-
return '无效的上游代理 IP 地址';
|
|
62
|
-
}
|
|
63
|
-
if (!port || typeof port !== 'number') {
|
|
64
|
-
return '无效的上游代理端口';
|
|
65
|
-
}
|
|
66
|
-
if (!userId || typeof userId !== 'string') {
|
|
67
|
-
return '无效的上游代理用户名';
|
|
68
|
-
}
|
|
69
|
-
if (!password || typeof password !== 'string') {
|
|
70
|
-
return '无效的上游代理密码';
|
|
71
|
-
}
|
|
72
|
-
return '';
|
|
73
|
-
}
|
|
74
|
-
filterProxyConfigs(proxyConfig) {
|
|
75
|
-
let configs = [];
|
|
76
|
-
if (proxyConfig && Array.isArray(proxyConfig)) {
|
|
77
|
-
configs = proxyConfig;
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
configs = [proxyConfig];
|
|
81
|
-
}
|
|
82
|
-
const filterCfgs = [];
|
|
83
|
-
for (const cfg of configs) {
|
|
84
|
-
if (!this.validateProxyConfig(cfg)) {
|
|
85
|
-
filterCfgs.push(cfg);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return filterCfgs;
|
|
89
|
-
}
|
|
90
|
-
async start(startPort = 8838) {
|
|
91
|
-
if (this.upstreamProxy.length <= 0)
|
|
92
|
-
return 0;
|
|
93
|
-
if (this.server) {
|
|
94
|
-
this.__debug && console.info(`[socks5] server is already running`);
|
|
95
|
-
return this.__port;
|
|
96
|
-
}
|
|
97
|
-
const port = await this.findAvailablePort(startPort);
|
|
98
|
-
if (!port)
|
|
99
|
-
return 0;
|
|
100
|
-
this.__port = port;
|
|
101
|
-
this.server = net_1.default.createServer((socket) => this.handleSocksConnection(socket));
|
|
102
|
-
this.server.listen(port, () => {
|
|
103
|
-
this.__debug && this.__logger?.info(`[socks5] server is running on port ${port}`);
|
|
104
|
-
});
|
|
105
|
-
this.server.on('error', (err) => {
|
|
106
|
-
this.__logger?.error('[socks5] server error:', err);
|
|
107
|
-
this.close();
|
|
108
|
-
});
|
|
109
|
-
return port;
|
|
110
|
-
}
|
|
111
|
-
setUpstreamProxy(upstreamProxy) {
|
|
112
|
-
if (!upstreamProxy)
|
|
113
|
-
return false;
|
|
114
|
-
const configs = this.filterProxyConfigs(upstreamProxy);
|
|
115
|
-
if (!configs || configs.length <= 0)
|
|
116
|
-
return false;
|
|
117
|
-
this.upstreamProxy = configs;
|
|
118
|
-
this._updateRules();
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
setSystemProxy(use, config) {
|
|
122
|
-
this.useSystemProxy = use;
|
|
123
|
-
if (use && config && config.ipaddress && config.port) {
|
|
124
|
-
this.systemProxy = config;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* 查找可用端口
|
|
129
|
-
* @param startPort
|
|
130
|
-
* @param maxRetries
|
|
131
|
-
* @returns
|
|
132
|
-
*/
|
|
133
|
-
async findAvailablePort(startPort, maxRetries = 200 // 最大重试次数
|
|
134
|
-
) {
|
|
135
|
-
let port = startPort;
|
|
136
|
-
let retries = 0;
|
|
137
|
-
while (retries < maxRetries) {
|
|
138
|
-
try {
|
|
139
|
-
await new Promise((resolve, reject) => {
|
|
140
|
-
const testServer = net_1.default.createServer();
|
|
141
|
-
testServer.unref();
|
|
142
|
-
testServer.on('error', reject);
|
|
143
|
-
testServer.listen(port, () => {
|
|
144
|
-
testServer.close(() => resolve());
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
return port; // 找到可用端口
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
retries++; // 记录重试次数
|
|
151
|
-
port++; // 尝试下一个端口
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
this.__debug && this.__logger?.warn('[socks5] findAvailablePort failed');
|
|
155
|
-
return 0;
|
|
156
|
-
}
|
|
157
|
-
async handleSocksConnection(clientSocket) {
|
|
158
|
-
let addrport = '';
|
|
159
|
-
try {
|
|
160
|
-
if (!clientSocket)
|
|
161
|
-
return;
|
|
162
|
-
this.clientSockets.add(clientSocket);
|
|
163
|
-
clientSocket.on('close', () => {
|
|
164
|
-
this.clientSockets.delete(clientSocket);
|
|
165
|
-
clientSocket?.destroy();
|
|
166
|
-
});
|
|
167
|
-
await this.performHandshake(clientSocket);
|
|
168
|
-
const destination = await this.parseClientRequest(clientSocket);
|
|
169
|
-
const addr = destination.addr;
|
|
170
|
-
addrport = `${addr}:${destination.port}`;
|
|
171
|
-
this.__debug && this.__logger?.info(`[socks5] connection`, addrport);
|
|
172
|
-
const proxyConfig = this.findProxyConfig(addr);
|
|
173
|
-
if (proxyConfig) {
|
|
174
|
-
// 走上游代理
|
|
175
|
-
const upstreamSocket = await this.connectToUpstreamProxy(destination, proxyConfig);
|
|
176
|
-
this.__logger?.info(`[socks5] connection upstream ${addrport}, use ${proxyConfig.ipaddress}:${proxyConfig.port}`);
|
|
177
|
-
this.setupDataForwarding(clientSocket, upstreamSocket, 'upstream');
|
|
178
|
-
}
|
|
179
|
-
else if (this.useSystemProxy && this.systemProxy && !index_1.default.isLocalIpAddress(addr)) {
|
|
180
|
-
// 走系统代理
|
|
181
|
-
const systemSocket = await this.connectToSystemProxy(destination);
|
|
182
|
-
this.__debug && console.info(`[socks5] connection system`, addrport);
|
|
183
|
-
this.setupDataForwarding(clientSocket, systemSocket, 'system');
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
this.__debug && console.info(`[socks5] connection local`, addrport);
|
|
187
|
-
// 本地连接
|
|
188
|
-
const localSocket = await this.connectToLocal(destination);
|
|
189
|
-
this.setupDataForwarding(clientSocket, localSocket, 'local');
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
catch (err) {
|
|
193
|
-
this.__debug && this.__logger?.error('[socks5] connection failed:', err);
|
|
194
|
-
// this.__event.emit(Socks5Event.Error, err, addrport)
|
|
195
|
-
clientSocket.end(new Uint8Array([0x05, 0x01]));
|
|
196
|
-
this._emit('error', err, addrport);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* 回复客户端请求响应数据
|
|
201
|
-
* VER是SOCKS版本,这里应该是0x05;
|
|
202
|
-
* REP应答字段:
|
|
203
|
-
* 0x00表示成功
|
|
204
|
-
* 0x01普通SOCKS服务器连接失败
|
|
205
|
-
* 0x02现有规则不允许连接
|
|
206
|
-
* 0x03网络不可达
|
|
207
|
-
* 0x04主机不可达
|
|
208
|
-
* 0x05连接被拒
|
|
209
|
-
* 0x06 TTL超时
|
|
210
|
-
* 0x07不支持的命令
|
|
211
|
-
* 0x08不支持的地址类型
|
|
212
|
-
* 0x09 - 0xFF未定义
|
|
213
|
-
*/
|
|
214
|
-
/**
|
|
215
|
-
* 握手
|
|
216
|
-
* @param clientSocket
|
|
217
|
-
* @returns
|
|
218
|
-
*/
|
|
219
|
-
performHandshake(clientSocket) {
|
|
220
|
-
return new Promise((resolve, reject) => {
|
|
221
|
-
clientSocket.once('data', (data) => {
|
|
222
|
-
if (data[0] !== 0x05) {
|
|
223
|
-
return reject(new Error('Unsupported SOCKS version'));
|
|
224
|
-
}
|
|
225
|
-
clientSocket.write(new Uint8Array([0x05, 0x00]));
|
|
226
|
-
resolve();
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* 解析请求
|
|
232
|
-
* @param clientSocket
|
|
233
|
-
* @returns
|
|
234
|
-
*/
|
|
235
|
-
parseClientRequest(clientSocket) {
|
|
236
|
-
return new Promise((resolve, reject) => {
|
|
237
|
-
clientSocket.once('data', (data) => {
|
|
238
|
-
let addr;
|
|
239
|
-
let port;
|
|
240
|
-
if (data[1] !== 0x01) {
|
|
241
|
-
return reject(new Error('Unsupported command'));
|
|
242
|
-
}
|
|
243
|
-
// 3 为 addrtype
|
|
244
|
-
// remotePort = data.readUInt16BE(data.length - 2); //最后两位为端口值
|
|
245
|
-
if (data[3] === 0x01) {
|
|
246
|
-
// IPv4 地址
|
|
247
|
-
addr = data.slice(4, 8).join('.');
|
|
248
|
-
port = data.readUInt16BE(8);
|
|
249
|
-
}
|
|
250
|
-
else if (data[3] === 0x03) {
|
|
251
|
-
// 域名
|
|
252
|
-
const len = data[4];
|
|
253
|
-
addr = data.slice(5, 5 + len).toString();
|
|
254
|
-
port = data.readUInt16BE(5 + len);
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
return reject(new Error('Unsupported address type'));
|
|
258
|
-
}
|
|
259
|
-
resolve({ addr, port });
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
// 上游代理连接
|
|
264
|
-
async connectToUpstreamProxy(destination, config) {
|
|
265
|
-
const options = {
|
|
266
|
-
proxy: {
|
|
267
|
-
ipaddress: config.ipaddress,
|
|
268
|
-
port: config.port,
|
|
269
|
-
type: 5,
|
|
270
|
-
userId: config.userId,
|
|
271
|
-
password: config.password,
|
|
272
|
-
},
|
|
273
|
-
command: 'connect',
|
|
274
|
-
destination: {
|
|
275
|
-
host: destination.addr,
|
|
276
|
-
port: destination.port,
|
|
277
|
-
},
|
|
278
|
-
};
|
|
279
|
-
try {
|
|
280
|
-
return await this.connectToProxy(options);
|
|
281
|
-
}
|
|
282
|
-
catch (err) {
|
|
283
|
-
throw new Error('Failed to connect to upstream proxy: ' + err);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
// 系统代理连接
|
|
287
|
-
async connectToSystemProxy(destination) {
|
|
288
|
-
const options = {
|
|
289
|
-
proxy: { ...this.systemProxy, type: 5 },
|
|
290
|
-
command: 'connect',
|
|
291
|
-
destination: {
|
|
292
|
-
host: destination.addr,
|
|
293
|
-
port: destination.port,
|
|
294
|
-
},
|
|
295
|
-
};
|
|
296
|
-
try {
|
|
297
|
-
return await this.connectToProxy(options);
|
|
298
|
-
}
|
|
299
|
-
catch (err) {
|
|
300
|
-
throw new Error('Failed to connect to system proxy: ' + err);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
async connectToProxy(options) {
|
|
304
|
-
const { socket } = await socks_1.SocksClient.createConnection(options);
|
|
305
|
-
return socket;
|
|
306
|
-
}
|
|
307
|
-
// 本地连接
|
|
308
|
-
async connectToLocal(destination) {
|
|
309
|
-
return new Promise((resolve, reject) => {
|
|
310
|
-
const localSocket = net_1.default.createConnection(destination.port, destination.addr, () => {
|
|
311
|
-
resolve(localSocket);
|
|
312
|
-
});
|
|
313
|
-
localSocket.on('error', (err) => {
|
|
314
|
-
reject(err);
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
setupDataForwarding(clientSocket, targetSocket, type = 'local') {
|
|
319
|
-
clientSocket.write(new Uint8Array([0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
|
|
320
|
-
clientSocket.pipe(targetSocket);
|
|
321
|
-
targetSocket.pipe(clientSocket);
|
|
322
|
-
const addrPort = `${targetSocket.localAddress}:${targetSocket.localPort}`;
|
|
323
|
-
this.__debug && console.info(`[socks5] setupDataForwarding ${addrPort}`);
|
|
324
|
-
if (type === 'upstream') {
|
|
325
|
-
targetSocket.on('data', (buf) => {
|
|
326
|
-
this.__totalSent += buf.length;
|
|
327
|
-
});
|
|
328
|
-
clientSocket.on('data', (buf) => {
|
|
329
|
-
this.__totalReceived += buf.length;
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
clientSocket.on('close', () => {
|
|
333
|
-
this.__debug && console.info('[socks5] client socket close', addrPort);
|
|
334
|
-
targetSocket.end();
|
|
335
|
-
});
|
|
336
|
-
targetSocket.on('close', () => {
|
|
337
|
-
this.__debug && console.info('[socks5] target socket close', addrPort);
|
|
338
|
-
clientSocket.end();
|
|
339
|
-
});
|
|
340
|
-
clientSocket.on('error', (err) => {
|
|
341
|
-
this.__debug && console.error('[socks5] client socket error:', err?.message);
|
|
342
|
-
targetSocket.end();
|
|
343
|
-
});
|
|
344
|
-
targetSocket.on('error', (err) => {
|
|
345
|
-
this.__debug && console.error('[socks5] target socket error:', err?.message);
|
|
346
|
-
clientSocket.end();
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
findProxyConfig(addr) {
|
|
350
|
-
if (index_1.default.isLocalIpAddress(addr))
|
|
351
|
-
return undefined;
|
|
352
|
-
for (const cfg of this.upstreamProxy) {
|
|
353
|
-
if (this.isAllowedDomain(addr, cfg.rules || []))
|
|
354
|
-
return cfg;
|
|
355
|
-
}
|
|
356
|
-
return undefined;
|
|
357
|
-
}
|
|
358
|
-
isAllowedDomain(addr, rules) {
|
|
359
|
-
if (index_1.default.isLocalIpAddress(addr))
|
|
360
|
-
return false;
|
|
361
|
-
if (!rules || !Array.isArray(rules))
|
|
362
|
-
return false;
|
|
363
|
-
for (const pattern of rules) {
|
|
364
|
-
if (pattern === '*')
|
|
365
|
-
return true;
|
|
366
|
-
if (index_1.default.shExpMatch(addr, pattern))
|
|
367
|
-
return true;
|
|
368
|
-
}
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
|
-
close() {
|
|
372
|
-
try {
|
|
373
|
-
if (!this.server)
|
|
374
|
-
return;
|
|
375
|
-
this.__debug && this.__logger?.info('[socks5] closing SOCKS5 proxy server...');
|
|
376
|
-
this.server.close((err) => {
|
|
377
|
-
if (err) {
|
|
378
|
-
this.__debug && this.__logger?.error('[socks5] closing the server failed:', err);
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
// 销毁客户端 socket
|
|
382
|
-
this.clientSockets.forEach((socket) => socket?.destroy());
|
|
383
|
-
this.clientSockets.clear();
|
|
384
|
-
// 销毁所有连接池中的 socket
|
|
385
|
-
// Object.values(this.connectionPool).forEach((socket) => socket?.destroy())
|
|
386
|
-
this.server = null;
|
|
387
|
-
this.__port = 0;
|
|
388
|
-
}
|
|
389
|
-
catch (error) {
|
|
390
|
-
this.__debug && this.__logger?.error('[socks5] close error:', error);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
on(name, listener) {
|
|
394
|
-
if (!name || !listener)
|
|
395
|
-
return;
|
|
396
|
-
this.__event.off(name, listener);
|
|
397
|
-
this.__event.on(name, listener);
|
|
398
|
-
}
|
|
399
|
-
off(name, listener) {
|
|
400
|
-
if (!name)
|
|
401
|
-
return;
|
|
402
|
-
this.__event.off(name, listener);
|
|
403
|
-
}
|
|
404
|
-
resetStatistics() {
|
|
405
|
-
this.__totalReceived = 0;
|
|
406
|
-
this.__totalSent = 0;
|
|
407
|
-
}
|
|
408
|
-
_emit(name, ...args) {
|
|
409
|
-
try {
|
|
410
|
-
if (!name)
|
|
411
|
-
return;
|
|
412
|
-
this.__event.emit(name, ...args);
|
|
413
|
-
}
|
|
414
|
-
catch (error) {
|
|
415
|
-
// nothing
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
_updateRules() {
|
|
419
|
-
if (!this.upstreamProxy)
|
|
420
|
-
return;
|
|
421
|
-
this.__rules = list_1.default.distinct(this.upstreamProxy.reduce((prev, current) => prev.concat(current?.rules || []), []));
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
exports.Socks5 = Socks5;
|