NEWAPI访问中转站国内正常,国外超时解决方案

典型现象:TCP 443 可以连接,但 HTTPS 请求长时间停留在 TLS ClientHello 阶段,最终返回 EOF 或连接超时;限制 TLS 版本或密钥交换组后立即恢复。

结论与直接解决方案

本次故障不是 New API 服务异常,也不是目标站完全封禁了海外服务器,而是以下条件叠加造成的:

1
2
3
4
5
6
7
TLS 1.3 默认启用混合后量子密钥交换
+
ClientHello 体积明显增大
+
特定网络路径存在 PMTU 黑洞
=
TCP 可以连接,但 TLS 握手超时

本次 New API 使用 Go 1.26.1。最直接、风险较低的处理方式,是通过 Go 官方提供的 GODEBUG 开关禁用 X25519MLKEM768

1
2
3
4
services:
new-api:
environment:
GODEBUG: tlsmlkem=0

如果已经配置了其他 GODEBUG 参数,应使用逗号追加:

1
2
3
4
services:
new-api:
environment:
GODEBUG: "原有参数,tlsmlkem=0"

修改后重新创建容器:

1
docker compose up -d --force-recreate new-api

随后重新测试 New API 渠道。本次修改后的结果为:

1
2
3
success: true
HTTP 200
耗时: 7.085 秒

该设置只禁用 ML-KEM 混合密钥交换,不会关闭 TLS 1.3。连接仍可使用 TLS 1.3、X25519 和 AES-GCM,只是不再提供混合后量子密钥交换能力。

问题现象

在 New API 中接入第三方中转站:

1
https://api.a6api.com

国内服务器测试正常,当前海外服务器等待约 60 秒后失败:

1
Post "https://api.a6api.com/v1/chat/completions": EOF

New API 本身运行正常,其他渠道也没有明显异常。

基础网络检查

目标域名能够正常解析:

1
api.a6api.com -> 45.61.235.131

基础连通性测试结果:

检查项目 结果
DNS 解析 正常
ICMP Ping 正常
TCP 80 正常
HTTP 80 返回 302,跳转至 HTTPS
TCP 443 可以完成三次握手
默认 HTTPS TLS ClientHello 后超时

这说明故障不属于普通的 DNS 解析失败、完整路由中断或目标端口未开放。问题发生在 TCP 连接建立之后、TLS 握手完成之前。

关键验证

测试服务器环境:

1
2
curl 8.14.1
OpenSSL 3.5.5

1. 默认 TLS 配置失败

直接访问目标站:

1
2
curl -4 -v --connect-timeout 10 --max-time 60 \
https://api.a6api.com/

客户端发送约 1568 字节的 TLS ClientHello 后,服务端没有返回 ServerHello:

1
2
TLSv1.3 (OUT), Client hello
Connection timed out

2. 限制为 TLS 1.2 后正常

1
curl -4 -v --tls-max 1.2 https://api.a6api.com/

结果立即返回:

1
HTTP/1.1 200 OK

此时 ClientHello 约为 222 字节。

3. TLS 1.3 仅使用 X25519 后正常

1
curl -4 -v --curves X25519 https://api.a6api.com/

结果同样正常:

1
2
TLSv1.3 / TLS_AES_256_GCM_SHA384
HTTP/1.1 200 OK

此时 ClientHello 缩小到约 512 字节。

ClientHello 的实际大小会受 TLS 库、扩展、密码套件和密钥组配置影响,上述数字是本次环境中的测试结果。

测试结果说明:

  • TLS 1.3 本身可以正常使用。
  • 目标站证书和密码套件没有异常。
  • 小型 ClientHello 可以通过。
  • 默认配置生成的较大 ClientHello 会触发超时。

因此,排查重点应从“是否支持 TLS 1.3”转向“链路是否能正确传输接近 MSS 上限的 TCP 分段”。

路径 MTU 验证

进一步进行禁止分片的 Ping 测试,得到以下结果:

IPv4 报文总长度 ICMP 负载参数 结果
1500 字节 -s 1472 失败
1480 字节 -s 1452 失败
1468 字节 -s 1440 成功

Linux 下可使用:

1
2
3
ping -4 -M do -s 1472 45.61.235.131
ping -4 -M do -s 1452 45.61.235.131
ping -4 -M do -s 1440 45.61.235.131

IPv4 的 ICMP 测试中,报文总长度约等于 -s 指定的负载大小加 28 字节的 IP 和 ICMP 头部。

该结果表明,这条路径无法稳定传输接近 1500 字节的 IPv4 报文。服务器网卡 MTU 虽然是 1500,但中间某段链路的实际 MTU 更小。

需要注意:ICMP 与 TCP 可能因为 ECMP、策略路由或防火墙规则而经历不同处理,因此 Ping 结果不能单独作为绝对证明;但它与“大 ClientHello 失败、小 ClientHello 成功”的现象高度吻合。

原因分析

ClientHello 为什么会变大

Go 1.24 以后默认启用了混合后量子密钥交换组 X25519MLKEM768。OpenSSL 3.5 也会默认提供相应的后量子密钥组。

