ICMP 是什么
ICMP 是 IP 层的配套控制协议,负责报告网络差错(目标不可达、超时、需分片)与执行诊断(Echo 请求与应答),本身不承载用户数据,而是封装在 IP 包里,协议号 1。IPv6 对应的是 ICMPv6(协议号 58),职责更重:它同时承担了邻居发现与组播管理,禁用 ICMPv6 会让 IPv6 直接不可用。
基本信息
| 封装 | IP 协议号 1;ICMPv6 为 58 |
|---|---|
| 报文结构 | 类型(8bit) + 代码(8bit) + 校验和(16bit) + 内容 |
| 大类 | 差错报文 + 查询报文 |
| 规范 | RFC 792(ICMP)、RFC 4443(ICMPv6)、RFC 1122 §3.2.2 |
| 权限 | ping/traceroute 普通用户可用,原始套接字抓包需要 root |
常用类型代码
| 类型 | 名称 | 典型场景 |
|---|---|---|
| 0 | Echo Reply | ping 的应答 |
| 3 | Destination Unreachable | code 0 网络不可达、code 3 端口不可达、code 4 需分片 |
| 5 | Redirect | 同链路存在更优网关 |
| 8 | Echo Request | ping 的请求 |
| 11 | Time Exceeded | TTL 减到 0,也是 traceroute 逐跳探测的依据 |
观察 ICMP
观察 ICMP
tcpdump -nn -v 'icmp' -c 10 # 抓 10 个包并显示类型与代码
tcpdump -nn 'icmp[0]==3 and icmp[1]==3' -c 5 # 只看端口不可达
ping -c 2 1.1.1.1 | tail -2 # 顺手看丢包率与 RTT
iptables -L INPUT -v -n | grep -i icmp # 看本机对 ICMP 的过滤与计数为什么不能全禁
- PMTUD 依赖「需分片」差错报文,禁掉后大包静默丢失,表现为小包通、大包卡死
- traceroute 依赖 TTL 超时报文,全禁后只能看到星号,无法定位路径断点
- ping 是判断「主机是否在线」的最快手段,全禁会让排查只能靠 TCP 探测
- ICMPv6 承载邻居发现,禁用后 IPv6 地址无法解析,链路直接不可用
ICMP 不是 TCP/UDP 的替代品:它属于网络层的控制机制,正确做法是按类型限速,而不是按协议整体封禁。
抓包怎么看
- 先看 icmp[0] 类型:3 是差错、8/0 是 ping、11 是超时
- 再看 icmp[1] 代码细分原因,例如代码 3 表示端口不可达
- 差错报文会带上原始 IP 头与部分载荷,可据此判断是哪个包引发的
- 加 -e 显示链路层地址,确认回复来自预期的下一跳而不是被劫持
策略建议
- 允许 Echo 但按源地址限速,避免成为放大攻击的反射面
- 务必放行「需分片」与「超时」两类差错,否则 PMTUD 与 traceroute 直接失效
- 禁止 Redirect 类型,防止同链路设备改写本机路由
- IPv6 侧必须放行 ICMPv6 的 NS/NA/RS/RA,否则地址无法生效