ICMP 与 Traceroute 原理
ICMP 是什么
IP 协议是"尽力而为"的,丢包了也不吭声。但网络排障需要知道"为什么丢包"——是地址错了?还是路由环路?还是防火墙拦截?
ICMP(Internet Control Message Protocol,互联网控制报文协议) 是 IP 的"诊断系统",负责报告错误和传递状态信息。它封装在 IP 包中(Protocol=1),但不是上层协议,而是 IP 层的配套协议。
ICMPv4 报文类型
ICMP 报文分为两大类:
- 差错报文:报告错误(Type 3, 5, 11, 12)
- 查询报文:请求/响应(Type 0, 8, 13, 14)
常见类型码
| Type | Code | 含义 | 场景 |
|---|---|---|---|
| 0 | 0 | Echo Reply | ping 成功返回 |
| 3 | 0 | Network Unreachable | 路由表没有该网络 |
| 3 | 1 | Host Unreachable | 网络可达,主机不可达 |
| 3 | 2 | Protocol Unreachable | 协议未运行 |
| 3 | 3 | Port Unreachable | 端口未监听 |
| 3 | 4 | Fragmentation Needed, DF set | MTU 不匹配 |
| 5 | 0 | Redirect | 路由器重定向 |
| 8 | 0 | Echo Request | ping 请求 |
| 11 | 0 | TTL exceeded in transit | TTL 耗尽(路由环路) |
| 11 | 1 | TTL exceeded in fragment reassembly | 分片重组超时 |
| 12 | 0 | Parameter Problem | IP 首部参数错误 |
Echo Request / Reply(ping)
主机 A → 主机 B:ICMP Echo Request
Identifier: 0x1234(标识一次 ping 会话)
Sequence Number: 1(第 1 个包)
Data: "abcdefghijklmnopqrstuvwabcdefghi"(填充数据)
主机 B → 主机 A:ICMP Echo Reply
Identifier: 0x1234(同 Request)
Sequence Number: 1(同 Request)
Data: 原样返回
Identifier:区分同一主机上多个并发的 ping 进程 Sequence Number:统计丢包和乱序 Data:接收方原样返回,发送方计算往返时间(RTT)
Destination Unreachable(Type 3)
最常见的排障报文:
- Network Unreachable(Code 0):路由器没有到目标网络的路由
- Host Unreachable(Code 1):最后一跳路由器 ARP 不到目标主机
- Port Unreachable(Code 3):UDP 目标端口未开放(Traceroute UDP 模式利用此特性)
- Fragmentation Needed(Code 4):包太大需要分片,但 DF=1
Time Exceeded(Type 11)
Code 0(TTL 耗尽):
包每经一个路由器 TTL 减 1,到 0 时路由器丢弃并返回 ICMP Time Exceeded。这是 Traceroute 的核心机制。
Code 1(分片重组超时):
目的主机收到部分分片后启动计时器,如果超时未收齐所有分片,丢弃并返回此报文。
Redirect(Type 5)
路由器告诉主机:"你下次直接发给另一个路由器更近"。
安全风险:攻击者伪造 ICMP Redirect,篡改主机路由表,把流量引向恶意节点。现代系统默认忽略 ICMP Redirect。
Traceroute 三种实现方式
Traceroute 利用 TTL 递增或端口探测,逐跳发现路径上的路由器。
方式一:UDP 模式(Linux 默认)
主机发送 UDP 到目标高端口(33434 起),TTL=1
↓
第 1 跳路由器 TTL-1=0,丢弃,返回 ICMP Time Exceeded
↓
主机记录第 1 跳 IP,发下一个包 TTL=2
↓
第 2 跳路由器 TTL-1=0,丢弃,返回 ICMP Time Exceeded
...
直到 TTL 足够大,包到达目标主机
↓
目标主机发现 UDP 端口未开放,返回 ICMP Port Unreachable
↓
Traceroute 结束
方式二:ICMP 模式(Windows tracert)
发送 ICMP Echo Request,TTL 从 1 递增。每跳路由器返回 ICMP Time Exceeded,目标返回 Echo Reply。
方式三:TCP 模式(tcptraceroute)
发送 TCP SYN,TTL 递增。用于绕过只放行 TCP 的防火墙。目标返回 SYN+ACK 或 RST。
对比
| 方式 | 协议 | 目标返回 | 适用场景 |
|---|---|---|---|
| UDP | UDP 高端口 | Port Unreachable | 通用,但防火墙可能拦 |
| ICMP | Echo Request | Echo Reply | Windows 默认,但防火墙可能拦 |
| TCP | TCP SYN | SYN/ACK 或 RST | 绕过防火墙,最可靠 |
三种模式的核心差异在到达目标时的返回信号:UDP 模式依赖目标端口未开放(返回 Port Unreachable),ICMP 模式依赖目标响应 Echo Reply,TCP 模式则利用目标必然响应的 SYN/ACK(端口开放)或 RST(端口关闭)。因此 TCP 模式最擅长绕过只放行特定端口的防火墙。
ICMPv6(RFC 4443)
ICMPv6 功能对应 ICMPv4,但类型码重新定义,且集成了 MLD(组播侦听发现)。
| ICMPv6 Type | 含义 | 对应 ICMPv4 |
|---|---|---|
| 128 | Echo Request | Type 8 |
| 129 | Echo Reply | Type 0 |
| 1 | Destination Unreachable | Type 3 |
| 2 | Packet Too Big | Type 3 Code 4(新) |
| 3 | Time Exceeded | Type 11 |
| 4 | Parameter Problem | Type 12 |
| 130 | MLD Query | IGMP Query |
| 131 | MLD Report | IGMP Report |
| 132 | MLD Done | IGMP Leave |
Packet Too Big(Type 2) 是 IPv6 特有:中间路由器发现包超过 MTU 时,不丢弃静默,而是返回此 ICMPv6,包含下一跳 MTU 值。这是 IPv6 PMTUD 的关键。
这张图把 ICMP 的两大类别(查询 vs 差错)和核心类型码一网打尽。排障时看到 ICMP Type 就能快速定位问题层级:Time Exceeded 通常是路由环路或 Traceroute,Destination Unreachable 细分的 Code 值则告诉你具体是网络、主机、端口还是 MTU 问题。
本篇小结
- ICMP 是 IP 的诊断系统,报告错误和传递状态
- Echo Request/Reply 实现 ping;Time Exceeded 实现 Traceroute
- Destination Unreachable 细分网络/主机/端口/协议/分片不可达
- ICMP Redirect 有安全风险,现代系统默认禁用
- Traceroute 有 UDP/ICMP/TCP 三种模式,TCP 最擅长绕过防火墙
- ICMPv6 类型码重新定义,新增 Packet Too Big,集成 MLD
动手实践
ping 8.8.8.8,Wireshark 过滤icmp,观察 Identifier、Sequence Number、Datatracert -d 8.8.8.8(Windows)或traceroute -I 8.8.8.8(Linux ICMP 模式),Wireshark 观察 TTL 递增和 ICMP Time Exceededtraceroute -T -p 80 www.example.com(TCP 模式),对比 UDP 模式的差异故意制造 TTL 耗尽:
# Linux ping -t 1 8.8.8.8 # 观察返回的 ICMP Time Exceeded 来自哪个路由器思考:为什么有些服务器 ping 不通但网站能打开?(防火墙丢弃 ICMP Echo,但放行 TCP 80/443)