fix: always sign cch=00000 placeholder and normalize env fingerprints
Two bugs identified from article "Claude Code封号真相": 1. cch=00000 never replaced (fix): signBillingHeaderCCH was gated by enableCCH (default false), so the cch=00000 placeholder injected by buildBillingAttributionBlockJSON was sent to Anthropic as-is — an obvious fake signal. The function already guards itself via regex match, so the enableCCH gate is removed. 2. NormalizeSystemPromptEnv was dead code (fix): Platform/Shell/OS Version/Working directory fields in user system prompts leaked real machine info (e.g. "Darwin 25.3.0", "/Users/win/...") that Anthropic could use to correlate requests across accounts. Now normalized to canonical values before injecting into the messages pair.
This commit is contained in:
parent
c5eb305f7f
commit
038f0ee8d3
@ -4124,10 +4124,12 @@ func rewriteSystemForNonClaudeCode(body []byte, system any) []byte {
|
|||||||
// 模型仍通过 messages 接收完整指令,保留客户端功能
|
// 模型仍通过 messages 接收完整指令,保留客户端功能
|
||||||
ccPromptTrimmed := strings.TrimSpace(claudeCodeSystemPrompt)
|
ccPromptTrimmed := strings.TrimSpace(claudeCodeSystemPrompt)
|
||||||
if originalSystemText != "" && originalSystemText != ccPromptTrimmed && !hasClaudeCodePrefix(originalSystemText) {
|
if originalSystemText != "" && originalSystemText != ccPromptTrimmed && !hasClaudeCodePrefix(originalSystemText) {
|
||||||
|
// 规范化 env 字段(Platform/Shell/OS/路径),防止真实机器信息被 Anthropic 用作跨账号关联信号。
|
||||||
|
normalizedSystemText := NormalizeSystemPromptEnv(originalSystemText)
|
||||||
instrMsg, err1 := json.Marshal(map[string]any{
|
instrMsg, err1 := json.Marshal(map[string]any{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": []map[string]any{
|
"content": []map[string]any{
|
||||||
{"type": "text", "text": "[System Instructions]\n" + originalSystemText},
|
{"type": "text", "text": "[System Instructions]\n" + normalizedSystemText},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
ackMsg, err2 := json.Marshal(map[string]any{
|
ackMsg, err2 := json.Marshal(map[string]any{
|
||||||
@ -6064,9 +6066,9 @@ func (s *GatewayService) buildUpstreamRequest(ctx context.Context, c *gin.Contex
|
|||||||
|
|
||||||
// OAuth账号:应用统一指纹和metadata重写(受设置开关控制)
|
// OAuth账号:应用统一指纹和metadata重写(受设置开关控制)
|
||||||
var fingerprint *Fingerprint
|
var fingerprint *Fingerprint
|
||||||
enableFP, enableMPT, enableCCH := true, false, false
|
enableFP, enableMPT, _ := true, false, false
|
||||||
if s.settingService != nil {
|
if s.settingService != nil {
|
||||||
enableFP, enableMPT, enableCCH = s.settingService.GetGatewayForwardingSettings(ctx)
|
enableFP, enableMPT, _ = s.settingService.GetGatewayForwardingSettings(ctx)
|
||||||
}
|
}
|
||||||
if account.IsOAuth() && s.identityService != nil {
|
if account.IsOAuth() && s.identityService != nil {
|
||||||
// 1. 获取或创建指纹(包含随机生成的ClientID)
|
// 1. 获取或创建指纹(包含随机生成的ClientID)
|
||||||
@ -6097,10 +6099,9 @@ func (s *GatewayService) buildUpstreamRequest(ctx context.Context, c *gin.Contex
|
|||||||
if fingerprint != nil {
|
if fingerprint != nil {
|
||||||
body = syncBillingHeaderVersion(body, fingerprint.UserAgent)
|
body = syncBillingHeaderVersion(body, fingerprint.UserAgent)
|
||||||
}
|
}
|
||||||
// CCH 签名:将 cch=00000 占位符替换为 xxHash64 签名(需在所有 body 修改之后)
|
// CCH 签名:将 cch=00000 占位符替换为 xxHash64 签名(需在所有 body 修改之后)。
|
||||||
if enableCCH {
|
// 无占位符时函数为 no-op,故无需 enableCCH gate — 占位符存在即意味着必须签名。
|
||||||
body = signBillingHeaderCCH(body)
|
body = signBillingHeaderCCH(body)
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "POST", targetURL, bytes.NewReader(body))
|
req, err := http.NewRequestWithContext(ctx, "POST", targetURL, bytes.NewReader(body))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -9278,9 +9279,9 @@ func (s *GatewayService) buildCountTokensRequest(ctx context.Context, c *gin.Con
|
|||||||
|
|
||||||
// OAuth 账号:应用统一指纹和重写 userID(受设置开关控制)
|
// OAuth 账号:应用统一指纹和重写 userID(受设置开关控制)
|
||||||
// 如果启用了会话ID伪装,会在重写后替换 session 部分为固定值
|
// 如果启用了会话ID伪装,会在重写后替换 session 部分为固定值
|
||||||
ctEnableFP, ctEnableMPT, ctEnableCCH := true, false, false
|
ctEnableFP, ctEnableMPT, _ := true, false, false
|
||||||
if s.settingService != nil {
|
if s.settingService != nil {
|
||||||
ctEnableFP, ctEnableMPT, ctEnableCCH = s.settingService.GetGatewayForwardingSettings(ctx)
|
ctEnableFP, ctEnableMPT, _ = s.settingService.GetGatewayForwardingSettings(ctx)
|
||||||
}
|
}
|
||||||
var ctFingerprint *Fingerprint
|
var ctFingerprint *Fingerprint
|
||||||
if account.IsOAuth() && s.identityService != nil {
|
if account.IsOAuth() && s.identityService != nil {
|
||||||
@ -9302,9 +9303,8 @@ func (s *GatewayService) buildCountTokensRequest(ctx context.Context, c *gin.Con
|
|||||||
if ctFingerprint != nil && ctEnableFP {
|
if ctFingerprint != nil && ctEnableFP {
|
||||||
body = syncBillingHeaderVersion(body, ctFingerprint.UserAgent)
|
body = syncBillingHeaderVersion(body, ctFingerprint.UserAgent)
|
||||||
}
|
}
|
||||||
if ctEnableCCH {
|
// 无占位符时函数为 no-op,故无需 ctEnableCCH gate。
|
||||||
body = signBillingHeaderCCH(body)
|
body = signBillingHeaderCCH(body)
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "POST", targetURL, bytes.NewReader(body))
|
req, err := http.NewRequestWithContext(ctx, "POST", targetURL, bytes.NewReader(body))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user