From 060415584e8fb2a45ce306dc1b9712da0750fb58 Mon Sep 17 00:00:00 2001 From: xream Date: Tue, 30 Jan 2024 01:53:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20tls=20=E7=9A=84=20?= =?UTF-8?q?plugin=20=E4=B8=AD=E8=B7=B3=E8=BF=87=E8=AF=81=E4=B9=A6=E9=AA=8C?= =?UTF-8?q?=E8=AF=81;=20Surge=20Shadow=20TLS=20=E9=BB=98=E8=AE=A4=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E4=B8=BA=202;=20sing-box=20=E6=94=AF=E6=8C=81=20Shado?= =?UTF-8?q?wsocks=20Shadow=20TLS?= 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 | 1 - .../core/proxy-utils/parsers/peggy/surge.js | 17 +++++++++ .../core/proxy-utils/parsers/peggy/surge.peg | 17 +++++++++ .../src/core/proxy-utils/producers/clash.js | 6 +++ .../core/proxy-utils/producers/clashmeta.js | 19 ++++++++++ .../proxy-utils/producers/shadowrocket.js | 7 +++- .../core/proxy-utils/producers/sing-box.js | 38 +++++++++++++++++-- .../src/core/proxy-utils/producers/stash.js | 6 +++ 9 files changed, 107 insertions(+), 6 deletions(-) diff --git a/backend/package.json b/backend/package.json index ed9db7a..ed2d2e9 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.14.191", + "version": "2.14.192", "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 82acaf6..60bda0b 100644 --- a/backend/src/core/proxy-utils/parsers/index.js +++ b/backend/src/core/proxy-utils/parsers/index.js @@ -41,7 +41,6 @@ function URI_SS() { } content = Base64.decode(content); if (query) { - console.log(query); if (/(&|\?)v2ray-plugin=/.test(query)) { const parsed = query.match(/(&|\?)v2ray-plugin=(.*?)(&|$)/); let v2rayPlugin = parsed[2]; diff --git a/backend/src/core/proxy-utils/parsers/peggy/surge.js b/backend/src/core/proxy-utils/parsers/peggy/surge.js index 006c3c4..311311e 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/surge.js +++ b/backend/src/core/proxy-utils/parsers/peggy/surge.js @@ -30,6 +30,11 @@ const grammars = String.raw` } } } + function handleShadowTLS() { + if (proxy['shadow-tls-password'] && !proxy['shadow-tls-version']) { + proxy['shadow-tls-version'] = 2; + } + } } start = (shadowsocks/vmess/trojan/https/http/snell/socks5/socks5_tls/tuic/tuic_v5/wireguard/hysteria2) { @@ -45,6 +50,7 @@ shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/ $set(proxy, "plugin-opts.host", obfs.host); $set(proxy, "plugin-opts.path", obfs.path); } + handleShadowTLS(); } vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/method/ip_version/underlying_proxy/no_error_alert/tls/sni/tls_fingerprint/tls_verification/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "vmess"; @@ -55,17 +61,21 @@ vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/ proxy.alterId = proxy.alterId || 0; } handleWebsocket(); + handleShadowTLS(); } trojan = tag equals "trojan" address (passwordk/ws/ws_path/ws_headers/tls/sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/no_error_alert/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "trojan"; handleWebsocket(); + handleShadowTLS(); } https = tag equals "https" address (username password)? (usernamek passwordk)? (sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "http"; proxy.tls = true; + handleShadowTLS(); } http = tag equals "http" address (username password)? (usernamek passwordk)? (ip_version/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "http"; + handleShadowTLS(); } snell = tag equals "snell" address (snell_version/snell_psk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/no_error_alert/fast_open/udp_relay/reuse/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "snell"; @@ -75,26 +85,33 @@ snell = tag equals "snell" address (snell_version/snell_psk/obfs/obfs_host/obfs_ $set(proxy, "obfs-opts.host", obfs.host); $set(proxy, "obfs-opts.path", obfs.path); } + handleShadowTLS(); } tuic = tag equals "tuic" address (alpn/token/ip_version/underlying_proxy/no_error_alert/tls_verification/sni/fast_open/tfo/ecn/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "tuic"; + handleShadowTLS(); } tuic_v5 = tag equals "tuic-v5" address (alpn/passwordk/uuidk/ip_version/underlying_proxy/no_error_alert/tls_verification/sni/fast_open/tfo/ecn/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "tuic"; proxy.version = 5; + handleShadowTLS(); } wireguard = tag equals "wireguard" (section_name/no_error_alert/ip_version/underlying_proxy/test_url/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "wireguard-surge"; + handleShadowTLS(); } hysteria2 = tag equals "hysteria2" address (no_error_alert/ip_version/underlying_proxy/test_url/sni/tls_verification/passwordk/tls_fingerprint/download_bandwidth/ecn/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "hysteria2"; + handleShadowTLS(); } socks5 = tag equals "socks5" address (username password)? (usernamek passwordk)? (no_error_alert/ip_version/underlying_proxy/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "socks5"; + handleShadowTLS(); } socks5_tls = tag equals "socks5-tls" address (username password)? (usernamek passwordk)? (no_error_alert/ip_version/underlying_proxy/sni/tls_fingerprint/tls_verification/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "socks5"; proxy.tls = true; + handleShadowTLS(); } address = comma server:server comma port:port { diff --git a/backend/src/core/proxy-utils/parsers/peggy/surge.peg b/backend/src/core/proxy-utils/parsers/peggy/surge.peg index cdcaab5..c555b12 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/surge.peg +++ b/backend/src/core/proxy-utils/parsers/peggy/surge.peg @@ -28,6 +28,11 @@ } } } + function handleShadowTLS() { + if (proxy['shadow-tls-password'] && !proxy['shadow-tls-version']) { + proxy['shadow-tls-version'] = 2; + } + } } start = (shadowsocks/vmess/trojan/https/http/snell/socks5/socks5_tls/tuic/tuic_v5/wireguard/hysteria2) { @@ -43,6 +48,7 @@ shadowsocks = tag equals "ss" address (method/passwordk/obfs/obfs_host/obfs_uri/ $set(proxy, "plugin-opts.host", obfs.host); $set(proxy, "plugin-opts.path", obfs.path); } + handleShadowTLS(); } vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/method/ip_version/underlying_proxy/no_error_alert/tls/sni/tls_fingerprint/tls_verification/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "vmess"; @@ -53,17 +59,21 @@ vmess = tag equals "vmess" address (vmess_uuid/vmess_aead/ws/ws_path/ws_headers/ proxy.alterId = proxy.alterId || 0; } handleWebsocket(); + handleShadowTLS(); } trojan = tag equals "trojan" address (passwordk/ws/ws_path/ws_headers/tls/sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/no_error_alert/fast_open/udp_relay/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "trojan"; handleWebsocket(); + handleShadowTLS(); } https = tag equals "https" address (username password)? (usernamek passwordk)? (sni/tls_fingerprint/tls_verification/ip_version/underlying_proxy/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "http"; proxy.tls = true; + handleShadowTLS(); } http = tag equals "http" address (username password)? (usernamek passwordk)? (ip_version/no_error_alert/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "http"; + handleShadowTLS(); } snell = tag equals "snell" address (snell_version/snell_psk/obfs/obfs_host/obfs_uri/ip_version/underlying_proxy/no_error_alert/fast_open/udp_relay/reuse/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "snell"; @@ -73,26 +83,33 @@ snell = tag equals "snell" address (snell_version/snell_psk/obfs/obfs_host/obfs_ $set(proxy, "obfs-opts.host", obfs.host); $set(proxy, "obfs-opts.path", obfs.path); } + handleShadowTLS(); } tuic = tag equals "tuic" address (alpn/token/ip_version/underlying_proxy/no_error_alert/tls_verification/sni/fast_open/tfo/ecn/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "tuic"; + handleShadowTLS(); } tuic_v5 = tag equals "tuic-v5" address (alpn/passwordk/uuidk/ip_version/underlying_proxy/no_error_alert/tls_verification/sni/fast_open/tfo/ecn/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "tuic"; proxy.version = 5; + handleShadowTLS(); } wireguard = tag equals "wireguard" (section_name/no_error_alert/ip_version/underlying_proxy/test_url/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "wireguard-surge"; + handleShadowTLS(); } hysteria2 = tag equals "hysteria2" address (no_error_alert/ip_version/underlying_proxy/test_url/sni/tls_verification/passwordk/tls_fingerprint/download_bandwidth/ecn/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "hysteria2"; + handleShadowTLS(); } socks5 = tag equals "socks5" address (username password)? (usernamek passwordk)? (no_error_alert/ip_version/underlying_proxy/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "socks5"; + handleShadowTLS(); } socks5_tls = tag equals "socks5-tls" address (username password)? (usernamek passwordk)? (no_error_alert/ip_version/underlying_proxy/sni/tls_fingerprint/tls_verification/fast_open/shadow_tls_version/shadow_tls_sni/shadow_tls_password/block_quic/others)* { proxy.type = "socks5"; proxy.tls = true; + handleShadowTLS(); } address = comma server:server comma port:port { diff --git a/backend/src/core/proxy-utils/producers/clash.js b/backend/src/core/proxy-utils/producers/clash.js index 8ea9d94..c17fc87 100644 --- a/backend/src/core/proxy-utils/producers/clash.js +++ b/backend/src/core/proxy-utils/producers/clash.js @@ -126,6 +126,12 @@ export default function Clash_Producer() { proxy['h2-opts'].headers.host = [host]; } } + if (proxy['plugin-opts']?.tls) { + if (isPresent(proxy, 'skip-cert-verify')) { + proxy['plugin-opts']['skip-cert-verify'] = + proxy['skip-cert-verify']; + } + } if ( ['trojan', 'tuic', 'hysteria', 'hysteria2'].includes( proxy.type, diff --git a/backend/src/core/proxy-utils/producers/clashmeta.js b/backend/src/core/proxy-utils/producers/clashmeta.js index 59f6dcc..b77b0b2 100644 --- a/backend/src/core/proxy-utils/producers/clashmeta.js +++ b/backend/src/core/proxy-utils/producers/clashmeta.js @@ -89,6 +89,18 @@ export default function ClashMeta_Producer() { proxy.servername = proxy.sni; delete proxy.sni; } + } else if (proxy.type === 'ss') { + if ( + isPresent(proxy, 'shadow-tls-password') && + !isPresent(proxy, 'plugin') + ) { + proxy.plugin = 'shadow-tls'; + proxy['plugin-opts'] = { + host: proxy['shadow-tls-sni'], + password: proxy['shadow-tls-password'], + version: proxy['shadow-tls-version'], + }; + } } if ( @@ -129,6 +141,13 @@ export default function ClashMeta_Producer() { proxy['h2-opts'].headers.host = [host]; } } + + if (proxy['plugin-opts']?.tls) { + if (isPresent(proxy, 'skip-cert-verify')) { + proxy['plugin-opts']['skip-cert-verify'] = + proxy['skip-cert-verify']; + } + } if ( ['trojan', 'tuic', 'hysteria', 'hysteria2'].includes( proxy.type, diff --git a/backend/src/core/proxy-utils/producers/shadowrocket.js b/backend/src/core/proxy-utils/producers/shadowrocket.js index c19c28a..ff6d927 100644 --- a/backend/src/core/proxy-utils/producers/shadowrocket.js +++ b/backend/src/core/proxy-utils/producers/shadowrocket.js @@ -145,7 +145,12 @@ export default function ShadowRocket_Producer() { proxy['h2-opts'].headers.host = [host]; } } - + if (proxy['plugin-opts']?.tls) { + if (isPresent(proxy, 'skip-cert-verify')) { + proxy['plugin-opts']['skip-cert-verify'] = + proxy['skip-cert-verify']; + } + } if ( ['trojan', 'tuic', 'hysteria', 'hysteria2'].includes( proxy.type, diff --git a/backend/src/core/proxy-utils/producers/sing-box.js b/backend/src/core/proxy-utils/producers/sing-box.js index 84fbbe2..0214a3d 100644 --- a/backend/src/core/proxy-utils/producers/sing-box.js +++ b/backend/src/core/proxy-utils/producers/sing-box.js @@ -263,6 +263,37 @@ const socks5Parser = (proxy = {}) => { return parsedProxy; }; +const shadowTLSParser = (proxy = {}) => { + const ssPart = { + tag: proxy.name, + type: 'shadowsocks', + method: proxy.cipher, + password: proxy.password, + detour: `${proxy.name}_shadowtls`, + }; + const stPart = { + tag: `${proxy.name}_shadowtls`, + type: 'shadowtls', + server: proxy.server, + server_port: parseInt(`${proxy.port}`, 10), + version: proxy['plugin-opts'].version, + password: proxy['plugin-opts'].password, + tls: { + enabled: true, + server_name: proxy['plugin-opts'].host, + utls: { + enabled: true, + fingerprint: proxy['client-fingerprint'], + }, + }, + }; + if (stPart.server_port < 1 || stPart.server_port > 65535) + throw '端口值非法'; + if (proxy['fast-open'] === true) stPart.udp_fragment = true; + tfoParser(proxy, stPart); + smuxParser(proxy.smux, ssPart); + return { type: 'ss-with-st', ssPart, stPart }; +}; const ssParser = (proxy = {}) => { const parsedProxy = { tag: proxy.name, @@ -607,9 +638,10 @@ export default function singbox_Producer() { break; case 'ss': if (proxy.plugin === 'shadow-tls') { - throw new Error( - `Platform sing-box does not support proxy type: ${proxy.type} with shadow-tls`, - ); + const { ssPart, stPart } = + shadowTLSParser(proxy); + list.push(ssPart); + list.push(stPart); } else { list.push(ssParser(proxy)); } diff --git a/backend/src/core/proxy-utils/producers/stash.js b/backend/src/core/proxy-utils/producers/stash.js index aaffc97..8e6bcba 100644 --- a/backend/src/core/proxy-utils/producers/stash.js +++ b/backend/src/core/proxy-utils/producers/stash.js @@ -225,6 +225,12 @@ export default function Stash_Producer() { proxy['h2-opts'].headers.host = [host]; } } + if (proxy['plugin-opts']?.tls) { + if (isPresent(proxy, 'skip-cert-verify')) { + proxy['plugin-opts']['skip-cert-verify'] = + proxy['skip-cert-verify']; + } + } if ( ['trojan', 'tuic', 'hysteria', 'hysteria2'].includes( proxy.type,