生产事件BUG跟进-【curl 卡在 Client Hello 问题复盘】

curl 卡在 Client Hello 问题复盘:MSS/MTU 不匹配导致 PMTUD 黑洞

一、故障现象

卡在了这里。是因为【网络层 MTU 与 TCP MSS 不匹配】需要对方【修复(MSS Clamping)】。

执行命令:

复制代码
curl -vk https://www.good.com/1234 -H 'Content-type:application/xml' -d 'asdf'

输出显示:

  • TCP 连接成功:Connected to 192.168.0.3 port 443 (#0)
  • ALPN 协商完成:h2http/1.1
  • 卡在:TLSv1.3 (OUT), TLS handshake, Client hello (1)
  • 后续无任何回包,直到超时。

同时测试:

复制代码
telnet 192.168.0.3 443

可以成功建立连接。

二、现象分析

  • telnet 成功:说明底层路由可达,TCP 三次握手正常(小包交互)。
  • curl 卡在 Client Hello:TCP 握手成功后,客户端发出第一个携带应用层数据的包(TLS Client Hello),但这个大包丢失,导致 TLS 握手无法继续。

三、根因分析

1. MTU 与 MSS 基础

  • MTU:链路层最大传输单元,以太网默认 1500 字节。
  • MSS:TCP 最大报文段长度。 MSS = MTU - IP头(20) - TCP头(20) = 1460(IPv4)。
  • TCP 三次握手时,双方在 SYN/SYN-ACK 中通告各自 MSS,发送方取对端通告值和本地推算值中的较小值。

2. 为什么小包通、大包丢?

  • telnet 和 TCP 握手包很小,不会触发 MTU 限制。
  • TLS Client Hello 包较大(包含 SNI、ALPN、加密套件、密钥共享等,可能 1000~1400 字节)。
  • 若客户端通告 MSS 为 1460,则会尝试发送 payload 接近 1460 的 TCP 包,加上 IP/TCP 头总长约 1500。
  • 实际路径 MTU 可能小于 1500(VPN 隧道、PPPoE、云专线等),大包在中间设备超限。
  • 若包带 DF 标志,中间路由器无法分片,丢弃该包,并期望返回 ICMP Fragmentation Needed
  • PMTUD 黑洞 :若中间防火墙或安全组过滤了 ICMP 差错报文,客户端收不到反馈,以为网络拥塞,触发 TCP 重传;重传仍是大包,仍被丢,最终 curl 卡死。

3. 为什么调整 MSS 能修复?

  • 在网关或客户端执行 MSS Clamping(MSS 钳制),将 MSS 强制改小(如 1360 或 1400)。
  • 客户端发出的 TLS Client Hello 被 TCP 层拆分成更小的段,加上头部后总长度小于路径 MTU。
  • 小包顺利穿过中间链路,服务器收到 Client Hello,TLS 握手继续,问题修复。

四、验证与修复过程

1. 调整前抓包验证

复制代码
sudo tcpdump -ni any host  192.168.0.3 and port 443 -vv

可看到客户端发出 Client Hello 后,对方没有 ACK,或客户端一直重传,但始终没有 Server Hello。

同时探测路径 MTU:

复制代码
ping -M do -s 1472  192.168.0.3

可能 100% 丢包。

2. 实施修复(MSS Clamping)

Linux 网关示例:

复制代码
# 限制经过网关的 TCP SYN 包 MSS 为 1360
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360

本机发出的流量:

复制代码
iptables -t mangle -A OUTPUT -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360

1360 是较安全的通用值,尤其适合存在 VPN 或隧道封装的场景。

3. 调整后验证

  • 再次执行 curl -vk ...,TLS 握手顺利完成。
  • 抓包确认 Client Hello 被拆分为多个较小 TCP 段,不再超过路径 MTU。
  • TCP 连接能正常传输大文件。

五、经验总结与预防措施

  1. PMTUD 黑洞是运维高频坑:云环境、VPN、PPPoE、GRE/IPIP 隧道中极其常见。特征:小包通、大包丢、TCP 握手成功、TLS/HTTP 卡死。
  2. 放行 ICMP 差错报文 :不要一刀切封禁所有 ICMP。必须放行:
    • IPv4:ICMP type 3 code 4(Fragmentation Needed)
    • IPv6:ICMPv6 type 2(Packet Too Big)
  3. 边缘网关标配 MSS Clamping :在出口路由器、防火墙或云网关上,建议全局开启 tcp adjust-mss 或 iptables TCPMSS --clamp-mss-to-pmtu,作为兜底方案。
  4. 排查工具箱
    • ping -M do -s <size>:探测路径 MTU。
    • tracepathmtr --mtu:探测每一跳 MTU。
    • tcpdump:观察重传,特别是大包是否有去无回。
  5. 注意方向 :MSS 双向独立,MSS Clamping 记得同时处理 FORWARD 链的入方向和出方向,确保 SYN 和 SYN-ACK 都被正确钳制。

六、结论

本次问题虽然表现为 TLS 握手失败,但本质是网络层 MTU 与 TCP MSS 不匹配的经典案例。调整 MSS 相当于给 TCP 层打了一个"截断补丁",让数据包绕过路径中的"窄门",从而恢复通信。

相关推荐
myy-learn1 小时前
33-HTTP协议TCP网页设计相关知识
tcp/ip·http
java_nnnn3 小时前
面试题(网络部分前传)-13问
服务器·网络·网络协议·tcp/ip·面试
上海云盾-小余4 小时前
业务被 DDoS 打崩?四层、七层攻击特征与防护方案复盘
网络·网络协议·tcp/ip·ddos
IpdataCloud15 小时前
高可用的IP数据接口平台有哪些?从可用性、P99延迟到离线部署的评估框架(含代码)
数据库·tcp/ip·ip
隐擎fox19 小时前
解构无感人机验证底层机制:行为生物轨迹采样、环境评分模型与自动化对抗实战
自动化测试·python·网络协议·tcp/ip·网络爬虫
...6221 天前
WinForm中Socket通信服务端客户端代码实现讲解
tcp/ip·c#·socket
captain3761 天前
网络原理(4)-TCP ▲▲▲
java·服务器·网络·网络协议·tcp/ip
上海云盾-小余1 天前
BGP 高防底层原理:TCP 异常流量识别与清洗机制
运维·网络·tcp/ip
captain3761 天前
▲网络原理(2)-TCP
java·服务器·网络·tcp/ip·java-ee