ICMP 实战与排错 — 互联网控制报文协议

Wireshark ICMP 过滤式、ping/traceroute/mtr/hping3 实操、ping 不通与 MTU 黑洞排查 / 网络层 / Protocol=1 / RFC 792

这篇你能学到

  • 怎么用 Wireshark / tcpdump 的过滤式,一眼揪出 Type/Code,把"报错回执"翻译成故障原因;
  • ping / traceroute / mtr / hping3 各在什么场景用、输出该怎么读(尤其是"中间跳丢包≠故障"这个坑);
  • “ping 不通"“能 ping 不能连"“小包通大包不通"等八类故障的排查套路,以及 ICMP/ICMPv6 该放行还是该禁。

1. 抓包观察

1.1 Wireshark 显示过滤式

过滤式作用
icmp / icmpv6所有 ICMP / ICMPv6 报文
icmp.type == 8Echo Request(谁在 ping 谁)
icmp.type == 0Echo Reply
icmp.type == 8 || icmp.type == 0完整 ping 会话
icmp.type == 3所有目的不可达(排错第一刀)
icmp.type == 3 && icmp.code == 1主机不可达(下一跳 ARP 失败)
icmp.type == 3 && icmp.code == 3端口不可达(UDP 无监听 / traceroute 终点)
icmp.type == 3 && icmp.code == 4需分片但 DF 置位 → MTU 问题铁证
icmp.type == 3 && icmp.code == 13被防火墙/ACL 明确拒绝
icmp.type == 11Time Exceeded(traceroute 或路由环路
icmp.type == 5ICMP 重定向(可能是攻击)
icmp.mtu直接显示 Next-Hop MTU 字段值
icmp.ident == 0x1234按 Identifier 追踪某个 ping 进程
icmp.seq > 100长时间 ping 的后段
icmp.resp_not_found有请求无应答——Wireshark 自动标记,找丢包极快
icmp.resptime > 100RTT 超过 100 ms 的应答,定位高延迟
data.len > 1000异常大载荷的 ICMP,怀疑 ICMP 隧道
icmpv6.type == 2IPv6 Packet Too Big(IPv6 的 MTU 问题)
icmpv6.type == 135 || icmpv6.type == 136NDP 邻居请求/通告(IPv6 版 ARP)
icmpv6.type == 134路由器通告 RA(SLAAC 排错)

捕获过滤式(BPF)icmpicmp[icmptype] == 8icmp[icmptype] == 3icmp6

1.2 典型字段判读

成功的 ping

1
2
3
4
5
6
7
8
9
Internet Control Message Protocol
    Type: 8 (Echo (ping) request)
    Code: 0
    Checksum: 0x4d5a [correct]
    Identifier (BE): 4660 (0x1234) ← 区分不同 ping 进程
    Sequence Number (BE): 1 ← 递增,用于算丢包/乱序
    [Response frame: 43] ← Wireshark 自动关联应答帧
    Timestamp from icmp data: ... ← 载荷中的时间戳,RTT 来源
    Data (48 bytes)

一条差错报文(信息量远大于 ping 成功):

1
2
3
4
5
6
7
Internet Protocol Version 4, Src: 10.0.0.1 (报错的路由器), Dst: 192.168.1.10 (原发送方)
Internet Control Message Protocol
    Type: 3 (Destination unreachable)
    Code: 4 (Fragmentation needed)
    MTU of next hop: 1400 ← 关键路径 MTU 就是它
    Internet Protocol Version 4, Src: 192.168.1.10, Dst: 203.0.113.5 ← 原始包头
    Transmission Control Protocol, Src Port: 51234, Dst Port: 443 ← 原始前8字节

判读三要点

  1. 外层源 IP = 谁在报错,直接锁定故障设备;
  2. 内层原始 IP 头 + 端口 = 哪条连接出的问题,能精确对应到业务;
  3. Type/Code 组合 = 原因,见速查表。

2. 常用命令 / 配置

2.1 ping

这组命令能干什么:回答"目标到底通不通、RTT 多少、走过了几跳、能不能扛大包”。-c 限定个数(Linux 默认无限,必加)、-s 调载荷大小、-M do 强制 DF=1 用来探 MTU、-t 指定 TTL 看第几跳、-I 指定出接口或源地址。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
ping -c 4 8.8.8.8 # 发 4 个包(Linux 默认无限,必加 -c)
ping -c 100 -i 0.2 8.8.8.8 # 间隔 0.2 秒,快速统计丢包率
ping -c 4 -s 1000 8.8.8.8 # 指定载荷 1000 字节(实际IP包 = 1000+8+20)
ping -c 3 -M do -s 1472 8.8.8.8 # MTU 探测:DF=1 且载荷1472 → 恰好 1500
ping -c 4 -t 5 8.8.8.8 # 指定 TTL=5,观察第5跳是谁
ping -c 4 -I eth0 8.8.8.8 # 指定出接口(多网卡必用)
ping -c 4 -I 10.0.0.5 8.8.8.8 # 指定源地址(验证回程路由)
ping -f 8.8.8.8 # 洪泛 ping(需 root),压测用,慎用
ping -D -c 4 8.8.8.8 # 每行加时间戳,便于与日志对齐
ping -A 8.8.8.8 # 自适应间隔,贴近实际 RTT

ping6 -c 4 2001:4860:4860::8888
ping -c 4 ff02::1%eth0 # IPv6 无广播,用全节点组播发现本链路设备

输出判读

1
2
64 bytes from 8.8.8.8: icmp_seq=1 ttl=113 time=12.3 ms
     ↑ ICMP报文大小 ↑ 序号 ↑ 剩余TTL ↑ RTT
  • ttl=113 → 初值大概率 128(Windows 系)或 120(部分设备),128−113 = 经过 15 跳;
  • icmp_seq 跳号 → 丢包;乱序 → 多路径或链路抖动;
  • time 波动剧烈 → 拥塞、无线干扰或 CPU 处理慢(网络设备对 ICMP 常是低优先级软件转发,RTT 高不一定代表转发平面差)。

2.2 traceroute / mtr

这组命令能干什么:traceroute 回答"数据包到你家要经过哪几跳、卡在哪一跳”;mtr 则是 traceroute + 持续丢包统计,专门用来定位"丢包到底发生在哪一跳”。-I 走 ICMP、-T -p 走 TCP 最贴近真实业务、-n 不反解 DNS 更快。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
traceroute 8.8.8.8 # Linux 默认 UDP 33434+
traceroute -n 8.8.8.8 # 不反解 DNS,快得多
traceroute -I 8.8.8.8 # ICMP Echo 模式
traceroute -T -p 443 example.com # TCP 模式,最贴近真实业务路径
traceroute -m 15 -q 1 8.8.8.8 # 最大15跳,每跳只发1个探测
tracepath 8.8.8.8 # 自带 PMTU 发现,会输出 pmtu 值

mtr -rwc 100 8.8.8.8 # 持续100轮+报告模式,定位丢包在第几跳
mtr -T -P 443 example.com # TCP 模式
mtr -n --report-cycles 50 8.8.8.8

mtr 结果判读的关键陷阱:某中间跳显示 30% 丢包、但后续跳都是 0%,说明该跳只是对 ICMP 限速(控制平面),转发平面完全正常,不是故障。只有从某跳开始丢包一路持续到最后一跳,才说明问题出在那里。

2.3 抓包

这组命令能干什么:在网卡层面"听诊"真实流量,确认你发的 ICMP 到底有没有、收到的是哪类差错、有没有被中途吃掉。tcpdump 的 icmp[icmptype] 表达式能精准只抓某类报文;tshark 那行用来统计各类 ICMP 的数量分布。

1
2
3
4
5
6
7
8
9
sudo tcpdump -i eth0 -nn icmp
sudo tcpdump -i eth0 -nn -v 'icmp[icmptype] == 3' # 只抓不可达
sudo tcpdump -i eth0 -nn 'icmp[icmptype]==3 and icmp[icmpcode]==4' # 只抓 MTU 通知
sudo tcpdump -i eth0 -nn 'icmp[icmptype] == 11' # 只抓超时(查环路)
sudo tcpdump -i eth0 -nn -v -s 0 icmp -w icmp.pcap
sudo tcpdump -i eth0 -nn 'icmp6' # IPv6

# 统计各类 ICMP 数量
tshark -r icmp.pcap -T fields -e icmp.type -e icmp.code | sort | uniq -c | sort -rn

2.4 构造与压测:hping3 / nping

这组命令能干什么:当你需要"自己造"一个特定 ICMP 包(比如指定 Type、指定载荷长度)来测防火墙策略,或当 ICMP 被禁时改用 TCP SYN 探活,hping3 / nping 就派上用场了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 自定义 ICMP 包
sudo hping3 -1 -c 3 8.8.8.8 # -1 = ICMP 模式
sudo hping3 -1 -c 3 -d 1400 8.8.8.8 # 指定数据长度
sudo hping3 -1 -c 3 --icmptype 13 8.8.8.8 # 发时间戳请求

# 探测被防火墙拦截的主机(TCP 探活,ICMP 被禁时的替代方案)
sudo hping3 -S -p 443 -c 3 example.com

# nping(nmap 套件)
sudo nping --icmp --icmp-type echo -c 3 8.8.8.8
sudo nping --icmp --mtu 1400 -c 3 8.8.8.8

2.5 系统与防火墙配置

这份配置能干什么:查看/调整 Linux 对 ICMP 的响应行为(禁不禁 ping、接不接重定向、开不开 PMTUD、PMTU 下限防伪造),以及用 iptables 做"精细放行"——放行诊断必需的 Type,丢弃危险的 Type 5/13/17,而不是一刀切 DROP。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 查看/修改 ICMP 相关内核参数
sysctl net.ipv4.icmp_echo_ignore_all # 1 = 不响应任何 ping
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 # 防 Smurf
sysctl -w net.ipv4.conf.all.accept_redirects=0 # 不接受重定向(防劫持)
sysctl -w net.ipv4.conf.all.send_redirects=0
sysctl -w net.ipv4.ip_no_pmtu_disc=0 # 启用 PMTUD
sysctl net.ipv4.route.min_pmtu # PMTU 下限,防伪造

# iptables:推荐的精细放行策略(不要一刀切 DROP ICMP)
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT # 含 Code 4,必须放行
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s -j ACCEPT
iptables -A INPUT -p icmp --icmp-type redirect -j DROP
iptables -A INPUT -p icmp -j DROP

# 查看某台主机的 PMTU 缓存
ip route get 203.0.113.5 # 输出中的 mtu 字段
ip route show cache

Cisco 侧对应的放行配置能干什么:在路由器/交换机上把 ICMPv4 必要的几类放行(echo-reply、packet-too-big 等价 Type3 Code4、time-exceeded、unreachable),关掉重定向和定向广播以堵安全洞;注意 no ip unreachables 要慎用——它会让 traceroute 失效。

1
2
3
4
5
6
7
8
! Cisco:放行必要 ICMP
access-list 101 permit icmp any any echo-reply
access-list 101 permit icmp any any packet-too-big ! 等价于 Type3 Code4,必放
access-list 101 permit icmp any any time-exceeded
access-list 101 permit icmp any any unreachable
no ip redirects ! 关闭重定向
no ip unreachables ! 慎用:会让 traceroute 失效
no ip directed-broadcast ! 防 Smurf

2.6 Windows

Windows 上的对应命令能干什么:和 Linux 同款思路——-f 即 DF、-l 指载荷,用来探 MTU;tracert/pathping 看路径与丢包;Test-NetConnection 做综合连通性测试;netsh 那行在 Windows 防火墙放行 ICMPv4 Echo。

1
2
3
4
5
6
ping -n 4 -l 1472 -f 8.8.8.8 # -f 即 DF,-l 载荷长度
tracert -d -h 15 8.8.8.8
pathping -n 8.8.8.8 # tracert + 各跳丢包统计
Test-NetConnection 8.8.8.8 # 综合测试(ICMP + TCP)
Test-NetConnection example.com -Port 443
netsh advfirewall firewall add rule name="Allow ICMPv4" protocol=icmpv4:8,any dir=in action=allow

3. 常见故障与排错

3.1 现象:ping 不通

先记住结论:排查 ping 不通,第一步永远是看输出里有没有 From <IP> 前缀——有前缀说明收到了明确的 ICMP 差错报文、可直接定位到报错设备;没有前缀就是纯静默丢弃,排查面大得多。这一步决定后续所有方向。

ping 输出含义下一步
From 192.168.1.1 Destination Net Unreachable该路由器无路由在该设备上 ip route get <目的IP>,补路由或查路由协议邻居
From 10.0.0.1 Destination Host Unreachable最后一跳ARP 不到目标目标是否开机、是否同 VLAN、ip neigh 查邻居表
Destination Host Unreachable From)本机ARP 不到下一跳检查网关配置、本机 ip neigh show <网关>
From x.x.x.x Communication prohibited被 ACL 明确拒绝定位该设备的防火墙/ACL 规则
Request timed out / 100% packet loss静默丢弃① 目标禁 ping(icmp_echo_ignore_all=1)② 防火墙 DROP ③ 回程路由缺失
ping: unknown hostDNS 解析失败与 ICMP 无关,查 /etc/resolv.confdig

