2026-06-15 · DECISION TRACE

Claude Code Provider 指纹调整复盘:JUN 8335 恢复与 x666 8334 边界

保留方案、指标、验证、复盘和治理判断,让结论能够追溯。

2026-06-15记录日期
决策记录记录类型
23章节数

Claude Code Provider 指纹调整复盘:JUN 8335 恢复与 x666 8334 边界

  • HTML: https://decision.ht1072.top/2026-06-15-claude-code-provider-fingerprint-jun-x666-2026-06-15.html
  • Local HTML: [已移除本地路径]
  • Generated: 2026-06-15T11:06:59+08:00

Claude Code Provider 指纹调整复盘:JUN 8335 恢复与 x666 8334 边界

页面摘要区

核心结论: JUN 8335 的 channel:client_restricted 不是单纯 User-Agent 问题,而是缺少 Claude Code / Stainless 客户端指纹;补齐 x-stainless-*、收敛 anthropic-beta、固定 Accept: application/json 后,non-stream、stream、tool_calls 均恢复 200。x666 8334 即使本地 adapter 补齐同样指纹仍返回 Go-http-client/1.1,说明被拦的是 x666 服务端出站 client,不是本机请求。

推荐路径: 继续把 JUN 8335 作为可用 Claude Code-shaped provider;x666 8334 保留 adapter 与最新指纹补丁,但不接入 Hermes 正式 provider,直到 x666 后端出站层改掉 Go client 指纹或更换 channel。

关键依据: 同一 key、同一模型下,JUN 单换 UA 全 403,但加完整 Stainless headers 后 /v1/messages/v1/chat/completions 均 200;x666 本地 adapter 加同样 headers 后,健康检查和模型列表 200,真实推理仍四路 403,错误仍显示 检测到:Go-http-client/1.1

落地方式: 已修改 [已移除本地路径][已移除本地路径],并重启对应 systemd user service。JUN 已验证可用;x666 已验证仍不可用,作为上游后端问题留档。

风险与边界: 这次结论只证明 JUN 可通过 headers 指纹恢复、x666 本机侧不可绕过;不证明所有 Claude Code channel 都只看 headers。若上游升级为 TLS/HTTP2 指纹校验,Go/Python 伪装仍可能失效。

背景

2026-06-15,JUN 8335 shim 开始返回:

Request failed: Forbidden
This channel does not allow the current client
Detected: claude-cli/2.1.74 (external, cli)
code: channel:client_restricted

初始判断容易落到“换 UA”上。但实测显示,JUN 当前策略不是只看 User-Agent,而是看一组更接近 Claude Code Node SDK 的客户端指纹。

同一轮排障还回看了 x666 8334:此前 x666 无论直连、本地 adapter、Axon channel 都返回 channel:client_restricted,且错误显示 Go-http-client/1.1。这次用 JUN 恢复经验再次补齐 x666 adapter headers,确认问题仍在 x666 后端出站层。

当前组件状态

JUN 8335

  • service:jun-claude-code-shim.service
  • script:[已移除本地路径]
  • local base_url:http://127.0.0.1:8335/v1
  • upstream:https://muyuan.do/v1/messages
  • inbound key:local-test
  • models:
  • claude-opus-4-8
  • claude-opus-4-6
  • claude-sonnet-4-6

x666 8334

  • service:x666-claude-code-adapter.service
  • script:[已移除本地路径]
  • local base_url:http://127.0.0.1:8334/v1
  • upstream:https://x666.me/v1/messages
  • inbound key:local-test
  • models:
  • claude-opus-4-8-cc
  • claude-sonnet-4-6-cc

探测过程

第一轮:只换 User-Agent,JUN 全部失败

https://muyuan.do/v1/messages 分别测试:

  • claude-cli/2.1.176 (external, cli)
  • claude-cli/2.1.176
  • claude-cli/2.1.74 (external, cli)
  • claude-cli/2.1.45 (external, cli)
  • claude-code/1.0.0
  • Claude-Code/2.1.176
  • anthropic-python/0.64.0
  • anthropic-typescript/0.60.0
  • curl/8.5.0
  • node
  • browser UA

结果:全部 403 或 Cloudflare 拦截。结论:单换 UA 没用。

第二轮:OpenAI endpoint 也不靠单 UA 恢复

https://muyuan.do/v1/chat/completions 做同样 UA 探测,结果仍全 403。结论:不是 /messages 单 endpoint 特有,JUN 当前 channel 对 client 指纹做更完整校验。

第三轮:补齐真实 Claude Code / Stainless headers 后 JUN 通过

参考公开抓包线索与实测,加入:

User-Agent: claude-cli/2.1.74 (external, cli)
x-app: cli
anthropic-beta: interleaved-thinking-2025-05-14,oauth-2025-04-20
x-stainless-lang: js
x-stainless-package-version: 0.75.0
x-stainless-os: Linux
x-stainless-arch: x64
x-stainless-runtime: node
x-stainless-runtime-version: v24.3.0
x-stainless-retry-count: 0
x-stainless-timeout: 600
Accept: application/json
Accept-Encoding: gzip, deflate

JUN /v1/messages 返回 200;JUN /v1/chat/completions 也返回 200。

第四轮:同样经验应用到 x666,仍失败

将 x666 adapter 改成同样 header 指纹,并加 gzip/deflate 解压。重启 x666-claude-code-adapter.service 后验证:

  • /health:200
  • /v1/models:200
  • claude-sonnet-4-6-cc non-stream:403
  • claude-opus-4-8-cc non-stream:403
  • stream:403
  • tool call:403

