From c3daea55abcb7b244bb491d409c87c95774f2546 Mon Sep 17 00:00:00 2001 From: xream Date: Wed, 15 Jan 2025 23:54:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Loon=20=E8=8A=82=E7=82=B9=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20ip-mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package.json | 2 +- .../core/proxy-utils/parsers/peggy/loon.js | 19 +++++++------ .../core/proxy-utils/parsers/peggy/loon.peg | 19 +++++++------ .../src/core/proxy-utils/producers/loon.js | 28 +++++++++++++++++++ 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/backend/package.json b/backend/package.json index e0fcd44..faeffb3 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "sub-store", - "version": "2.16.16", + "version": "2.16.17", "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/loon.js b/backend/src/core/proxy-utils/parsers/peggy/loon.js index 2ffa236..9615037 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/loon.js +++ b/backend/src/core/proxy-utils/parsers/peggy/loon.js @@ -39,12 +39,12 @@ start = (shadowsocksr/shadowsocks/vmess/vless/trojan/https/http/socks5/hysteria2 return proxy; } -shadowsocksr = tag equals "shadowsocksr"i address method password (ssr_protocol/ssr_protocol_param/obfs_ssr/obfs_ssr_param/obfs_host/obfs_uri/fast_open/udp_relay/udp_port/shadow_tls_version/shadow_tls_sni/shadow_tls_password/others)*{ +shadowsocksr = tag equals "shadowsocksr"i address method password (ssr_protocol/ssr_protocol_param/obfs_ssr/obfs_ssr_param/obfs_host/obfs_uri/fast_open/udp_relay/udp_port/shadow_tls_version/shadow_tls_sni/shadow_tls_password/ip_mode/others)*{ proxy.type = "ssr"; // handle ssr obfs proxy.obfs = obfs.type; } -shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs_hostv)? (obfs_ss/obfs_host/obfs_uri/fast_open/udp_relay/udp_port/shadow_tls_version/shadow_tls_sni/shadow_tls_password/others)* { +shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs_hostv)? (obfs_ss/obfs_host/obfs_uri/fast_open/udp_relay/udp_port/shadow_tls_version/shadow_tls_sni/shadow_tls_password/ip_mode/others)* { proxy.type = "ss"; // handle ss obfs if (obfs.type == "http" || obfs.type === "tls") { @@ -54,31 +54,31 @@ shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs $set(proxy, "plugin-opts.path", obfs.path); } } -vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/vmess_alterId/fast_open/udp_relay/others)* { +vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/vmess_alterId/fast_open/udp_relay/ip_mode/others)* { proxy.type = "vmess"; proxy.cipher = proxy.cipher || "none"; proxy.alterId = proxy.alterId || 0; handleTransport(); } -vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* { +vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/ip_mode/others)* { proxy.type = "vless"; handleTransport(); } -trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* { +trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/ip_mode/others)* { proxy.type = "trojan"; handleTransport(); } -hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* { +hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/ip_mode/others)* { proxy.type = "hysteria2"; } -https = tag equals "https"i address (username password)? (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* { +https = tag equals "https"i address (username password)? (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/ip_mode/others)* { proxy.type = "http"; proxy.tls = true; } -http = tag equals "http"i address (username password)? (fast_open/udp_relay/others)* { +http = tag equals "http"i address (username password)? (fast_open/udp_relay/ip_mode/others)* { proxy.type = "http"; } -socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* { +socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/ip_mode/others)* { proxy.type = "socks5"; } @@ -182,6 +182,7 @@ tls_pubkey_sha256 = comma "tls-pubkey-sha256" equals match:[^,]+ { proxy["tls-pu fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; } udp_relay = comma "udp" equals flag:bool { proxy.udp = flag; } +ip_mode = comma "ip-mode" equals match:[^,]+ { proxy["ip-version"] = match.join(""); } ecn = comma "ecn" equals flag:bool { proxy.ecn = flag; } download_bandwidth = comma "download-bandwidth" equals match:[^,]+ { proxy.down = match.join(""); } diff --git a/backend/src/core/proxy-utils/parsers/peggy/loon.peg b/backend/src/core/proxy-utils/parsers/peggy/loon.peg index fe70a53..60f3623 100644 --- a/backend/src/core/proxy-utils/parsers/peggy/loon.peg +++ b/backend/src/core/proxy-utils/parsers/peggy/loon.peg @@ -37,12 +37,12 @@ start = (shadowsocksr/shadowsocks/vmess/vless/trojan/https/http/socks5/hysteria2 return proxy; } -shadowsocksr = tag equals "shadowsocksr"i address method password (ssr_protocol/ssr_protocol_param/obfs_ssr/obfs_ssr_param/obfs_host/obfs_uri/fast_open/udp_relay/udp_port/shadow_tls_version/shadow_tls_sni/shadow_tls_password/others)*{ +shadowsocksr = tag equals "shadowsocksr"i address method password (ssr_protocol/ssr_protocol_param/obfs_ssr/obfs_ssr_param/obfs_host/obfs_uri/fast_open/udp_relay/udp_port/shadow_tls_version/shadow_tls_sni/shadow_tls_password/ip_mode/others)*{ proxy.type = "ssr"; // handle ssr obfs proxy.obfs = obfs.type; } -shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs_hostv)? (obfs_ss/obfs_host/obfs_uri/fast_open/udp_relay/udp_port/shadow_tls_version/shadow_tls_sni/shadow_tls_password/others)* { +shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs_hostv)? (obfs_ss/obfs_host/obfs_uri/fast_open/udp_relay/udp_port/shadow_tls_version/shadow_tls_sni/shadow_tls_password/ip_mode/others)* { proxy.type = "ss"; // handle ss obfs if (obfs.type == "http" || obfs.type === "tls") { @@ -52,31 +52,31 @@ shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs $set(proxy, "plugin-opts.path", obfs.path); } } -vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/vmess_alterId/fast_open/udp_relay/others)* { +vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/vmess_alterId/fast_open/udp_relay/ip_mode/others)* { proxy.type = "vmess"; proxy.cipher = proxy.cipher || "none"; proxy.alterId = proxy.alterId || 0; handleTransport(); } -vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* { +vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/ip_mode/others)* { proxy.type = "vless"; handleTransport(); } -trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* { +trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/ip_mode/others)* { proxy.type = "trojan"; handleTransport(); } -hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* { +hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/ip_mode/others)* { proxy.type = "hysteria2"; } -https = tag equals "https"i address (username password)? (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* { +https = tag equals "https"i address (username password)? (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/ip_mode/others)* { proxy.type = "http"; proxy.tls = true; } -http = tag equals "http"i address (username password)? (fast_open/udp_relay/others)* { +http = tag equals "http"i address (username password)? (fast_open/udp_relay/ip_mode/others)* { proxy.type = "http"; } -socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* { +socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/ip_mode/others)* { proxy.type = "socks5"; } @@ -180,6 +180,7 @@ tls_pubkey_sha256 = comma "tls-pubkey-sha256" equals match:[^,]+ { proxy["tls-pu fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; } udp_relay = comma "udp" equals flag:bool { proxy.udp = flag; } +ip_mode = comma "ip-mode" equals match:[^,]+ { proxy["ip-version"] = match.join(""); } ecn = comma "ecn" equals flag:bool { proxy.ecn = flag; } download_bandwidth = comma "download-bandwidth" equals match:[^,]+ { proxy.down = match.join(""); } diff --git a/backend/src/core/proxy-utils/producers/loon.js b/backend/src/core/proxy-utils/producers/loon.js index 671ed10..dd708e3 100644 --- a/backend/src/core/proxy-utils/producers/loon.js +++ b/backend/src/core/proxy-utils/producers/loon.js @@ -3,6 +3,14 @@ const targetPlatform = 'Loon'; import { isPresent, Result } from './utils'; import { isIPv4, isIPv6 } from '@/utils'; +const ipVersions = { + dual: 'dual', + ipv4: 'v4-only', + ipv6: 'v6-only', + 'ipv4-prefer': 'prefer-v4', + 'ipv6-prefer': 'prefer-v6', +}; + export default function Loon_Producer() { const produce = (proxy, type, opts = {}) => { switch (proxy.type) { @@ -139,6 +147,8 @@ function shadowsocks(proxy, includeUnsupportedProxy) { `shadow-tls is not supported(请使用 includeUnsupportedProxy 参数)`, ); } + const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); return result.toString(); } @@ -216,6 +226,8 @@ function shadowsocksr(proxy, includeUnsupportedProxy) { `shadow-tls is not supported(请使用 includeUnsupportedProxy 参数)`, ); } + const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); return result.toString(); } @@ -269,6 +281,8 @@ function trojan(proxy) { if (proxy.udp) { result.append(`,udp=true`); } + const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); return result.toString(); } @@ -345,6 +359,9 @@ function vmess(proxy) { // udp if (proxy.udp) { result.append(`,udp=true`); + const ip_version = + ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); } return result.toString(); } @@ -417,6 +434,9 @@ function vless(proxy) { // udp if (proxy.udp) { result.append(`,udp=true`); + const ip_version = + ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); } return result.toString(); } @@ -439,6 +459,8 @@ function http(proxy) { // tfo result.appendIfPresent(`,tfo=${proxy.tfo}`, 'tfo'); + const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); return result.toString(); } @@ -467,6 +489,8 @@ function socks5(proxy) { if (proxy.udp) { result.append(`,udp=true`); } + const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); return result.toString(); } @@ -532,6 +556,8 @@ function wireguard(proxy) { presharedKey ?? '' }}]`, ); + const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); return result.toString(); } @@ -579,6 +605,8 @@ function hysteria2(proxy) { ); result.appendIfPresent(`,ecn=${proxy.ecn}`, 'ecn'); + const ip_version = ipVersions[proxy['ip-version']] || proxy['ip-version']; + result.appendIfPresent(`,ip-mode=${ip_version}`, 'ip-version'); return result.toString(); }