“ping 不通但业务正常"很常见——大量服务器与云安全组默认禁 ICMP。此时应改用 TCP 探活验证:

1
2
3
4
nc -zv example.com 443
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com
sudo hping3 -S -p 443 -c 3 example.com
traceroute -T -p 443 example.com

3.2 现象:ping 通但业务连不上

先记住结论:ICMP 走通只证明三层可达,一丁点都不能说明四层端口可用——业务连不上几乎都是目标端口没监听、或被防火墙只放行了 ICMP 而拦了业务端口。

排查顺序nc -zv <IP> <端口> 测端口 → 目标端 ss -lntp 确认服务在监听且不是只绑 127.0.0.1 → 检查防火墙/安全组是否只放行了 ICMP → 抓包看 TCP SYN 是否有 SYN-ACK 或 RST 回应。

3.3 现象:小包通、大包不通(MTU 黑洞)——最经典的疑难杂症

先记住结论“小包通、大包不通"这八个字,直接指向 MTU 黑洞——根因几乎都是 ICMP Type 3 Code 4 被防火墙丢了,发送方永远收不到"包太大、请分片"的通知,于是死循环地发大包、被丢、再发。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 1. 二分法确定真实 PMTU
ping -c 2 -M do -s 1472 目标 # 失败
ping -c 2 -M do -s 1400 目标 # 失败
ping -c 2 -M do -s 1372 目标 # 成功 → PMTU = 1372 + 28 = 1400

