feat: IP管理代理与 node-tls-proxy 指纹伪装共存
- Do()/DoWithTLS() 移除 proxyURL=="" 条件,绑了代理也走 node-tls-proxy - doViaNodeTLSProxy 通过 X-Upstream-Proxy header 传递账号代理给 node-tls-proxy - node-tls-proxy 支持 per-request 动态上游代理,优先 X-Upstream-Proxy,回退全局 UPSTREAM_PROXY - 效果:IP管理 = 落地机网络,账号绑代理后指纹伪装仍然生效
This commit is contained in:
parent
e1de3a7b21
commit
8c6e578a84
@ -573,10 +573,15 @@ function sendViaH1(targetHost, method, path, reqHeaders, body, res, savedHeaders
|
||||
proxyReq.end(body);
|
||||
};
|
||||
|
||||
if (UPSTREAM_PROXY) {
|
||||
connectViaProxy(UPSTREAM_PROXY, targetHost, 443)
|
||||
// 动态上游代理:优先使用 per-request 的 X-Upstream-Proxy,回退到全局 UPSTREAM_PROXY
|
||||
const upstreamProxy = reqHeaders['x-upstream-proxy'] || UPSTREAM_PROXY;
|
||||
// 清除内部 header,不传给上游
|
||||
delete headers['x-upstream-proxy'];
|
||||
|
||||
if (upstreamProxy) {
|
||||
connectViaProxy(upstreamProxy, targetHost, 443)
|
||||
.then((socket) => { opts.socket = socket; opts.agent = false; finish(opts); })
|
||||
.catch((err) => { log('error', 'tunnel_failed', { error: err.message }); if (!res.headersSent) { res.writeHead(502); res.end('tunnel error'); } resolve('error'); });
|
||||
.catch((err) => { log('error', 'tunnel_failed', { error: err.message, proxy: upstreamProxy }); if (!res.headersSent) { res.writeHead(502); res.end('tunnel error'); } resolve('error'); });
|
||||
} else {
|
||||
finish(opts);
|
||||
}
|
||||
|
||||
@ -124,8 +124,10 @@ 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 代理:Anthropic + Google APIs(无 per-account 代理时)
|
||||
if s.isNodeTLSProxyEnabled() && proxyURL == "" && req != nil && req.URL != nil && req.URL.Scheme == "https" {
|
||||
// Node.js TLS 代理:Anthropic + Google APIs
|
||||
// 无论是否绑定 per-account 代理,都走 node-tls-proxy(指纹伪装)
|
||||
// proxyURL 通过 X-Upstream-Proxy header 传递给 node-tls-proxy 动态选择出口
|
||||
if s.isNodeTLSProxyEnabled() && req != nil && req.URL != nil && req.URL.Scheme == "https" {
|
||||
host := req.URL.Hostname()
|
||||
if host == "api.anthropic.com" ||
|
||||
strings.HasSuffix(host, ".googleapis.com") {
|
||||
@ -184,8 +186,9 @@ func (s *httpUpstreamService) DoWithTLS(req *http.Request, proxyURL string, acco
|
||||
return s.Do(req, proxyURL, accountID, accountConcurrency)
|
||||
}
|
||||
|
||||
// 优先使用 Node.js TLS 代理模式(Anthropic + Google APIs,无 per-account 代理)
|
||||
if s.isNodeTLSProxyEnabled() && proxyURL == "" && req != nil && req.URL != nil {
|
||||
// 优先使用 Node.js TLS 代理模式(Anthropic + Google APIs)
|
||||
// 无论是否绑定 per-account 代理,都走 node-tls-proxy(指纹伪装)
|
||||
if s.isNodeTLSProxyEnabled() && req != nil && req.URL != nil {
|
||||
host := req.URL.Hostname()
|
||||
if host == "api.anthropic.com" || strings.HasSuffix(host, ".googleapis.com") {
|
||||
return s.doViaNodeTLSProxy(req, proxyURL, accountID, accountConcurrency)
|
||||
|
||||
@ -79,6 +79,12 @@ func (s *httpUpstreamService) doViaNodeTLSProxy(req *http.Request, proxyURL stri
|
||||
originalHost := req.URL.Host
|
||||
proxyReq.Header.Set("X-Forwarded-Host", originalHost)
|
||||
|
||||
// 如果账号绑定了代理(落地机 GOST),通过 header 传递给 node-tls-proxy
|
||||
// node-tls-proxy 会用此代理作为上游出口,实现动态路由
|
||||
if proxyURL != "" {
|
||||
proxyReq.Header.Set("X-Upstream-Proxy", proxyURL)
|
||||
}
|
||||
|
||||
// 重写请求 URL:https://api.anthropic.com/v1/... → http://127.0.0.1:3456/v1/...
|
||||
proxyReq.URL.Scheme = "http"
|
||||
proxyReq.URL.Host = fmt.Sprintf("%s:%d", listenHost, listenPort)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user