diff --git a/backend/package.json b/backend/package.json index 25d1e8f..d0b5666 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.14.66", + "version": "2.14.67", "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 b6d0c3d..a1a482b 100644 --- a/backend/src/core/proxy-utils/parsers/index.js +++ b/backend/src/core/proxy-utils/parsers/index.js @@ -784,6 +784,15 @@ function Surge_WireGuard() { return { name, test, parse }; } +function Surge_Hysteria2() { + const name = 'Surge Hysteria2 Parser'; + const test = (line) => { + return /^.*=\s*hysteria2/.test(line.split(',')[0]); + }; + const parse = (line) => getSurgeParser().parse(line); + return { name, test, parse }; +} + export default [ URI_SS(), URI_SSR(), @@ -798,6 +807,7 @@ export default [ Surge_Snell(), Surge_Tuic(), Surge_WireGuard(), + Surge_Hysteria2(), Surge_Socks5(), Loon_SS(), Loon_SSR(), diff --git a/backend/src/core/proxy-utils/parsers/peggy/surge.js b/backend/src/core/proxy-utils/parsers/peggy/surge.js index cf39579..898b2cc 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/surge.js +++ b/backend/src/core/proxy-utils/parsers/peggy/surge.js @@ -32,7 +32,7 @@ const grammars = String.raw` } } -start = (shadowsocks/vmess/trojan/https/http/snell/socks5/socks5_tls/tuic/tuic_v5/wireguard) { +start = (shadowsocks/vmess/trojan/https/http/snell/socks5/socks5_tls/tuic/tuic_v5/wireguard/hysteria2) { return proxy; } @@ -86,6 +86,9 @@ tuic_v5 = tag equals "tuic-v5" address (alpn/passwordk/uuidk/ip_version/tls_veri wireguard = tag equals "wireguard" (section_name/no_error_alert/ip_version/underlying_proxy/test_url/others)* { proxy.type = "wireguard-surge"; } +hysteria2 = tag equals "hysteria2" address (no_error_alert/ip_version/underlying_proxy/test_url/sni/tls_verification/passwordk/download_bandwidth/others)* { + proxy.type = "hysteria2"; +} socks5 = tag equals "socks5" address (username password)? (fast_open/others)* { proxy.type = "socks5"; } @@ -194,6 +197,7 @@ ip_version = comma "ip-version" equals match:[^,]+ { proxy["ip-version"] = match section_name = comma "section-name" equals match:[^,]+ { proxy["section-name"] = match.join(""); } no_error_alert = comma "no-error-alert" equals match:[^,]+ { proxy["no-error-alert"] = match.join(""); } underlying_proxy = comma "underlying-proxy" equals match:[^,]+ { proxy["underlying-proxy"] = match.join(""); } +download_bandwidth = comma "download-bandwidth" equals match:[^,]+ { proxy.down = match.join(""); } test_url = comma "test-url" equals match:[^,]+ { proxy["test-url"] = match.join(""); } token = comma "token" equals match:[^,]+ { proxy.token = match.join(""); } alpn = comma "alpn" equals match:[^,]+ { proxy.alpn = match.join(""); } diff --git a/backend/src/core/proxy-utils/parsers/peggy/surge.peg b/backend/src/core/proxy-utils/parsers/peggy/surge.peg index 3b2bc02..75a1e3b 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/surge.peg +++ b/backend/src/core/proxy-utils/parsers/peggy/surge.peg @@ -30,7 +30,7 @@ } } -start = (shadowsocks/vmess/trojan/https/http/snell/socks5/socks5_tls/tuic/tuic_v5/wireguard) { +start = (shadowsocks/vmess/trojan/https/http/snell/socks5/socks5_tls/tuic/tuic_v5/wireguard/hysteria2) { return proxy; } @@ -84,6 +84,9 @@ tuic_v5 = tag equals "tuic-v5" address (alpn/passwordk/uuidk/ip_version/tls_veri wireguard = tag equals "wireguard" (section_name/no_error_alert/ip_version/underlying_proxy/test_url/others)* { proxy.type = "wireguard-surge"; } +hysteria2 = tag equals "hysteria2" address (no_error_alert/ip_version/underlying_proxy/test_url/sni/tls_verification/passwordk/download_bandwidth/others)* { + proxy.type = "hysteria2"; +} socks5 = tag equals "socks5" address (username password)? (fast_open/others)* { proxy.type = "socks5"; } @@ -192,6 +195,7 @@ ip_version = comma "ip-version" equals match:[^,]+ { proxy["ip-version"] = match section_name = comma "section-name" equals match:[^,]+ { proxy["section-name"] = match.join(""); } no_error_alert = comma "no-error-alert" equals match:[^,]+ { proxy["no-error-alert"] = match.join(""); } underlying_proxy = comma "underlying-proxy" equals match:[^,]+ { proxy["underlying-proxy"] = match.join(""); } +download_bandwidth = comma "download-bandwidth" equals match:[^,]+ { proxy.down = match.join(""); } test_url = comma "test-url" equals match:[^,]+ { proxy["test-url"] = match.join(""); } token = comma "token" equals match:[^,]+ { proxy.token = match.join(""); } alpn = comma "alpn" equals match:[^,]+ { proxy.alpn = match.join(""); } diff --git a/backend/src/core/proxy-utils/producers/surge.js b/backend/src/core/proxy-utils/producers/surge.js index dfdaa6b..9936939 100644 --- a/backend/src/core/proxy-utils/producers/surge.js +++ b/backend/src/core/proxy-utils/producers/surge.js @@ -31,6 +31,8 @@ export default function Surge_Producer() { return tuic(proxy); case 'wireguard-surge': return wireguard(proxy); + case 'hysteria2': + return hysteria2(proxy); } throw new Error( `Platform ${targetPlatform} does not support proxy type: ${proxy.type}`, @@ -364,6 +366,45 @@ function wireguard(proxy) { return result.toString(); } +function hysteria2(proxy) { + const result = new Result(proxy); + result.append(`${proxy.name}=hysteria2,${proxy.server},${proxy.port}`); + + result.appendIfPresent(`,password=${proxy.password}`, 'password'); + + result.appendIfPresent( + `,ip-version=${ipVersions[proxy['ip-version']] || proxy['ip-version']}`, + 'ip-version', + ); + + result.appendIfPresent( + `,no-error-alert=${proxy['no-error-alert']}`, + 'no-error-alert', + ); + + // tls verification + result.appendIfPresent(`,sni=${proxy.sni}`, 'sni'); + result.appendIfPresent( + `,skip-cert-verify=${proxy['skip-cert-verify']}`, + 'skip-cert-verify', + ); + + // tfo + result.appendIfPresent(`,tfo=${proxy['fast-open']}`, 'fast-open'); + result.appendIfPresent(`,tfo=${proxy.tfo}`, 'tfo'); + + // test-url + result.appendIfPresent(`,test-url=${proxy['test-url']}`, 'test-url'); + + // underlying-proxy + result.appendIfPresent( + `,underlying-proxy=${proxy['underlying-proxy']}`, + 'underlying-proxy', + ); + + return result.toString(); +} + function handleTransport(result, proxy) { if (isPresent(proxy, 'network')) { if (proxy.network === 'ws') {