fix: Node.js TLS 代理按主机白名单过滤,Gemini 走原路径
Some checks failed
CI / test (push) Failing after 6m40s
Security Scan / backend-security (push) Has been cancelled
Security Scan / frontend-security (push) Has been cancelled
CI / golangci-lint (push) Failing after 19m50s

- 新增 proxy_hosts 配置:白名单内的主机走 Node.js 代理
- 默认仅代理 api.anthropic.com
- Gemini/Sora 等非 Anthropic 请求自动走原有 uTLS 路径
- 解决 Gemini 请求经 Node.js 代理后 socket hang up 的问题
This commit is contained in:
win 2026-03-22 01:15:56 +08:00
parent 5c587c1095
commit c6a282c2e7
2 changed files with 24 additions and 10 deletions

View File

@ -689,6 +689,11 @@ type NodeTLSProxyConfig struct {
// UpstreamHost: 上游目标主机(默认 api.anthropic.com
// 通常不需要修改,除非需要指向不同的 API 端点
UpstreamHost string `mapstructure:"upstream_host"`
// ProxyHosts: 需要走 Node.js 代理的上游主机白名单
// 只有目标主机在此列表中的 HTTPS 请求才走 Node.js 代理
// 不在列表中的请求走原有路径uTLS 或直连)
// 为空时默认只代理 api.anthropic.com
ProxyHosts []string `mapstructure:"proxy_hosts"`
}
// GatewaySchedulingConfig accounts scheduling configuration.

View File

@ -124,8 +124,8 @@ func NewHTTPUpstream(cfg *config.Config) service.HTTPUpstream {
// - 调用方必须关闭 resp.Body否则会导致 inFlight 计数泄漏
// - inFlight > 0 的客户端不会被淘汰,确保活跃请求不被中断
func (s *httpUpstreamService) Do(req *http.Request, proxyURL string, accountID int64, accountConcurrency int) (*http.Response, error) {
// 优先使用 Node.js TLS 代理模式:拦截所有 HTTPS 上游请求
if s.isNodeTLSProxyEnabled() && req != nil && req.URL != nil && req.URL.Scheme == "https" {
// Node.js TLS 代理:仅拦截白名单内的上游主机
if s.isNodeTLSProxyEnabled() && s.shouldRouteViaNodeProxy(req) {
return s.doViaNodeTLSProxy(req, accountID, accountConcurrency)
}
@ -247,19 +247,28 @@ func (s *httpUpstreamService) isNodeTLSProxyEnabled() bool {
}
// shouldRouteViaNodeProxy 判断请求是否应该走 Node.js TLS 代理
// 仅拦截发往配置的上游主机(默认 api.anthropic.com的 HTTPS 请求,
// 其他请求(如 Gemini、Sora走原有路径
// 仅拦截目标主机在 proxy_hosts 白名单中的 HTTPS 请求,
// 白名单为空时默认只代理 api.anthropic.com
func (s *httpUpstreamService) shouldRouteViaNodeProxy(req *http.Request) bool {
if req == nil || req.URL == nil || req.URL.Scheme != "https" {
return false
}
upstreamHost := s.cfg.Gateway.NodeTLSProxy.UpstreamHost
if upstreamHost == "" {
upstreamHost = "api.anthropic.com"
}
// 比较请求的目标主机(去掉端口)
reqHost := req.URL.Hostname()
return reqHost == upstreamHost
if reqHost == "" {
return false
}
hosts := s.cfg.Gateway.NodeTLSProxy.ProxyHosts
if len(hosts) == 0 {
// 默认只代理 Anthropic
return reqHost == "api.anthropic.com"
}
for _, h := range hosts {
if reqHost == h {
return true
}
}
return false
}
// doViaNodeTLSProxy 通过 Node.js TLS 代理发送请求