关键是要捕获DF=1的IP包及对应的ICMP类型3代码4错误:用tcpdump -i eth0 'ip[6:2] & 0x4000 != 0'捕获DF包,加or (icmp[0]==3 and icmp[1]==4)同步抓ICMP错误,配合ping -M do测试路径MTU。

要排查因路径MTU发现失败或中间设备丢弃分片导致的通信异常,关键之一是捕获并识别设置了DF(Don't Fragment)标志位的IP数据包。这类报文一旦遇到小于其长度的链路MTU,且DF=1,就会被路由器直接丢弃,并可能返回ICMP “Fragmentation Needed and DF set”(类型3,代码4)错误——这正是路径分片丢包的典型信号。
以下是在Linux中用tcpdump精准捕获、验证和初步分析DF报文的实用方法:
捕获带DF标志的IPv4报文
DF位位于IPv4首部的Flags字段(第7–9位),其中第8位(从0开始计)为DF位。tcpdump支持BPF语法直接匹配该位:
sudo tcpdump -i eth0 'ip[6:2] & 0x4000 != 0' -nn -v
-
ip[6:2]:取IP首部第6字节开始的2字节(即Flags + Fragment Offset字段,共16位) -
0x4000:二进制0100 0000 0000 0000,对应DF位(第8位,高位在前) -
& 0x4000 != 0:判断DF是否置1 -
-nn:禁用DNS和端口名解析,提升捕获效率,避免干扰 -
-v:显示IP首部详情(含TTL、ID、Flags、Frag offset等),便于确认DF实际值
✅ 示例输出中你会看到类似:
10.0.1.5.45678 > 10.0.2.6.80: Flags [S], seq 12345, win 64240, options [mss 1460,sackOK,TS val 123456789 ecr 0,nop,wscale 7], length 0
但注意:上述TCP行不显式标DF;需看上层IP行,如:IP (tos 0x0, ttl 64, id 54321, offset 0, flags [DF], proto TCP (6), length 60)← 这里[DF]就是关键标识。
同时捕获DF报文及其可能触发的ICMP错误
路径MTU问题常伴随ICMP Type 3 Code 4响应。可一次性捕获两者,便于关联分析:
sudo tcpdump -i eth0 -nn -w df_debug.pcap \ '(ip[6:2] & 0x4000 != 0) or (icmp[0] == 3 and icmp[1] == 4)'
- 该命令将DF数据包与对应的“需要分片但DF置位”ICMP错误一并保存到
df_debug.pcap - 后续可用Wireshark打开,用显示过滤器
icmp.type == 3 && icmp.code == 4快速定位错误报文,并追踪其Original IP ID或源/目的IP+端口,反向查找哪个DF包触发了它
验证DF行为:主动发包测试
若需复现或验证路径是否阻断DF报文,可用ping配合-M do(禁止分片):
ping -s 1472 -M do 192.168.1.1
-
-s 1472:载荷1472字节 → IP总长 = 20(IP头) + 8(ICMP头) + 1472 = 1500 → 刚好填满标准以太网MTU -
-M do:强制DF=1,不可分片 - 若不通且收到
"Frag needed and DF set",说明路径MTU < 1500;逐步减小-s值(如1400→1300)可定位实际路径MTU
减少抓包丢包,确保DF报文不被遗漏
DF报文本身数量少,但若系统负载高或过滤宽松,tcpdump缓冲区溢出可能导致关键ICMP错误丢失。建议:
- 始终指定精确接口(如
-i eth0),避免any引入额外开销 - 使用
-s 0捕获完整帧,防止截断后无法解析Flags - 优先写入文件(
-w file.pcap),而非实时打印,降低处理延迟 - 如仍见
packets dropped by kernel提示,加-n(已含在-nn中)并考虑调大内核接收缓冲区:sudo sysctl -w net.core.rmem_max=16777216
不复杂但容易忽略


















