From c547f34f5720c31d9bc320d12703084c01db78ba Mon Sep 17 00:00:00 2001 From: xream Date: Sun, 29 Oct 2023 23:04:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20Loon=20Hysteria2(e?= =?UTF-8?q?cn,=20=E6=B5=81=E9=87=8F=E6=8E=A7=E5=88=B6=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=9C=AA=E7=9F=A5)?= 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 | 10 ++++++ .../core/proxy-utils/parsers/peggy/loon.js | 8 ++++- .../core/proxy-utils/parsers/peggy/loon.peg | 8 ++++- .../src/core/proxy-utils/producers/loon.js | 32 +++++++++++++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/backend/package.json b/backend/package.json index 0c3c10b..44bede0 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.14.79", + "version": "2.14.80", "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 c2fbc76..7328798 100644 --- a/backend/src/core/proxy-utils/parsers/index.js +++ b/backend/src/core/proxy-utils/parsers/index.js @@ -642,6 +642,15 @@ function Loon_Trojan() { const parse = (line) => getLoonParser().parse(line); return { name, test, parse }; } +function Loon_Hysteria2() { + const name = 'Loon Hysteria2 Parser'; + const test = (line) => { + return /^.*=\s*Hysteria2/i.test(line.split(',')[0]); + }; + + const parse = (line) => getLoonParser().parse(line); + return { name, test, parse }; +} function Loon_Http() { const name = 'Loon HTTP Parser'; @@ -864,6 +873,7 @@ export default [ Loon_SSR(), Loon_VMess(), Loon_Vless(), + Loon_Hysteria2(), Loon_Trojan(), Loon_Http(), Loon_WireGuard(), diff --git a/backend/src/core/proxy-utils/parsers/peggy/loon.js b/backend/src/core/proxy-utils/parsers/peggy/loon.js index ef97a27..cbaf856 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/loon.js +++ b/backend/src/core/proxy-utils/parsers/peggy/loon.js @@ -35,7 +35,7 @@ const grammars = String.raw` } } -start = (shadowsocksr/shadowsocks/vmess/vless/trojan/https/http) { +start = (shadowsocksr/shadowsocks/vmess/vless/trojan/https/http/hysteria2) { return proxy; } @@ -68,6 +68,9 @@ trojan = tag equals "trojan"i address password (transport/transport_host/transpo proxy.type = "trojan"; handleTransport(); } +hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/udp_relay/download_bandwidth/ecn/others)* { + proxy.type = "hysteria2"; +} https = tag equals "https"i address (username password)? (tls_host/tls_verification/fast_open/udp_relay/others)* { proxy.type = "http"; proxy.tls = true; @@ -167,6 +170,9 @@ tls_verification = comma "skip-cert-verify" equals flag:bool { proxy["skip-cert- fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; } udp_relay = comma "udp" equals flag:bool { proxy.udp = flag; } +ecn = comma "ecn" equals flag:bool { proxy.ecn = flag; } +download_bandwidth = comma "download-bandwidth" equals match:[^,]+ { proxy.down = match.join(""); } + tag = match:[^=,]* { proxy.name = match.join("").trim(); } comma = _ "," _ equals = _ "=" _ diff --git a/backend/src/core/proxy-utils/parsers/peggy/loon.peg b/backend/src/core/proxy-utils/parsers/peggy/loon.peg index fe8b82a..0e35cf6 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/loon.peg +++ b/backend/src/core/proxy-utils/parsers/peggy/loon.peg @@ -33,7 +33,7 @@ } } -start = (shadowsocksr/shadowsocks/vmess/vless/trojan/https/http) { +start = (shadowsocksr/shadowsocks/vmess/vless/trojan/https/http/hysteria2) { return proxy; } @@ -66,6 +66,9 @@ trojan = tag equals "trojan"i address password (transport/transport_host/transpo proxy.type = "trojan"; handleTransport(); } +hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/udp_relay/download_bandwidth/ecn/others)* { + proxy.type = "hysteria2"; +} https = tag equals "https"i address (username password)? (tls_host/tls_verification/fast_open/udp_relay/others)* { proxy.type = "http"; proxy.tls = true; @@ -165,6 +168,9 @@ tls_verification = comma "skip-cert-verify" equals flag:bool { proxy["skip-cert- fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; } udp_relay = comma "udp" equals flag:bool { proxy.udp = flag; } +ecn = comma "ecn" equals flag:bool { proxy.ecn = flag; } +download_bandwidth = comma "download-bandwidth" equals match:[^,]+ { proxy.down = match.join(""); } + tag = match:[^=,]* { proxy.name = match.join("").trim(); } comma = _ "," _ equals = _ "=" _ diff --git a/backend/src/core/proxy-utils/producers/loon.js b/backend/src/core/proxy-utils/producers/loon.js index 73f2e6e..c5c2626 100644 --- a/backend/src/core/proxy-utils/producers/loon.js +++ b/backend/src/core/proxy-utils/producers/loon.js @@ -20,6 +20,8 @@ export default function Loon_Producer() { return http(proxy); case 'wireguard': return wireguard(proxy); + case 'hysteria2': + return hysteria2(proxy); } throw new Error( `Platform ${targetPlatform} does not support proxy type: ${proxy.type}`, @@ -334,3 +336,33 @@ function wireguard(proxy) { return result.toString(); } + +function hysteria2(proxy) { + if (proxy.obfs || proxy['obfs-password']) { + throw new Error(`obfs is unsupported`); + } + const result = new Result(proxy); + result.append(`${proxy.name}=Hysteria2,${proxy.server},${proxy.port}`); + + result.appendIfPresent(`,"${proxy.password}"`, 'password'); + + // sni + result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni'); + result.appendIfPresent( + `,skip-cert-verify=${proxy['skip-cert-verify']}`, + 'skip-cert-verify', + ); + + // udp + result.appendIfPresent(`,udp=${proxy.udp}`, 'udp'); + + // download-bandwidth + result.appendIfPresent( + `,download-bandwidth=${`${proxy['down']}`.match(/\d+/)?.[0] || 0}`, + 'down', + ); + + result.appendIfPresent(`,ecn=${proxy.ecn}`, 'ecn'); + + return result.toString(); +}