From 0c2e19e6565f76909e5d8127c8911b3778eb559b Mon Sep 17 00:00:00 2001 From: noir017 Date: Sun, 5 Jul 2026 13:29:57 +0800 Subject: [PATCH] fix: support authenticated socks5/http proxies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chromium 的 --proxy-server 无法携带凭据,导致导入带鉴权的 socks5://user:pass@host:port 代理时浏览器静默丢弃鉴权而连接失败。 内核选择器原先将所有 socks5/http 一律固定为 native,永远走不到 已有的 xray/mihomo 桥接逻辑。现改为:带鉴权的 socks5/http 自动 使用 xray/mihomo 桥接为本地无鉴权 socks5 再交给浏览器;无鉴权 代理仍走 native。 Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/internal/proxy/kernel_resolver.go | 10 +++++++++- backend/internal/proxy/kernel_resolver_test.go | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/backend/internal/proxy/kernel_resolver.go b/backend/internal/proxy/kernel_resolver.go index fbe1bfd9..6f2169df 100644 --- a/backend/internal/proxy/kernel_resolver.go +++ b/backend/internal/proxy/kernel_resolver.go @@ -117,7 +117,15 @@ func DetectProxyProtocol(proxyConfig string) string { func SupportedKernelsForProtocol(protocol string, proxyConfig string, proxies []config.BrowserProxy, proxyId string) []string { switch strings.ToLower(strings.TrimSpace(protocol)) { - case "direct", "http", "https", "socks5": + case "direct": + return []string{ProxyKernelNative} + case "http", "https", "socks5": + // 带账号密码鉴权的 socks5/http 代理:Chromium 的 --proxy-server 无法携带凭据, + // 浏览器 native 会静默丢弃鉴权信息导致连接失败。这类代理必须通过 xray / mihomo + // 桥接成本地无鉴权 socks5 再交给浏览器。无鉴权的代理仍走 native。 + if RequiresLocalProxyBridgeForBrowser(proxyConfig) { + return []string{ProxyKernelXray, ProxyKernelMihomo} + } return []string{ProxyKernelNative} case "vmess", "vless", "trojan", "ss", "shadowsocks", "chain+socks5": return []string{ProxyKernelXray, ProxyKernelMihomo} diff --git a/backend/internal/proxy/kernel_resolver_test.go b/backend/internal/proxy/kernel_resolver_test.go index 21fcf555..736500bf 100644 --- a/backend/internal/proxy/kernel_resolver_test.go +++ b/backend/internal/proxy/kernel_resolver_test.go @@ -17,6 +17,9 @@ func TestResolveProxyKernelDefaultPriority(t *testing.T) { {name: "anytls URI uses sing-box", proxy: "anytls://pass@example.com:443?sni=example.com", wantKernel: ProxyKernelSingBox}, {name: "mieru uses mihomo", proxy: mieruClashNode, wantKernel: ProxyKernelMihomo}, {name: "http uses native", proxy: "http://127.0.0.1:8080", wantKernel: ProxyKernelNative}, + {name: "socks5 without auth uses native", proxy: "socks5://127.0.0.1:1080", wantKernel: ProxyKernelNative}, + {name: "socks5 with auth uses xray", proxy: "socks5://user:pass@127.0.0.1:1080", wantKernel: ProxyKernelXray}, + {name: "http with auth uses xray", proxy: "http://user:pass@127.0.0.1:8080", wantKernel: ProxyKernelXray}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) {