PMTU 黑洞探测是什么
net.ipv4.tcp_mtu_probing 用于应对路径 MTU 发现失效的情况。TCP 会通过设置不分片标志来探测路径上的最大传输单元,依赖中间设备返回「需要分片」的 ICMP 报文;一旦这条 ICMP 被拦截,发送方就会持续用过大报文重传而毫无反馈,链路虽然能建立连接却传不动数据,这种情形称为 PMTU 黑洞。该参数让内核在检测到黑洞后主动二分探测更小的 MTU。取值为 0 关闭、1 检测到黑洞后启用、2 始终启用。
基本信息
| 参数 | net.ipv4.tcp_mtu_probing |
|---|---|
| 取值 | 0 关闭 / 1 遇黑洞启用 / 2 始终启用 |
| 伴随参数 | net.ipv4.tcp_probe_interval 控制试探间隔(秒) |
| 典型场景 | VPN、隧道、部分云网络与防火墙拦截 ICMP |
| 验证工具 | ping 的禁止分片选项、加长报文的连通性测试 |
| 观察入口 | 内核日志中的 MTU 相关输出 |
典型使用场景
- 隧道与 VPN 环境:封装带来额外头部开销,路径 MTU 小于常规值
- 跨云专线排障:小包正常、大包不通是典型症状
- HTTPS 握手卡住:大证书链在黑洞路径上无法完成协商
- 加固后的网络:安全策略拦截全部 ICMP 时更容易出现此类问题
- 问题复现:用禁止分片的 ping 逐级降低报文长度定位实际 MTU
确认路径 MTU
确认路径 MTU
ping -M do -s 1472 -c 2 10.0.0.1 # 1472 加 28 字节头部等于 1500,成功说明无黑洞
ping -M do -s 1400 -c 2 10.0.0.1 # 逐步减小报文长度定位实际 MTU
sysctl net.ipv4.tcp_mtu_probing # 读当前取值
sysctl -w net.ipv4.tcp_mtu_probing=1 # 遇黑洞时启用探测
dmesg -T | grep -i mtu | tail # 查内核相关输出落盘与回读
落盘与回读
# /etc/sysctl.d/99-net-tuning.conf
net.ipv4.tcp_mtu_probing = 1 # 检测到 PMTU 黑洞后启用探测
net.ipv4.tcp_probe_interval = 600 # 探测间隔,默认值以本机为准
# 回读命令:sysctl net.ipv4.tcp_mtu_probing症状与原因
| 症状 | 可能原因 | 验证方式 |
|---|---|---|
| 小包通、大包不通 | 路径 MTU 黑洞 | 用禁止分片的 ping 逐步缩小报文长度 |
| 连接能建立但传输卡住 | 大报文被静默丢弃 | 抓包看重传是否集中在满载报文 |
| 只有部分目标异常 | 特定路径上的设备拦截 ICMP | 对故障目标单独做分片探测 |
| 启用探测后好转 | 确认是黑洞问题 | 对比启用前后的重传与吞吐数据 |
先复现再启用:小包正常、大包超时,或者连接能建立但传输停滞,是这类问题的典型症状。在确认链路确实存在黑洞之后启用探测,比默认打开更划算。
探测本身有开销:取值 2 会让所有连接都进行试探,带来额外的探测与重传。常规做法是用 1,只在发现问题时才触发,并可通过试探间隔参数控制频率。