IPsec 的 MTU 与 MSS 问题
IPsec 隧道要在原始报文外面再套一层封装(外层 IP 头、ESP 头、加密相关字段与认证尾),隧道内的有效载荷因此变小。两端链路 MTU 都是 1500 时,隧道内 1500 字节的大包封装后就超过路径 MTU,若路径上又不允许分片,包会被直接丢掉。典型表现很反直觉:ping 通、小文件正常,稍大的传输却卡死,SSH 登录后敲命令卡顿、网页加载到一半停住。
基本信息
| 根本原因 | 封装开销使隧道内报文超过路径 MTU,且分片被禁止 |
|---|---|
| 典型症状 | 小包通、大包丢;握手成功但数据传输卡顿 |
| 封装开销 | 外层 IP 头 + ESP 头 + 加密相关字段,视算法与模式而定 |
| 处理手段 | 下调隧道接口 MTU,或在设备上做 TCP MSS 钳制 |
| 验证方法 | 用不允许分片的 ping 逐步探测临界字节数 |
| 处理范围 | 通常需要两端一起处理并双向验证 |
典型使用场景
- 专线或 VPN 打通后发现部分页面加载失败、文件传输中断
- HTTPS 访问正常但大响应体下载中断,疑似路径 MTU 黑洞
- 自建隧道(GRE/IPsec)后出现随机卡顿,排查链路带宽却没有丢包证据
- 混合云迁移后应用层出现「连得上但传不动」的超时
- 新上线隧道交付验收,做一次大包双向连通性测试
排查步骤与预期结果
| 步骤 | 操作 | 结论判读 |
|---|---|---|
| 1 基础连通 | 小包 ping 对端 | 通说明隧道与路由已就绪 |
| 2 大包探测 | 不允许分片的情况下逐步增大字节数 | 找到临界值,低于该值通、高于该值丢 |
| 3 对照测试 | 同样探测不经隧道的链路 | 隧道内外临界值不同即可确认封装开销影响 |
| 4 调整 | 下调隧道 MTU 或钳制 MSS | 调整后大包恢复通过 |
| 5 双向验证 | 两端各做一次大包传输 | 单向不通说明只处理了一侧 |
探测与临时调整(Linux)
探测与临时调整(Linux)
ping -M do -s 1400 -c 2 10.0.0.1 # 不允许分片,从较小值逐步上调
ping -M do -s 1420 -c 2 10.0.0.1 # 找到临界值即为隧道内可用上限
ip link set dev tun0 mtu 1400 # 下调隧道接口 MTU
# 钳制 TCP MSS:让 TCP 协商出的报文更小,避免依赖路径分片
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
sysctl net.ipv4.tcp_mtu_probing=1 # 开启黑洞探测,作为辅助手段MTU 调整通常要两端一起处理:只改一侧时,反方向的大包仍会被丢弃,表现为「能发不能收」或反过来。改完必须双向做大包验证,并覆盖实际承载长连接的业务。
经验值可作起点而非结论:常见做法是把隧道接口 MTU 设在 1400 以内、把 MSS 钳制到 1360 左右,具体取决于封装模式与加密算法开销,仍需实测确认。ICMP 被策略拦截时 ping 探测会失真,可改用 tcpdump 观察大包是否被封装的中间设备丢弃。