History

fix: 修复反代检测对抗的 3 个问题

- computeFingerprint 使用 rune 索引替代字节索引,修复多字节字符指纹不匹配 - utls Chrome TLS 指纹仅对 Anthropic 官方域名生效,自定义 base_url 走标准 transport - IPv6 地址使用 net.JoinHostPort 正确拼接端口

pzy committed 7 months ago

Commit bb446711 parent 249f9692 files · +22 −15Browse files

Unified · Split

2 files
  1. internal/runtime/executor/claude_executor.go +7 −6
  2. internal/runtime/executor/helps/utls_client.go +15 −9
internal/runtime/executor/claude_executor.go+7−6
@@ -1200,15 +1200,16 @@ const fingerprintSalt = "59cf53e54c78" · 1199 unmodified lines
1200// Algorithm: SHA256(salt + messageText[4] + messageText[7] + messageText[20] + version)[:3]1200// Algorithm: SHA256(salt + messageText[4] + messageText[7] + messageText[20] + version)[:3]
1201func computeFingerprint(messageText, version string) string {1201func computeFingerprint(messageText, version string) string {
1202 indices := [3]int{4, 7, 20}1202 indices := [3]int{4, 7, 20}
1203 var chars [3]byte1203 runes := []rune(messageText)
1204 for i, idx := range indices {1204 var sb strings.Builder
1205 if idx < len(messageText) {1205 for _, idx := range indices {
1206 chars[i] = messageText[idx]1206 if idx < len(runes) {
1207 sb.WriteRune(runes[idx])
1207 } else {1208 } else {
1208 chars[i] = '0'1209 sb.WriteRune('0')
1209 }1210 }
1210 }1211 }
1211 input := fingerprintSalt + string(chars[:]) + version1212 input := fingerprintSalt + sb.String() + version
1212 h := sha256.Sum256([]byte(input))1213 h := sha256.Sum256([]byte(input))
1213 return hex.EncodeToString(h[:])[:3]1214 return hex.EncodeToString(h[:])[:3]
1214}1215}
internal/runtime/executor/helps/utls_client.go+15−9
@@ -103,13 +103,12 @@ func (t *utlsRoundTripper) createConnection(host, addr string) (*http2.ClientCon · 102 unmodified lines
103}103}
104 104
105func (t *utlsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {105func (t *utlsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
106 host := req.URL.Host
107 addr := host
108 if !strings.Contains(addr, ":") {
109 addr += ":443"
110 }
111
112 hostname := req.URL.Hostname()106 hostname := req.URL.Hostname()
107 port := req.URL.Port()
108 if port == "" {
109 port = "443"
110 }
111 addr := net.JoinHostPort(hostname, port)
113 112
114 h2Conn, err := t.getOrCreateConnection(hostname, addr)113 h2Conn, err := t.getOrCreateConnection(hostname, addr)
115 if err != nil {114 if err != nil {
@@ -129,8 +128,13 @@ func (t *utlsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) · 13 unmodified lines
129 return resp, nil128 return resp, nil
130}129}
131 130
132// fallbackRoundTripper tries utls first; if the target is plain HTTP or a131// anthropicHosts contains the hosts that should use utls Chrome TLS fingerprint.
133// non-HTTPS scheme it falls back to a standard transport.132var anthropicHosts = map[string]struct{}{
133 "api.anthropic.com": {},
134}
135
136// fallbackRoundTripper uses utls for Anthropic HTTPS hosts and falls back to
137// standard transport for all other requests (non-HTTPS or non-Anthropic hosts).
134type fallbackRoundTripper struct {138type fallbackRoundTripper struct {
135 utls *utlsRoundTripper139 utls *utlsRoundTripper
136 fallback http.RoundTripper140 fallback http.RoundTripper
@@ -138,7 +142,9 @@ type fallbackRoundTripper struct { · 1 unmodified line
138 142
139func (f *fallbackRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {143func (f *fallbackRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
140 if req.URL.Scheme == "https" {144 if req.URL.Scheme == "https" {
141 return f.utls.RoundTrip(req)145 if _, ok := anthropicHosts[strings.ToLower(req.URL.Hostname())]; ok {
146 return f.utls.RoundTrip(req)
147 }
142 }148 }
143 return f.fallback.RoundTrip(req)149 return f.fallback.RoundTrip(req)
144}150}