第7章:ICMP(Internet Control Message Protocol)
Internet控制报文协议
一、导读
1.1 本章学习目标
第7章讲解ICMP(Internet控制报文协议)——IP层的辅助协议,用于传递控制信息和差错报告。ICMP虽然"辅助"于IP,但它是网络诊断和故障排查的核心工具。ping和traceroute这两个最常用的网络工具都建立在ICMP之上。
本章的核心学习目标包括:
- 理解ICMP的定位和作用:为什么IP需要ICMP作为辅助协议
- 掌握ICMP报文的格式:类型、代码、校验和
- 区分ICMP差错报文和查询报文:各自的类型和使用场景
- 深入理解ping的工作原理:ICMP回显请求/应答的交互过程
- 深入理解traceroute的工作原理:利用TTL和ICMP超时报文发现路由路径
- 了解ICMP在网络安全中的角色:ICMP洪水攻击、防火墙对ICMP的过滤
1.2 为什么本章如此重要
ICMP是网络管理员和开发者最常用的诊断工具的基础。当你遇到网络问题时,第一个反应通常是"ping一下看看"。理解ICMP的工作原理,可以帮助你:
- 更准确地诊断网络故障(区分"主机不可达"和"超时")
- 理解traceroute的输出(每一跳返回的是什么报文)
- 配置合理的防火墙规则(哪些ICMP类型应该允许,哪些应该阻止)
- 理解路径MTU发现(依赖ICMP"需要分片"报文)
此外,ICMP也是很多网络协议和机制的基础:IGMP使用ICMP类型、MPLS的LSP ping使用ICMP、IPv6的NDP使用ICMPv6等。
1.3 核心问题引导
在阅读本章时,请带着以下问题思考:
ICMP报文封装在IP数据报中,那如果IP数据报本身出错了,ICMP差错报文会不会也出错?形成死循环?
ping返回的"Request timeout"和"Destination unreachable"有什么区别?分别对应什么ICMP报文?
traceroute是如何知道每一跳路由器的IP地址的?它发送的是什么报文?
为什么很多防火墙默认阻止ICMP?这样做有什么安全风险?
ICMP差错报文为什么要包含原始数据报的头部和前8字节数据?
ICMP重定向有什么用途?为什么现代网络中很少使用?
二、核心概念详解
2.1 ICMP的定位
ICMP是IP层的辅助协议,用于在主机和路由器之间传递控制信息和差错报告。ICMP报文封装在IP数据报中,协议字段为1。
+-------------+---------------------------+
| IP头部(20B) | ICMP报文 |
| proto=1 | 类型 | 代码 | 校验和 | 数据 |
+-------------+---------------------------+ICMP不是一个"高层"协议——它逻辑上在IP之下,为IP提供差错报告和控制功能。但实现上,ICMP报文封装在IP数据报中,看起来像是在IP之上。
2.2 ICMP报文格式
ICMP报文的通用格式:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据部分(随类型/代码不同而不同) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+2.3 ICMP差错报文
差错报文在检测到错误时由路由器或目的主机生成,发送回源主机。
2.3.1 目的不可达(Destination Unreachable,类型3)
当路由器无法将数据报交付到目的地址时,发送此报文。
| 代码 | 含义 |
|---|---|
| 0 | 网络不可达 |
| 1 | 主机不可达 |
| 2 | 协议不可达(目的主机不支持该协议) |
| 3 | 端口不可达(目的主机没有监听该端口) |
| 4 | 需要分片但设置了DF标志 |
| 13 | 管理禁止(防火墙阻止) |
ICMP差错报文的数据部分包含触发错误的原始IP数据报的头部和前8字节数据(前8字节包含TCP/UDP的端口号等信息),以便源主机将差错与原始连接关联。
2.3.2 超时(Time Exceeded,类型11)
当TTL减到0时,路由器丢弃数据报并发送此报文。
| 代码 | 含义 |
|---|---|
| 0 | 传输中超时(TTL=0) |
| 1 | 分片重组超时 |
这是traceroute的工作原理基础。
2.3.3 源抑制(Source Quench,类型4)
当路由器或主机的缓冲区满时,发送此报文请求源主机减慢发送速度。由于实际效果不佳,现代网络中已基本不使用。
2.3.4 重定向(Redirect,类型5)
路由器通知主机存在更优的路由路径。主机收到后更新路由表。由于安全问题(容易被伪造),现代网络中很少使用。
2.4 ICMP查询报文
2.4.1 回显请求/应答(Echo Request/Reply,类型8/0)
这是ping工具使用的ICMP报文。
回显请求(ping发送):
Type = 8, Code = 0
Identifier | Sequence Number | Data
回显应答(ping响应):
Type = 0, Code = 0
Identifier | Sequence Number | Data(原样返回)Identifier用于区分同一主机上的多个ping进程,Sequence Number用于标识报文的顺序。
ping -c 4 www.example.com
# PING www.example.com (93.184.216.34): 56 data bytes
# 64 bytes from 93.184.216.34: icmp_seq=0 ttl=56 time=25.123 ms
# 64 bytes from 93.184.216.34: icmp_seq=1 ttl=56 time=24.987 ms
# 64 bytes from 93.184.216.34: icmp_seq=2 ttl=56 time=25.012 ms
# 64 bytes from 93.184.216.34: icmp_seq=3 ttl=56 time=24.876 ms分析:
icmp_seq:序列号,从0递增ttl:响应报文的TTL值(可以推算源主机的初始TTL)time:往返时间(RTT)
2.4.2 时间戳请求/应答(Timestamp Request/Reply,类型13/14)
用于同步时钟和测量往返时间。响应中包含三个时间戳: originate、receive、transmit。
2.5 ping的工作原理
ping(Packet Internet Groper)使用ICMP回显请求和回显应答来测试主机之间的连通性和测量往返时间。
2.5.1 ping的执行过程
主机A 主机B
│ │
│ ICMP Echo Request (Type=8) │
│ ID=1234, Seq=1, Time=T1 │
│ ────────────────────────────────────→ │
│ │
│ 处理延迟 │
│ │
│ ICMP Echo Reply (Type=0) │
│ ID=1234, Seq=1, Time=T2 │
│ ←──────────────────────────────────── │
│ │
│ RTT = T_reply_received - T1 │2.5.2 ping的高级用法
# 指定发送间隔
ping -i 0.2 www.example.com # 每0.2秒发送一次
# 指定数据包大小
ping -s 1472 www.example.com # 数据1472 + IP头部20 = 1492
# 设置TTL
ping -t 10 www.example.com # TTL=10
# 设置DF标志
ping -M do -s 1472 www.example.com # 测试路径MTU
# flood ping(压力测试,需要root)
sudo ping -f www.example.com2.6 traceroute的工作原理
traceroute利用ICMP超时报文和递增的TTL值,发现从源到目的的路由路径。
2.6.1 基本算法
第1轮:发送TTL=1的报文
→ 第1跳路由器收到,TTL减到0,丢弃,返回ICMP超时
→ 获得第1跳路由器的IP地址
第2轮:发送TTL=2的报文
→ 第1跳路由器转发,TTL减到1
→ 第2跳路由器收到,TTL减到0,丢弃,返回ICMP超时
→ 获得第2跳路由器的IP地址
...
第N轮:发送TTL=N的报文
→ 到达目的主机,返回ICMP端口不可达(UDP方式)
→ 或返回ICMP回显应答(ICMP方式)
→ 路由发现完成2.6.2 不同实现的差异
| 实现 | 发送的报文 | 期望的响应 |
|---|---|---|
| 原始traceroute(Unix) | UDP高端口号 | ICMP端口不可达 |
| Linux traceroute -I | ICMP Echo Request | ICMP Echo Reply |
| Windows tracert | ICMP Echo Request | ICMP Echo Reply |
| traceroute -T | TCP SYN | TCP RST |
# Linux使用ICMP方式
traceroute -I www.example.com
# Linux使用TCP方式(可以穿透某些防火墙)
traceroute -T -p 80 www.example.com2.7 ICMP与安全
2.7.1 ICMP洪水攻击
攻击者发送大量ICMP回显请求(ping flood),试图耗尽目标的带宽或处理能力。防范措施:限制ICMP报文速率。
2.7.2 Ping of Death
发送超过65535字节的ICMP数据报(通过分片),导致旧系统的缓冲区溢出。现代系统已经修复了这个漏洞。
2.7.3 防火墙对ICMP的处理
很多防火墙默认阻止ICMP报文,但这可能导致问题:
- 阻止ICMP"需要分片"会破坏路径MTU发现
- 阻止所有ICMP会使ping和traceroute失效
- 应该允许必要的ICMP类型(如类型0/3/11),阻止其他类型
三、实战案例
3.1 案例一:使用tcpdump观察ping过程
sudo tcpdump -i eth0 -nn 'icmp'输出示例:
12:34:56.789 IP 192.168.1.100 > 93.184.216.34:
ICMP echo request, id 1234, seq 1, length 64
12:34:56.815 IP 93.184.216.34 > 192.168.1.100:
ICMP echo reply, id 1234, seq 1, length 643.2 案例二:使用tcpdump观察traceroute过程
sudo tcpdump -i eth0 -nn 'icmp or udp'
# 同时执行:traceroute -n www.example.com输出示例:
# TTL=1的探测
12:34:56.789 IP 192.168.1.100 > 192.168.1.1: UDP, length 0
12:34:56.790 IP 192.168.1.1 > 192.168.1.100: ICMP time exceeded
# TTL=2的探测
12:34:57.789 IP 192.168.1.100 > 10.0.0.1: UDP, length 0
12:34:57.790 IP 10.0.0.1 > 192.168.1.100: ICMP time exceeded
# 最终到达目的
12:34:58.789 IP 192.168.1.100 > 93.184.216.34: UDP, length 0
12:34:58.815 IP 93.184.216.34 > 192.168.1.100: ICMP port unreachable3.3 案例三:诊断网络故障
# 步骤1:ping本地网关
ping 192.168.1.1
# 成功 → 链路层和本地网络正常
# 步骤2:ping远程IP
ping 8.8.8.8
# 失败 → 可能是路由问题或ISP问题
# 步骤3:traceroute定位故障点
traceroute 8.8.8.8
# 观察在哪一跳开始超时
# 步骤4:检查ICMP是否被阻止
ping -c 1 8.8.8.8
# 如果"Request timeout"而不是"Destination unreachable"
# 可能是中间设备阻止了ICMP四、常见误区与难点
4.1 误区一:"ICMP在TCP之上"
ICMP封装在IP数据报中,协议字段为1。它在逻辑上是IP的辅助协议,不是TCP或UDP之上的应用层协议。
4.2 误区二:"ping通就代表网络没问题"
ping只测试ICMP报文的往返,不能测试TCP连接。某些防火墙允许ICMP但阻止TCP,或者反之。应该用 telnet host port 或 nc -zv host port 测试TCP连通性。
4.3 难点:理解ICMP差错报文包含原始数据报的原因
ICMP差错报文必须包含触发错误的原始IP数据报的头部和前8字节数据。原因是:源主机可能同时有多个连接,需要通过原始数据报的源/目的IP、协议、端口号来将差错信息关联到正确的连接。
五、本章小结
第7章深入讲解了ICMP协议:
ICMP是IP的辅助协议,用于传递差错报告和控制信息,封装在IP数据报中(协议号1)。
ICMP差错报文包括目的不可达(类型3)、超时(类型11)、源抑制(类型4)等。差错报文包含原始数据报的头部和前8字节。
ICMP查询报文包括回显请求/应答(ping使用)和时间戳请求/应答。
ping使用ICMP回显请求/应答测试连通性和测量RTT。
traceroute利用递增的TTL和ICMP超时报文发现路由路径。
ICMP安全:需要合理配置防火墙规则,不应完全阻止ICMP。
六、思考与练习
思考题
如果防火墙阻止了所有ICMP报文,路径MTU发现还能正常工作吗?为什么?
traceroute发送的每个TTL值通常发3个探测报文,为什么不发1个?3个报文能提供什么额外信息?
为什么ICMP差错报文要包含原始数据报的前8字节数据?只包含IP头部不够吗?
有人建议用ICMP ping的RTT来估算网络延迟,这准确吗?有什么局限性?
练习题
使用tcpdump捕获ping和traceroute的完整过程,分析每个ICMP报文的类型、代码和字段。
使用traceroute测试到三个不同目的地的路由路径,分析延迟分布和可能的瓶颈。
编写一个简单的程序,使用原始套接字发送ICMP回显请求并接收回显应答,实现一个简化版的ping。