# 2. 确认是否收到 ICMP 通知(收不到 = 黑洞)
sudo tcpdump -i eth0 -nn 'icmp[icmptype]==3 and icmp[icmpcode]==4'

# 3. 查看内核记录的 PMTU
ip route get 目标IP # 看输出中有无 mtu 字段

处置:调小接口 MTU;网关做 MSS Clamping(iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu);根治是放行 ICMP Type 3 Code 4

3.4 现象:traceroute 中间跳全是 * * *

先记住结论:中间跳全是 * * * 绝大多数不是故障——通常是路由器禁了/限速了 ICMP Time Exceeded 回复,或不响应 UDP 高端口探测。判定标准只有一个:最后一跳能否到达。

判定标准:最后一跳能否到达。可换探测方式复测:traceroute -I(ICMP)、traceroute -T -p 443(TCP,最贴近业务)。若三种方式最后一跳都不通,才是真故障。

3.5 现象:收到大量 ICMP Type 11(TTL 超时)

先记住结论:大量 Type 11 是路由环路的典型信号——包在两台(或多台)设备之间被互相当作下一跳,永远到不了目的地,直到 TTL 归零不断产生 Time Exceeded。

排查mtr 观察是否有两个 IP 交替出现;在环路涉及的每台设备上执行 ip route get <目的IP> 逐跳确认下一跳;检查静态路由配置错误、动态路由双向重分发未做防环(tag 过滤)、路由收敛中的瞬时环路。

