服务:curl访问github代理问题

问题现象

2026-10-15,经本机 mihomo 代理访问 GitHub 时 curl 报错:

curl -vS --max-time 20 -x http://127.0.0.1:7890 https://api.github.com/
* CONNECT tunnel established, response 200
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLS connect error: error:0A000126:SSL routines::unexpected eof while reading
curl: (35) TLS connect error: error:0A000126:SSL routines::unexpected eof while reading

同一时刻访问 https://www.google.com/ 也报同样的 unexpected eof。特征是 TCP 隧道已建立(CONNECT 返回 200),但 TLS 握手阶段被对端掐断。

根因分析

不是 curl 命令的问题,也不是 GitHub 相关路由规则的问题。

查 mihomo 日志,找到确证:

[TCP] dial 节点选择 (match GeoSite/github) --> github.com:443
  error: sg-3-1.noraven.com:443 connect error:
         dial tcp 201.4.48.114:443: connect: connection refused

即:「节点选择」当前挂在 新加坡-SG-3-1 这个节点上,而该节点拒连(connection refused),于是所有走「节点选择」的流量全部失败。curl 看到的 unexpected eof 就是节点在 TLS 握手前把连接掐掉的表现。

  • 受影响面:github / google / cloudflare / microsoft / youtube / Telegram(149.154.167.x)等一切走「节点选择」的目标,全部返回 000。
  • 与 GitHub 下载聚合规则无关:api.github.com 不在「下载聚合-github」的域名清单里(清单只有 codeload / objects.githubusercontent.com / release-assets / github-releases / media / raw.githubusercontent.com),它命中的是 GEOSite,github → 节点选择。
  • 节点池本身是好的:走其它组(下载聚合-nixos / -docker)及国内直连均正常;逐节点扫描 33 个节点对 github.com 全部 200。

直接原因 = 「自动选择」停在一个瞬时死掉的节点上、且组的健康检查没及时把它踢掉。

处置

1. 即时止血:切换出口节点

把「节点选择」从卡死的「自动选择」切到一个在线节点,立刻恢复:

curl -X PUT "http://127.0.0.1:9091/proxies/节点选择" -d '{"name":"日本-OS-2-流量倍率:0.6"}'
# 恢复后切回自动:  -d '{"name":"自动选择"}'

2. 重启容器,重跑健康检查

DOCKER_HOST=unix:///run/user/1000/docker.sock docker restart clash

3. 参数硬化(让节点抖动自动切换、免人工干预)

把「坏节点能赖着不走多久」压到最短,并让检查更快判失败:

参数原值新值作用
interval(所有 url-test / load-balance 组)30060每分钟重测,坏节点最多影响 1 分钟
timeout50002000慢/死节点更快判失败被剔除
tolerance(url-test)10050稍快即切,更积极
provider health-check interval300150节点更快被标生死,候选池不含死节点

实测证据

  • 切换节点前:api.github.com 连打 8 次全失败(000)。
  • 切到 日本-OS-2 后:api.github.com → 200。
  • 逐节点扫描(临时 mihomo 实例测 github.com/robots.txt):33 个节点全部 200,耗时 0.64–2.55s;连先前拒连的 SG-3-1 也恢复到 0.68s。
  • 重启后组选择:自动选择 → 新加坡-SG-3-2,谷歌 → 日本-TY-1。

诊断命令

用途命令
看是不是节点拒连docker logs --since 90s clash | grep -iE "refused|error"
看当前选中链curl -s http://127.0.0.1:9091/proxies(读 节点选择 / 自动选择 的 now)
强制某组重测(URL 用该组自己的检查地址)curl "http://127.0.0.1:9091/group/自动选择/delay?url=https%3A%2F%2Fcache.nixos.org%2Fnix-cache-info&timeout=3000"
切换出口节点curl -X PUT "http://127.0.0.1:9091/proxies/节点选择" -d '{"name":"自动选择"}'

踩坑记录

  • 现象:curl 报 error:0A000126:SSL routines::unexpected eof while reading。成因:出口节点拒连,TLS 握手被掐断。处置:查日志确认 refused,切节点。
  • 现象:PUT /configs 热重载后健康检查疑似停摆(组选中的节点长期不改)。成因:热重载未重跑全部健康检查。处置:改用 docker restart clash,让其从头做一轮检查。
  • 现象:一个组只配一个健康检查 URL。成因:用 cache.nixos.org 检查的组会挑出"连 nix 快、连 google/telegram 慢"的节点,自以为健康因而不会切换。处置:按目标拆组、每组用自己目标的 URL 做检查。

边界

  • 本档只记录本机 mihomo(Docker)代理的 curl / GitHub 访问故障定位与处置,不含节点订阅本身的采购与更换。
  • url-test 只按 RTT 排序,测不出"活着但很慢 / 丢包"的节点;整个订阅池大面积挂掉时,任何参数都无法自愈。
  • 「下载聚合」及「谷歌」组的路由规则不在本故障的成因内,勿混为一谈。