用 tcpdump 抓 ICMP 是干什么的
tcpdump 支持按 ICMP 类型与代码做精确过滤,是定位不可达、超时、需要分片等问题最直接的证据来源。表达式里 icmp[0] 取类型、icmp[1] 取代码;IPv6 的 ICMPv6 则用 ip6[40] 取类型。配合 -nn 与 -v 才能看到类型与代码细节,否则只剩一层摘要。
基本信息
| 适用平台 | Linux/macOS 的 tcpdump |
|---|---|
| 权限要求 | 抓包需要 root 或 CAP_NET_RAW |
| IPv4 偏移 | icmp[0] 是类型、icmp[1] 是代码 |
| IPv6 偏移 | ip6[40] 是 ICMPv6 类型 |
| 常用选项 | -nn 不做解析、-v 显示细节、-c 限包数、-w 存盘 |
| 常用取值 | 类型 3 不可达、11 超时、8 回显请求;代码 3 端口不可达、4 需要分片 |
典型使用场景
- 定位连接超时:确认收到的是 ICMP 超时还是纯粹丢包不回
- 排查 PMTU 黑洞:抓 IPv4 类型 3 代码 4 与 IPv6 类型 2 是否真的到达
- 判断目标端口是否关闭:端口不可达即类型 3 代码 3
- 验证链路质量:统计回显请求与应答是否成对,算丢包率
- 安全排查:识别异常的 ICMP 隧道、大范围扫描或伪造源地址行为
- 网关与路由变更验证:确认重定向(类型 5)是否被正确下发
常用表达式
常用表达式
# 抓 20 个 ICMP 包并显示类型与代码细节
tcpdump -nn -v 'icmp' -c 20
# 只看「需要分片」:IPv4 类型 3 代码 4
tcpdump -nn 'icmp[0] == 3 and icmp[1] == 4' -c 5
# 端口不可达:类型 3 代码 3
tcpdump -nn 'icmp[0] == 3 and icmp[1] == 3'
# IPv6 包太大:ICMPv6 类型 2
tcpdump -nn 'icmp6 and ip6[40] == 2'
# 回显请求,也就是 ping 请求
tcpdump -nn 'icmp[0] == 8' | head字段偏移读法
| 偏移写法 | 对应位置 | 典型值 |
|---|---|---|
| icmp[0] | ICMP 类型 | 3 不可达、8 回显请求、11 超时 |
| icmp[1] | ICMP 代码 | 0 网络不可达、3 端口不可达、4 需要分片 |
| icmp[4:2] | 校验和字段 | 用于校验报文完整性 |
| ip[6:2] | IPv4 分片标志 | MF/DF 位,判断是否被分片 |
Wireshark 里直接看 Internet Control Message Protocol 的 Type 与 Code 更直观;服务器上没有图形界面时,用 tcpdump 存成 pcap 再回本地分析更稳妥。
ICMP 错误报文只携带触发它的原始 IP 头加前 8 字节负载,因此抓到不可达后要顺着内层包头去匹配到底是哪条连接触发的。
内核默认对 ICMP 发送做限速,高压力场景下抓到的应答数会少于实际错误数,不能直接用抓包计数推算真实错误率。