3.6 现象:主机路由表莫名多出条目 / 流量被劫持

先记住结论:主机路由表莫名多出条目、或流量被引向陌生网关,多半是收到了 ICMP 重定向(Type 5)——可能是网络在"好心"优化路径,也可能是中间人攻击在劫持流量。

排查与处置tcpdump -i eth0 'icmp[icmptype]==5' 看谁发的;ip route show cache 查看重定向产生的缓存路由;关闭接受:sysctl -w net.ipv4.conf.all.accept_redirects=0

3.7 现象:RTT 很高但业务不慢

先记住结论:ping 延迟高、业务却不慢,通常是因为网络设备把 ICMP 交给 CPU 软件转发(控制平面),优先级低于硬件转发的数据流量——CPU 一忙 ping 就飙高,但实际数据转发毫无影响。

验证:用 TCP 层面的延迟做对照,如 curl -w '%{time_connect}\n'mtr -T -P 443,若 TCP 延迟正常则可排除真实性能问题。

3.8 现象:IPv6 完全不通,ping6 无响应,邻居状态 FAILED

先记住结论:IPv6 完全不通、邻居状态 FAILED,首要怀疑 ICMPv6 被防火墙全量拦截——因为 NDP(地址解析)、RA(地址自动配置)、MLD(组播)、PMTUD 全部依赖 ICMPv6,全禁等于直接拔网线。