错误保持:

channel:client_restricted
该渠道不允许当前客户端使用(检测到:Go-http-client/1.1)

这个错误文本说明,被上游检测到的不是本机 adapter 的 Python/Claude headers,而是 x666 服务端出站请求的 Go client。

已落地修改

JUN shim

文件:[已移除本地路径]

主要修改:

  1. 默认 anthropic-beta 从多 beta 收敛为: text interleaved-thinking-2025-05-14,oauth-2025-04-20
  2. 增加 x-stainless-* headers。
  3. Accept 固定为 application/json
  4. Accept-Encoding 固定为 gzip, deflate
  5. 增加 gzip/deflate 解压,避免压缩响应进入 JSON 解析时乱码。
  6. systemd unit 固化: ini Environment="JUN_CC_USER_AGENT=claude-cli/2.1.74 (external, cli)"

验证结果:

non_stream  HTTP 200 content=ok
stream      HTTP 200 SSE 正常返回
tool_call   HTTP 200 返回 tool_calls,参数 {"a":1,"b":2}

x666 adapter

文件:[已移除本地路径]

主要修改:

  1. 默认 UA 改为: text claude-cli/2.1.74 (external, cli)
  2. 增加 anthropic-betax-stainless-* headers。
  3. Accept 固定为 application/json
  4. Accept-Encoding 固定为 gzip, deflate
  5. 增加 gzip/deflate 解压。

验证结果:

/health    HTTP 200
/v1/models HTTP 200
non-stream HTTP 403 Go-http-client/1.1
stream     HTTP 403 Go-http-client/1.1
tool_call  HTTP 403 Go-http-client/1.1

判断

JUN 的根因

JUN 的 403 是本机 shim 发出的 client 指纹不完整。上游能看到并使用我们发出的 header,所以补齐 Stainless 指纹即可恢复。

对应链路:

Hermes / OpenAI SDK
  -> 127.0.0.1:8335 shim
  -> https://muyuan.do/v1/messages
  -> 上游识别 shim 出站 headers

x666 的根因

x666 的 403 不是本机 adapter headers 问题。即使本机 adapter 已发送完整 Claude Code / Stainless 指纹,上游错误仍显示 Go-http-client/1.1,说明 x666 服务端再转发到真实上游时使用了 Go 默认 client 或 Go-like 指纹。

对应链路:

Hermes / OpenAI SDK
  -> 127.0.0.1:8334 adapter
  -> https://x666.me
  -> x666 后端出站到真实 Claude channel
  -> 被识别为 Go-http-client/1.1 并拒绝

本机侧不能改变 x666 后端出站请求的 TLS/HTTP/UA 指纹,因此不能靠 Hermes adapter 解决。

后续建议

短期

  1. JUN 8335 继续作为可用 Claude Code-shaped provider 使用。
  2. x666 8334 保留本地 adapter,但不加入 Hermes 正式 provider。
  3. provider 验证不能只看 /v1/models/health,必须跑: - non-stream - stream - tool_calls - 至少两个模型

x666 若要恢复,需要上游后端改造

x666 服务端出站层至少需要:

User-Agent: claude-cli/2.1.74 (external, cli)
x-app: cli
anthropic-beta: interleaved-thinking-2025-05-14,oauth-2025-04-20
x-stainless-lang: js
x-stainless-package-version: 0.75.0
x-stainless-os: Linux
x-stainless-arch: x64
x-stainless-runtime: node
x-stainless-runtime-version: v24.3.0
x-stainless-retry-count: 0
x-stainless-timeout: 600
Accept: application/json
Accept-Encoding: gzip, deflate

如果仍失败,说明上游还检查 TLS / HTTP2 / header order / transport 指纹。那时 Go 里改 headers 不够,需要:

  • Node/undici sidecar;或
  • curl-impersonate / browser-like transport;或
  • 真 Claude Code sidecar;或
  • 直接换允许 server-to-server 调用的 channel。

Smoke Test 命令

JUN 8335

curl -sS http://127.0.0.1:8335/v1/chat/completions \
  -H 'Authorization: Bearer local-test' \
  -H 'Content-Type: application/json' \
  -d '{"model":"claude-sonnet-4-6","messages":[{"role":"user","content":"只回复ok"}],"max_tokens":16}'

预期:HTTP 200,content 为 ok

x666 8334

curl -sS http://127.0.0.1:8334/v1/chat/completions \
  -H 'Authorization: Bearer local-test' \
  -H 'Content-Type: application/json' \
  -d '{"model":"claude-sonnet-4-6-cc","messages":[{"role":"user","content":"只回复ok"}],"max_tokens":16}'

当前预期:HTTP 403,错误包含 Go-http-client/1.1。若未来变为 200,说明 x666 后端已修复或 channel 已更换。

经验规则

  1. channel:client_restricted 不要先假设是 key 或模型名问题,要看错误里的 detected client。
  2. 如果 detected 是本机发出的 UA,说明本机 adapter 还有机会修。
  3. 如果 detected 是后端出站 client,如 Go-http-client/1.1,而本机已发送不同 UA,则本机 adapter 无法直接修。
  4. /v1/models 200 只能证明模型目录可见,不证明推理链路可用。
  5. Claude Code-shaped provider 的最小验收是:non-stream、stream、tool_calls 三条都 200。
  6. headers 恢复后要处理压缩响应,否则 gzip/deflate 可能让 JSON 解析失败。