diff --git a/backend/package.json b/backend/package.json index f2c23f9..3a479ab 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.19.79", + "version": "2.19.81", "description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.", "main": "src/main.js", "scripts": { @@ -32,6 +32,7 @@ "dns-packet": "^5.6.1", "dotenv": "^16.4.7", "express": "^4.17.1", + "fetch-socks": "^1.3.2", "http-proxy-middleware": "^3.0.3", "ip-address": "^9.0.5", "js-base64": "^3.7.2", diff --git a/backend/pnpm-lock.yaml b/backend/pnpm-lock.yaml index 2f6590e..30cd895 100644 --- a/backend/pnpm-lock.yaml +++ b/backend/pnpm-lock.yaml @@ -40,6 +40,9 @@ importers: express: specifier: ^4.17.1 version: 4.21.2 + fetch-socks: + specifier: ^1.3.2 + version: 1.3.2 http-proxy-middleware: specifier: ^3.0.3 version: 3.0.3 @@ -1974,6 +1977,9 @@ packages: fastq@1.18.0: resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} + fetch-socks@1.3.2: + resolution: {integrity: sha512-vkH5+Zgj2yEbU57Cei0iyLgTZ4OkEKJj56Xu3ViB5dpsl599JgEooQ3x6NVagIFRHWnWJ+7K0MO0aIV1TMgvnw==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3636,6 +3642,10 @@ packages: resolution: {integrity: sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==} engines: {node: '>=0.10.0'} + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + snapdragon-node@2.1.1: resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} engines: {node: '>=0.10.0'} @@ -3648,6 +3658,10 @@ packages: resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} engines: {node: '>=0.10.0'} + socks@2.8.6: + resolution: {integrity: sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + source-map-generator@0.8.0: resolution: {integrity: sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA==} engines: {node: '>= 10'} @@ -6553,6 +6567,11 @@ snapshots: dependencies: reusify: 1.0.4 + fetch-socks@1.3.2: + dependencies: + socks: 2.8.6 + undici: 7.4.0 + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -8424,6 +8443,8 @@ snapshots: slash@1.0.0: {} + smart-buffer@4.2.0: {} + snapdragon-node@2.1.1: dependencies: define-property: 1.0.0 @@ -8447,6 +8468,11 @@ snapshots: transitivePeerDependencies: - supports-color + socks@2.8.6: + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + source-map-generator@0.8.0: {} source-map-resolve@0.5.3: diff --git a/backend/src/vendor/open-api.js b/backend/src/vendor/open-api.js index f71ed34..8e07288 100644 --- a/backend/src/vendor/open-api.js +++ b/backend/src/vendor/open-api.js @@ -18,6 +18,26 @@ function isPlainObject(obj) { ); } +function parseSocks5Uri(uri) { + // eslint-disable-next-line no-unused-vars + let [__, username, password, server, port, query, name] = uri.match( + /^socks5:\/\/(?:(.*?):(.*?)@)?(.*?)(?::(\d+?))?(\?.*?)?(?:#(.*?))?$/, + ); + if (port) { + port = parseInt(port, 10); + } else { + $.error(`port is not present in line: ${uri}`); + throw new Error(`port is not present in line: ${uri}`); + } + return { + type: 5, + host: server, + port, + + userId: username != null ? decodeURIComponent(username) : undefined, + password: password != null ? decodeURIComponent(password) : undefined, + }; +} export class OpenAPI { constructor(name = 'untitled', debug = false) { this.name = name; @@ -393,6 +413,7 @@ export function HTTP(defaultOptions = { baseURL: '' }) { } if (isNode) { const undici = eval("require('undici')"); + const { socksDispatcher } = eval("require('fetch-socks')"); const { ProxyAgent, EnvHttpProxyAgent, @@ -422,16 +443,34 @@ export function HTTP(defaultOptions = { baseURL: '' }) { ).toString('base64')}`, }; } + let dispatcher; + if (!opts.proxy) { + const allProxy = + eval('process.env.all_proxy') || + eval('process.env.ALL_PROXY'); + if (allProxy && /^socks5:\/\//.test(allProxy)) { + opts.proxy = allProxy; + } + } + if (opts.proxy) { + if (/^socks5:\/\//.test(opts.proxy)) { + dispatcher = socksDispatcher( + parseSocks5Uri(opts.proxy), + agentOpts, + ); + } else { + dispatcher = new ProxyAgent({ + ...agentOpts, + uri: opts.proxy, + }); + } + } else { + dispatcher = new EnvHttpProxyAgent(agentOpts); + } const response = await request(opts.url, { ...opts, method: method.toUpperCase(), - dispatcher: (opts.proxy - ? new ProxyAgent({ - ...agentOpts, - uri: opts.proxy, - }) - : new EnvHttpProxyAgent(agentOpts) - ).compose( + dispatcher: dispatcher.compose( interceptors.redirect({ maxRedirections: 3, throwOnMaxRedirects: true,