From 6331cdd8ccd696ddeaa571a409f3a5dc6c20c6ab Mon Sep 17 00:00:00 2001 From: xream Date: Mon, 14 Apr 2025 15:28:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20QX=20udp-over-tcp?= =?UTF-8?q?=3Dtrue/sp.v1;=20mihomo=20UDP=20over=20TCP=20=E7=9A=84=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E7=89=88=E6=9C=AC=E9=BB=98=E8=AE=A4=201,=20sing-box?= =?UTF-8?q?=20=E9=BB=98=E8=AE=A4=E4=B8=BA=202?= 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/peggy/qx.js | 4 +++- backend/src/core/proxy-utils/parsers/peggy/qx.peg | 4 +++- backend/src/core/proxy-utils/producers/qx.js | 10 ++++++++++ backend/src/core/proxy-utils/producers/sing-box.js | 11 ++++++++++- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/backend/package.json b/backend/package.json index 2f44037..8bd331f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.19.20", + "version": "2.19.21", "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/peggy/qx.js b/backend/src/core/proxy-utils/parsers/peggy/qx.js index c50f46f..7036705 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/qx.js +++ b/backend/src/core/proxy-utils/parsers/peggy/qx.js @@ -49,7 +49,7 @@ trojan = "trojan" equals address } shadowsocks = "shadowsocks" equals address - (password/method/obfs_ssr/obfs_ss/obfs_host/obfs_uri/ssr_protocol/ssr_protocol_param/tls_pubkey_sha256/tls_alpn/tls_no_session_ticket/tls_no_session_reuse/tls_fingerprint/tls_verification/udp_relay/udp_over_tcp/fast_open/tag/server_check_url/others)* { + (password/method/obfs_ssr/obfs_ss/obfs_host/obfs_uri/ssr_protocol/ssr_protocol_param/tls_pubkey_sha256/tls_alpn/tls_no_session_ticket/tls_no_session_reuse/tls_fingerprint/tls_verification/udp_relay/udp_over_tcp_new/fast_open/tag/server_check_url/others)* { if (proxy.protocol || proxy.type === "ssr") { proxy.type = "ssr"; if (!proxy.protocol) { @@ -157,6 +157,8 @@ aead = comma "aead" equals flag:bool { proxy.aead = flag; } udp_relay = comma "udp-relay" equals flag:bool { proxy.udp = flag; } udp_over_tcp = comma "udp-over-tcp" equals flag:bool { throw new Error("UDP over TCP is not supported"); } +udp_over_tcp_new = comma "udp-over-tcp" equals param:$[^=,]+ { if (param === "sp.v1") { proxy["udp-over-tcp"] = true; proxy["udp-over-tcp-version"] = 1; } else if (param === "true") { proxy["_ssr_python_uot"] = true; } else { throw new Error("Invalid value for udp-over-tcp"); } } + fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; } over_tls = comma "over-tls" equals flag:bool { proxy.tls = flag; } diff --git a/backend/src/core/proxy-utils/parsers/peggy/qx.peg b/backend/src/core/proxy-utils/parsers/peggy/qx.peg index d77712c..6c7fc24 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/qx.peg +++ b/backend/src/core/proxy-utils/parsers/peggy/qx.peg @@ -47,7 +47,7 @@ trojan = "trojan" equals address } shadowsocks = "shadowsocks" equals address - (password/method/obfs_ssr/obfs_ss/obfs_host/obfs_uri/ssr_protocol/ssr_protocol_param/tls_pubkey_sha256/tls_alpn/tls_no_session_ticket/tls_no_session_reuse/tls_fingerprint/tls_verification/udp_relay/udp_over_tcp/fast_open/tag/server_check_url/others)* { + (password/method/obfs_ssr/obfs_ss/obfs_host/obfs_uri/ssr_protocol/ssr_protocol_param/tls_pubkey_sha256/tls_alpn/tls_no_session_ticket/tls_no_session_reuse/tls_fingerprint/tls_verification/udp_relay/udp_over_tcp_new/fast_open/tag/server_check_url/others)* { if (proxy.protocol || proxy.type === "ssr") { proxy.type = "ssr"; if (!proxy.protocol) { @@ -155,6 +155,8 @@ aead = comma "aead" equals flag:bool { proxy.aead = flag; } udp_relay = comma "udp-relay" equals flag:bool { proxy.udp = flag; } udp_over_tcp = comma "udp-over-tcp" equals flag:bool { throw new Error("UDP over TCP is not supported"); } +udp_over_tcp_new = comma "udp-over-tcp" equals param:$[^=,]+ { if (param === "sp.v1") { proxy["udp-over-tcp"] = true; proxy["udp-over-tcp-version"] = 1; } else if (param === "true") { proxy["_ssr_python_uot"] = true; } else { throw new Error("Invalid value for udp-over-tcp"); } } + fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; } over_tls = comma "over-tls" equals flag:bool { proxy.tls = flag; } diff --git a/backend/src/core/proxy-utils/producers/qx.js b/backend/src/core/proxy-utils/producers/qx.js index 0c44409..8068574 100644 --- a/backend/src/core/proxy-utils/producers/qx.js +++ b/backend/src/core/proxy-utils/producers/qx.js @@ -131,6 +131,16 @@ function shadowsocks(proxy, includeUnsupportedProxy) { // udp appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp'); + // udp over tcp + if (proxy['_ssr_python_uot']) { + append(`,udp-over-tcp=true`); + } else if ( + proxy['udp-over-tcp'] && + (!proxy['udp-over-tcp-version'] || proxy['udp-over-tcp-version'] === 1) + ) { + append(`,udp-over-tcp=sp.v1`); + } + // server_check_url result.appendIfPresent( `,server_check_url=${proxy['test-url']}`, diff --git a/backend/src/core/proxy-utils/producers/sing-box.js b/backend/src/core/proxy-utils/producers/sing-box.js index 6ea6571..7620535 100644 --- a/backend/src/core/proxy-utils/producers/sing-box.js +++ b/backend/src/core/proxy-utils/producers/sing-box.js @@ -359,7 +359,16 @@ const ssParser = (proxy = {}) => { if (parsedProxy.server_port < 0 || parsedProxy.server_port > 65535) throw 'invalid port'; if (proxy.uot) parsedProxy.udp_over_tcp = true; - if (proxy['udp-over-tcp']) parsedProxy.udp_over_tcp = true; + if (proxy['udp-over-tcp']) { + parsedProxy.udp_over_tcp = { + enabled: true, + version: + !proxy['udp-over-tcp-version'] || + proxy['udp-over-tcp-version'] === 1 + ? 1 + : 2, + }; + } if (proxy['fast-open']) parsedProxy.udp_fragment = true; networkParser(proxy, parsedProxy); tfoParser(proxy, parsedProxy);