该方案结合 X25519 与 ML-KEM,可增强对未来量子计算攻击的抵抗能力,但也会携带更大的密钥材料,从而显著增加 TLS ClientHello 的体积。

本次部署使用 Go 1.26.1。启用默认密钥组后,ClientHello 约为 1568 字节;限制为传统 X25519 后,ClientHello 缩小到约 512 字节。

为什么 TCP 443 能连,TLS 却会超时

TCP 三次握手使用的 SYN、SYN-ACK 和 ACK 报文都很小,因此即使路径 MTU 异常,也通常能够完成连接。

TLS 握手开始后,较大的 ClientHello 会促使 TCP 发送接近协商 MSS 上限的分段。如果两端按照 1500 MTU 协商出约 1460 字节的 TCP MSS,而中间链路只能传输更小的报文,就可能出现以下过程:

  1. TCP 三次握手正常完成。
  2. 客户端发送包含较大 ClientHello 的 TCP 数据。
  3. 接近 1500 字节的 IP 报文在中间链路无法通过。
  4. 中间设备没有正确返回 ICMP Fragmentation Needed,或者该消息被防火墙过滤。
  5. 客户端无法获知实际路径 MTU,也就不能及时降低报文大小。
  6. 服务端始终无法收到完整的 ClientHello,因而不会返回 ServerHello。
  7. 客户端持续重传,最终表现为连接超时或 EOF

这就是典型的 Path MTU Discovery 失效,也称为 PMTU 黑洞。

curl -v 中看到的 1568 字节是 TLS 握手消息大小,不代表它一定以单个 1568 字节 IP 包在网络中传输。真正触发故障的是它会产生接近 MSS 上限的 TCP 分段,而这些分段超过了实际路径 MTU。

为什么国内服务器正常

决定结果的不是简单的“国内”或“海外”,而是访问请求所经过的具体路径:

1
源服务器 -> 出口运营商 -> 国际中转网络 -> 目标服务器

国内服务器所在路径可能满足以下任一条件:

  • 全链路支持 1500 MTU。
  • 中间设备能够正确返回 ICMP Fragmentation Needed
  • 出口网关配置了 TCP MSS Clamping。
  • 使用了不同的运营商、BGP 路由或国际出口。
  • 中间防火墙能够正确处理较大的 TLS ClientHello。
  • 客户端使用的 TLS 库或版本没有默认发送 ML-KEM 密钥组。

海外服务器走的是另一条路径,其中某一段实际 MTU 较小,同时 PMTU Discovery 没有正常工作。因此,相同目标站在不同服务器上的表现可能完全不同。

其他解决方向

GODEBUG=tlsmlkem=0 是应用层兼容方案,改动范围小、见效快。如果需要从网络层彻底解决,还可以考虑:

  1. 联系海外服务器运营商,提供目标 IP、MTR 和禁止分片 Ping 结果,请其检查路径 MTU。
  2. 检查服务器、宿主机、NAT 网关和出口防火墙是否过滤了 ICMP Fragmentation Needed
  3. 在出口网关配置 TCP MSS Clamping,使 TCP MSS 与实际路径 MTU 匹配。
  4. 为目标 IP 配置较小的路由 MTU,并在确认合适数值后再长期使用。
  5. 更换 VPS 出口 IP、运营商或机房线路。
  6. 通过网络路径正常的代理节点访问目标站。
  7. 由目标站接入 CDN 或反向代理,减少客户端直连源站时的路径差异。

同类问题快速排查

遇到“TCP 443 能连接,但 HTTPS 卡在 ClientHello”的问题,可以依次执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 默认 TLS 配置
curl -4 -v --connect-timeout 10 --max-time 60 \
https://example.com/

# 限制为 TLS 1.2
curl -4 -v --tls-max 1.2 \
https://example.com/

# 保留 TLS 1.3,但只使用 X25519
curl -4 -v --curves X25519 \
https://example.com/

# 检查 TCP 443 路径
mtr -4 -rwzc 20 -T -P 443 example.com

# 检查禁止分片时可通过的最大报文
ping -4 -M do -s 1472 example.com
ping -4 -M do -s 1440 example.com

如果表现为“小 ClientHello 正常、大 ClientHello 超时”,应优先检查:

  • Go/OpenSSL 是否默认启用了 ML-KEM 混合密钥组。
  • 路径 MTU 是否小于服务器网卡 MTU。
  • ICMP Fragmentation Needed 是否被过滤。
  • 出口网关是否需要配置 MSS Clamping。

总结

本次故障的表面现象是海外 New API 请求目标站时等待约 60 秒,最终返回 EOF;实际故障点位于 TCP 建连之后、TLS ServerHello 返回之前。

强制 TLS 1.2 或将 TLS 1.3 密钥组限制为 X25519 后,请求立即恢复;结合禁止分片测试,可以判断默认的混合后量子 ClientHello 触发了异常路径上的 PMTU 黑洞。

对于 New API,优先使用以下配置即可恢复业务:

1
2
environment:
GODEBUG: tlsmlkem=0

业务恢复后,再根据需要联系网络运营商修复 PMTU Discovery、ICMP 过滤或 MSS 配置问题。