1
2
3
4
5
ip -6 neigh show # FAILED/INCOMPLETE 说明 NDP 不通
sudo tcpdump -i eth0 'icmp6' # 看 NS/NA/RS/RA 是否存在
ping -c 3 ff02::1%eth0 # 全节点组播,探测本链路存活设备
# 放行(参考 RFC 4890)
ip6tables -A INPUT -p icmpv6 -j ACCEPT

4. 与其他协议对比

维度ICMPIPARPIGMPTCP/UDP
所属层网络层(封装于 IP)网络层数据链路层网络层(封装于 IP)传输层
职责差错报告 + 诊断寻址与转发IP→MAC组播成员管理端到端数据传输
标识方式Type + CodeProtocol 号Operation 码Type端口号
Protocol 号1(v6 为 58)26 / 17
可靠性不可靠,无重传不可靠不可靠不可靠TCP 可靠 / UDP 不可靠
是否有连接TCP 有 / UDP 无
RFC792 / 4443791 / 82008261112 / 2236 / 33769293 / 768

ICMPv4 与 ICMPv6 的核心差异

维度ICMPv4ICMPv6
Protocol / Next Header158
Type 划分无规律0–127 差错,128–255 信息
校验和不含伪首部包含 IPv6 伪首部
承担职责仅差错与诊断差错诊断 + NDP + MLD + PMTUD
能否全禁可以(代价是失去 PMTUD)绝对不能,会导致网络瘫痪
分片相关Type 3 Code 4Type 2 Packet Too Big

5. 速查表 / 常见面试题

5.1 速查

记忆点
IP Protocol 号1(ICMPv6 = 58)
Echo Request / ReplyType 8 / 0
目的不可达Type 3
TTL 超时Type 11 Code 0
MTU 不足Type 3 Code 4(含 Next-Hop MTU)
UDP 端口无监听Type 3 Code 3
防火墙拒绝Type 3 Code 13
差错报文携带原始 IP 头 + 前 8 字节数据
IPv6 Packet Too BigICMPv6 Type 2
IPv6 NDPICMPv6 Type 135/136(NS/NA)
MTU 探测ping -M do -s <载荷>,载荷 + 28 = MTU
必须放行Type 3 Code 4,否则 MTU 黑洞

