fix: 修复反代检测对抗的 3 个问题
- computeFingerprint 使用 rune 索引替代字节索引,修复多字节字符指纹不匹配 - utls Chrome TLS 指纹仅对 Anthropic 官方域名生效,自定义 base_url 走标准 transport - IPv6 地址使用 net.JoinHostPort 正确拼接端口
This commit is contained in:
@@ -1200,15 +1200,16 @@ const fingerprintSalt = "59cf53e54c78"
|
|||||||
// Algorithm: SHA256(salt + messageText[4] + messageText[7] + messageText[20] + version)[:3]
|
// Algorithm: SHA256(salt + messageText[4] + messageText[7] + messageText[20] + version)[:3]
|
||||||
func computeFingerprint(messageText, version string) string {
|
func computeFingerprint(messageText, version string) string {
|
||||||
indices := [3]int{4, 7, 20}
|
indices := [3]int{4, 7, 20}
|
||||||
var chars [3]byte
|
runes := []rune(messageText)
|
||||||
for i, idx := range indices {
|
var sb strings.Builder
|
||||||
if idx < len(messageText) {
|
for _, idx := range indices {
|
||||||
chars[i] = messageText[idx]
|
if idx < len(runes) {
|
||||||
|
sb.WriteRune(runes[idx])
|
||||||
} else {
|
} else {
|
||||||
chars[i] = '0'
|
sb.WriteRune('0')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input := fingerprintSalt + string(chars[:]) + version
|
input := fingerprintSalt + sb.String() + version
|
||||||
h := sha256.Sum256([]byte(input))
|
h := sha256.Sum256([]byte(input))
|
||||||
return hex.EncodeToString(h[:])[:3]
|
return hex.EncodeToString(h[:])[:3]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,13 +103,12 @@ func (t *utlsRoundTripper) createConnection(host, addr string) (*http2.ClientCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *utlsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (t *utlsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
host := req.URL.Host
|
|
||||||
addr := host
|
|
||||||
if !strings.Contains(addr, ":") {
|
|
||||||
addr += ":443"
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname := req.URL.Hostname()
|
hostname := req.URL.Hostname()
|
||||||
|
port := req.URL.Port()
|
||||||
|
if port == "" {
|
||||||
|
port = "443"
|
||||||
|
}
|
||||||
|
addr := net.JoinHostPort(hostname, port)
|
||||||
|
|
||||||
h2Conn, err := t.getOrCreateConnection(hostname, addr)
|
h2Conn, err := t.getOrCreateConnection(hostname, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -129,8 +128,13 @@ func (t *utlsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallbackRoundTripper tries utls first; if the target is plain HTTP or a
|
// anthropicHosts contains the hosts that should use utls Chrome TLS fingerprint.
|
||||||
// non-HTTPS scheme it falls back to a standard transport.
|
var anthropicHosts = map[string]struct{}{
|
||||||
|
"api.anthropic.com": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallbackRoundTripper uses utls for Anthropic HTTPS hosts and falls back to
|
||||||
|
// standard transport for all other requests (non-HTTPS or non-Anthropic hosts).
|
||||||
type fallbackRoundTripper struct {
|
type fallbackRoundTripper struct {
|
||||||
utls *utlsRoundTripper
|
utls *utlsRoundTripper
|
||||||
fallback http.RoundTripper
|
fallback http.RoundTripper
|
||||||
@@ -138,7 +142,9 @@ type fallbackRoundTripper struct {
|
|||||||
|
|
||||||
func (f *fallbackRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (f *fallbackRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
if req.URL.Scheme == "https" {
|
if req.URL.Scheme == "https" {
|
||||||
return f.utls.RoundTrip(req)
|
if _, ok := anthropicHosts[strings.ToLower(req.URL.Hostname())]; ok {
|
||||||
|
return f.utls.RoundTrip(req)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return f.fallback.RoundTrip(req)
|
return f.fallback.RoundTrip(req)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user