From 37fc7ac88e1597cf19e4469844ff8e64cc9a4876 Mon Sep 17 00:00:00 2001 From: xream Date: Tue, 27 May 2025 00:34:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20VMess=20=E6=94=AF=E6=8C=81=20kcp/quic(?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E5=A4=84=E7=90=86=20type,=20host,=20path,=20?= =?UTF-8?q?fp,=20alpn,=20tls=E7=AD=89=E5=8F=82=E6=95=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package.json | 2 +- backend/src/core/proxy-utils/parsers/index.js | 38 +++++++++++++-- backend/src/core/proxy-utils/producers/uri.js | 47 ++++++++++++++----- 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/backend/package.json b/backend/package.json index b34a416..087f3e0 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.19.52", + "version": "2.19.54", "description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.", "main": "src/main.js", "scripts": { diff --git a/backend/src/core/proxy-utils/parsers/index.js b/backend/src/core/proxy-utils/parsers/index.js index 67f578a..68a6424 100644 --- a/backend/src/core/proxy-utils/parsers/index.js +++ b/backend/src/core/proxy-utils/parsers/index.js @@ -439,7 +439,16 @@ function URI_VMess() { type: 'vmess', server, port, - cipher: getIfPresent(params.scy, 'auto'), + // https://github.com/2dust/v2rayN/wiki/Description-of-VMess-share-link + // https://github.com/XTLS/Xray-core/issues/91 + cipher: [ + 'auto', + 'aes-128-gcm', + 'chacha20-poly1305', + 'none', + ].includes(params.scy) + ? params.scy + : 'auto', uuid: params.id, alterId: parseInt( getIfPresent(params.aid ?? params.alterId, 0), @@ -473,8 +482,8 @@ function URI_VMess() { ['http'].includes(params.type) ) { proxy.network = 'http'; - } else if (['grpc'].includes(params.net)) { - proxy.network = 'grpc'; + } else if (['grpc', 'kcp', 'quic'].includes(params.net)) { + proxy.network = params.net; } else if ( params.net === 'httpupgrade' || proxy.network === 'httpupgrade' @@ -524,13 +533,28 @@ function URI_VMess() { } } // 传输层应该有配置, 暂时不考虑兼容不给配置的节点 - if (transportPath || transportHost) { + if ( + transportPath || + transportHost || + ['kcp', 'quic'].includes(proxy.network) + ) { if (['grpc'].includes(proxy.network)) { proxy[`${proxy.network}-opts`] = { 'grpc-service-name': getIfNotBlank(transportPath), '_grpc-type': getIfNotBlank(params.type), '_grpc-authority': getIfNotBlank(params.authority), }; + } else if (['kcp', 'quic'].includes(proxy.network)) { + proxy[`${proxy.network}-opts`] = { + [`_${proxy.network}-type`]: getIfNotBlank( + params.type, + ), + [`_${proxy.network}-host`]: getIfNotBlank( + getIfNotBlank(transportHost), + ), + [`_${proxy.network}-path`]: + getIfNotBlank(transportPath), + }; } else { const opts = { path: getIfNotBlank(transportPath), @@ -546,6 +570,12 @@ function URI_VMess() { delete proxy.network; } } + + proxy['client-fingerprint'] = params.fp; + proxy.alpn = params.alpn ? params.alpn.split(',') : undefined; + // 然而 wiki 和 app 实测中都没有字段表示这个 + // proxy['skip-cert-verify'] = /(TRUE)|1/i.test(params.allowInsecure); + return proxy; } }; diff --git a/backend/src/core/proxy-utils/producers/uri.js b/backend/src/core/proxy-utils/producers/uri.js index dc5c732..f2f1cd2 100644 --- a/backend/src/core/proxy-utils/producers/uri.js +++ b/backend/src/core/proxy-utils/producers/uri.js @@ -119,12 +119,17 @@ export default function URI_Producer() { v: '2', ps: proxy.name, add: proxy.server, - port: proxy.port, + port: `${proxy.port}`, id: proxy.uuid, - type, - aid: proxy.alterId || 0, + aid: `${proxy.alterId || 0}`, + scy: proxy.cipher, net, + type, tls: proxy.tls ? 'tls' : '', + alpn: Array.isArray(proxy.alpn) + ? proxy.alpn.join(',') + : proxy.alpn, + fp: proxy['client-fingerprint'], }; if (proxy.tls && proxy.sni) { result.sni = proxy.sni; @@ -135,16 +140,7 @@ export default function URI_Producer() { proxy[`${proxy.network}-opts`]?.path; let vmessTransportHost = proxy[`${proxy.network}-opts`]?.headers?.Host; - if (vmessTransportPath) { - result.path = Array.isArray(vmessTransportPath) - ? vmessTransportPath[0] - : vmessTransportPath; - } - if (vmessTransportHost) { - result.host = Array.isArray(vmessTransportHost) - ? vmessTransportHost[0] - : vmessTransportHost; - } + if (['grpc'].includes(proxy.network)) { result.path = proxy[`${proxy.network}-opts`]?.[ @@ -156,6 +152,31 @@ export default function URI_Producer() { 'gun'; result.host = proxy[`${proxy.network}-opts`]?.['_grpc-authority']; + } else if (['kcp', 'quic'].includes(proxy.network)) { + // https://github.com/XTLS/Xray-core/issues/91 + result.type = + proxy[`${proxy.network}-opts`]?.[ + `_${proxy.network}-type` + ] || 'none'; + result.host = + proxy[`${proxy.network}-opts`]?.[ + `_${proxy.network}-host` + ]; + result.path = + proxy[`${proxy.network}-opts`]?.[ + `_${proxy.network}-path` + ]; + } else { + if (vmessTransportPath) { + result.path = Array.isArray(vmessTransportPath) + ? vmessTransportPath[0] + : vmessTransportPath; + } + if (vmessTransportHost) { + result.host = Array.isArray(vmessTransportHost) + ? vmessTransportHost[0] + : vmessTransportHost; + } } } result = 'vmess://' + Base64.encode(JSON.stringify(result));