5.2 常见面试题

Q1:ping 用的是什么协议?工作在哪一层? ICMP,网络层。ICMP 报文封装在 IP 数据报中(Protocol=1),不使用端口——ping 的"端口"是不存在的概念。

Q2:traceroute 的原理是什么?为什么中间跳会显示 * * * 依次发送 TTL=1,2,3… 的探测包,每台路由器在 TTL 归零时回 ICMP Type 11,从而逐跳还原路径。* * * 通常是该路由器禁用或限速了 ICMP Time Exceeded 回复,不代表链路故障——只要最终目的可达即可。

Q3:Linux traceroute 默认用 UDP,怎么知道到达终点了? 探测目标的高端口(33434 起,通常无人监听),目标主机回 ICMP Type 3 Code 3(Port Unreachable),即判定到达。Windows tracert 用 ICMP Echo,收到 Echo Reply 判定终点;TCP 模式则看 SYN-ACK/RST。

Q4:为什么 ICMP 差错报文要带原始 IP 头 + 8 字节数据? 让源主机能定位是哪条连接出的错。前 8 字节包含 TCP/UDP 的源端口与目的端口,加上 IP 头的源目地址与协议号,恰好构成五元组,内核据此把错误投递给正确的套接字。

Q5:Destination Host UnreachableRequest timed out 有什么区别? 前者收到了明确的 ICMP 差错报文,说明路径上某设备主动告知无法投递(可据 From 后的 IP 直接定位故障点);后者什么都没收到,说明包被静默丢弃或回程不通,排查面更大。

Q6:为什么不能把 ICMP 全部禁掉? ① 破坏 PMTUD(Type 3 Code 4 被丢 → MTU 黑洞,小包通大包死);② 失去 ping/traceroute 诊断能力;③ IPv6 下更致命——ICMPv6 承载 NDP/MLD/PMTUD,全禁直接导致网络不可用。正确做法:按 Type/Code 精细放行 + 限速。

Q7:Type 3 Code 4 的作用?为什么它这么重要? “需要分片但 DF 置位”。它携带 Next-Hop MTU 字段,是 IPv4 PMTUD 的唯一信息来源。被拦截即形成 MTU 黑洞——生产环境最难查的故障之一。

Q8:ICMP 重定向是做什么的?为什么通常关闭? 路由器发现主机选的下一跳不是最优(且最优下一跳与主机同网段)时发出提示。因为攻击者可伪造 Redirect 把主机流量引向自己实现中间人,所以现代系统普遍 accept_redirects=0

Q9:ping 通了能说明业务正常吗? 不能。ping 只验证三层可达,不能说明目标端口有服务在监听、四层策略是否放行、应用是否健康。应用 nc -zvcurltelnet 等做四层/七层验证。

Q10:mtr 显示中间某跳丢包 30%,是不是那台设备有问题? 不一定。如果后续跳丢包为 0,说明该跳只是对 ICMP 响应限速(控制平面低优先级),转发平面正常。只有从某跳起丢包一路持续到最后一跳,才指向真实故障。

Q11:为什么 ICMPv6 的重要性远高于 ICMPv4? ICMPv6 不只报错,还吸收了 IPv4 中 ARP(→NDP Type 135/136)与 IGMP(→MLD Type 130-132/143)的全部职责,并且是 IPv6 PMTUD(Type 2)的唯一途径。禁掉 ICMPv6 等于同时禁掉了地址解析、地址自动配置和组播。

Q12:为什么 ICMP 不对 ICMP 差错报文再产生差错报文? 防止无限循环与放大风暴:若 A 的差错报文触发 B 回一个差错报文,B 的又触发 A…… 网络会被瞬间淹没。RFC 1122 同时禁止对广播/组播包、非首片、非单播源产生差错报文,都是出于同样的防放大考虑。