ICMP协议
一、ICMP协议简介
IP协议本身并没有终端系统提供直接的方法来发现那些发往目的地址失败的IP数据包,且没有提供直接的方式来获取诊断信息。为了解决这些不足之处,将一个特殊的Internet控制报文协议
,也就是ICMP
,与IP结合使用,以便提供与IP协议层配置和IP数据包处置相关的诊断和控制信息。
ICMP报文是在IP数据报内被封装传输的,如图所示。在IPv4中,协议(Protocal)
字段值为1表示该报文携带了ICMPv4。

如图所示,为ICMPv4的报文格式。所有的ICMP报文都以8位的类型(Type)
和代码(Code)
字段开始,其后的16位校验和(CheckSum)
字段涵盖了整个报文。

如果一个ICMP实现收到一个校验和错误的ICMP报文,该报文将被丢弃;没有ICMP报文可以表示收到的ICMP报文中的校验和是错误的。
二、ICMP报文
2.1 报文类型
ICMP报文可以分为两大类:
- 差错报文:有关IP数据报传递的ICMP报文
- 查询报文:有关信息采集和配置的ICMP报文
常用的ICMP报文类型如下表所示,其中*
表示最常见的类型:
类型 | 正式名称 | E/I | 用途/注释 |
---|---|---|---|
0* | 回显应答 | Info | 回显(ping)应答,返回数据 |
3* | 目的不可达 | Error | 不可达的主机/协议 |
4 | 源端抑制 | Error | 表示拥塞(弃用) |
5* | 重定向 | Error | 表示应该被使用的可选路由器 |
8* | 回显 | Info | 回显(ping)请求(数据可选) |
9 | 路由器通告 | Info | 指示路由器地址/优先级 |
10 | 路由器请求 | Info | 请求路由器通告 |
11* | 超时 | Error | 资源耗尽(例如IPv4 TTL) |
12* | 参数问题 | Error | 有问题的数据包或头部 |
常用的ICMP报文代码号见《TCP/IP详解 卷一》第二版 250页
在ICMP中,对传入报文的处理随着系统的不同而不同。一般来说,传入的信息类请求将被操作系统自动处理,而差错类报文传递给用户进程或传输层协议。
2.2 差错报文
限制生成ICMP差错报文的原因是限制生成所谓的广播风暴
,在这种情况下生成少数的报文就会造成不想要的流量喷流(例如,无限的为响应差错报文而生成差错报文)。
以下情况下不会响应产生ICMPv4差错报文:
- ICMPv4差错报文(但是,响应ICMPv4查询报文可能会产生ICMPv4差错报文)
- 目的地址是IPv4广播地址或IPv4组播地址的数据报
- 作为链路层广播的数据报
- 不是第一个分片的其他分片
- 源地址不是单个主机的数据报。即源地址不能为零地址、环回地址、广播地址或组播地址
除了控制ICMP报文产生的条件,还有限制从单一发送者发出的ICMP总体流量水平的规则。一种推荐的限制ICMP报文速率的方法是使用令牌桶(token bucket)
。采用令牌桶后,每个“桶”保存了最大数量(B)的“令牌”,每个“令牌”允许一定数量的报文被发送。桶定期被新的令牌(速率为N)填充,并且每发送一个报文便减1。因此,令牌桶可以使用参数(B,N)来表述。
一个ICMP差错报文中会包含一个导致错误的数据报的IP头部,以及任何IP选项,再加上原始数据报的IP有效载荷区中的任何其他数据,同时要确保生成的IP/ICMP数据报的大小不会超过一个特定值。对于IPv4来说,这个值是576字节。
包含原始IP数据报的有效载荷使接受的ICMP模块能够根据IP头部中的协议
或者下一个头部
字段将该报文和特定的协议及应用进程相关联。
2.2.1 目的不可达
这种类型的报文用来表示数据报无法送达目的地,可能是因为传输过程中出现了问题或接收者缺乏兴趣接收它。常用的代码有4个,包括:
- 主机不可达(代码1)
- 端口不可达(代码3)
- 需要分片/指定不用分片(代码4)
- 管理禁止通信(代码13)
ICMPv4目的不可达报文格式如图所示:

具体的细节如下:
- 主机不可达——代码1:这种形式的目的不可达报文是由路由器或者主机产生的,出现在当它被要求是由直接交付方法发送一个IP数据报到一个主机,但由于某些原因无法到达目的地时。
- 管理禁止通信——代码13:这些目的不可达报文能够表明一个管理禁令正阻止到目的地的成功通信。这通常是由一个防火墙故意丢弃流量导致的。
- 端口不可达——代码3:当传入的数据报的目的应用程序还没准备好接受它时,就会生成一个端口不可达报文。
- PTB——代码4:如果一个IPv4路由器收到一个打算转发的数据报,如果数据报大于选定的传出网络接口的MTU,则数据报需要分片。如果到达的数据报在IP头部中设置了
不分片
位字段,那么它会被丢弃而不是转发,此时将产生ICMPv4目的不可达(PTB)报文。
2.2.2 重定向
假如一个路由器收到一个来自主机的数据报,并确定自身并不是主机将数据报投递到目的地的对应下一跳,则该路由器发送一个重定向报文到主机并将该报文发送到正确的路由器(或主机)。也就是说,如果它能够确定给定的数据报存在一个比自己更好的下一跳路由,它就向主机发送重定向报文使其更新转发表,这样以后目的地一样的流量就会被定向到新的节点中。
如图,一个网段内有1台主机和2个路由器,R1和R2。当主机不正确的使用路由器R2发送一个数据报时,R2通过向主机发送一个重定向报文进行回复,同时将该数据报转发到R1。尽管主机可能被配置为根据ICMP重定向报文来更新它们的路由表,但是在路由器通过动态路由协议已经知道所有可达目的地的最佳下一跳节点这样的假设下,路由器不鼓励这么做。

ICMPv4重定向报文格式如图所示:

2.2.3 超时
每个IPv4数据报在头部中都有一个生存周期(TTL
)字段,当由于TTL或跳数限制字段值太小(即到达值为1或0,且必须转发)致使路由器丢弃报文时,会产生ICMP超时(代码0)报文。其格式如图所示:

另一个不常见的该报文的变体出现在当一个分片的IP数据报只有部分到达目的地时(即在一段时间后并不是所有的分片都到达了)。在这种情况下,一个ICMP超时报文(代码1)的变体被用于告知发送者它的整个数据报被丢弃了。
2.2.4 参数问题
当一个主机或者路由器接收到一个IP数据报,其IP头部存在不可修复的问题时便会产生一个ICMP参数问题报文。在ICMPv4中,当头部中某个字段超过可接受范围导致了一个错误时,一个特殊的ICMP差错报文指针(Pointer)
字段指示了错误字段相对于出错IP头部的偏移值。
例如,指针字段值为1表示一个错误的IPv4 DS
字段或ECN
字段或者ToS
字段。
代码0时ICMP参数问题报文最为常见的变体,可用于IPv4头部中出现的任何问题。代码1以前被用于指示数据包中缺少例如安全标志之类的选项,目前已经不使用了。代码2用来指示存在一个损坏了的IHL或者总长度字段值。

2.3 查询/信息类报文
尽管ICMP定义了一定数量的查询报文,但是许多功能都已经被其他特殊目的的协议所替代。唯一保存下来的广泛使用的ICMP查询/信息类报文是回显请求/应答
报文,通常称为ping
,以及路由器发现报文
。
2.3.1 回显请求/应答(ping)
一种最为常用的ICMP报文对就是回显请求和回显应答。在ICMPv4中,其类型分别是8和0。ICMP的回显请求报文大小几乎是任意的(受限于最终封装的IP数据报的大小)。收到ICMP回显请求报文后,ICMP的实现要求将任何接收到的数据返回给发送者。即使涉及多个IP分片。其报文格式如下:

与其他ICMP查询/信息类报文一样,服务器必须在回复中包含标识符
和序列号
字段。
在ping的实现中将ICMP报文的标识符
字段设置为某个数,发送主机能够利用它来分离返回的应答。在基于UNIX的系统中,例如,发送进程的进程ID通常被放置在标识符字段。如果由多个ping在同一台主机同时运行的话,这样将允许ping应用程序识别返回的应答,因为ICMP协议不像传输层协议那样有端口号。当涉及防火墙行为时,这个字段通常被称为查询标识符
字段。
当一个新的ping实例运行时,序列号字段从0开始,并且每发送一个回显请求报文便增加1。ping打印出每个返回的数据包的序列号,方便用户查看数据包是否丢失、重排或者重复了。
2.3.2 路由器发现:路由器请求和通告
学习路由器的方式除了DHCP协议之外,还有另一种方式是路由器发现(Router Discovery)
。目前,它用来与移动IP一起使用。
IPv4的路由器发现是通过采用一对ICMPv4信息类报文实现的:路由器请求(RS,类型10)和路由器通告(RA,类型9)。
通告由路由器通过两种方法发送:首先,他们定期对本地网络(使用TTL=1)的所有主机组播地址进行组播,并提供给有需要的主机,它们通常使用RS报文进行请求。使用组播将RS报文发送到所有路由器组播地址上。路由器发现的主要目的是让一台主机学习到它所在的本地子网中的所有路由器,因此它能够从中选择一台作为默认路由。它也被用于发现那些愿意充当移动IP代理的路由器。
如图为ICMPv4 RA报文格式,其中包含了一个IPv4地址列表可用作下一跳的默认路由:

如图所示,地址数
字段给出了报文中路由地址块的个数。每个块包含一个IPv4地址及相应的优先水平。优先水平是一个32位的有符号二进制补码整数,其值越大代表优先级越高。默认的优先水平是0,特殊值0x80000000表示这个地址不应该用作有效的默认路由。地址条目大小
字段给出了给个块的32位字数。生命周期
字段给出了地址列表被认为是有效的秒数。
上图也是一个RA报文,即路由器通告报文,其中包含了一个移动代理通告扩展
。这个扩展遵循传统的RA信息并包含一个值为16的类型
字段,以及一个给出了扩展区域(不包含类型和长度字段)内字节个数的长度
字段,其值为6+4K(K表示地址个数)。序列号
字段给出了自从初始化之后代理产生的这种扩展的个数。注册生命周期
字段给出了发送代理愿意接受MIPv4注册的最大秒数(0xFFFF代表无穷大)。标志位
字段如下:
- R:为MIP服务所需的注册
- B:代理太忙无法接收新注册
- H:代理愿意充当本地代理
- F:代理愿意充当外地代理
- M:支持最小封装格式
- G:代理支持封装数据报的GRE隧道
- r:保留零
- T:支持反向隧道
- U:支持UDP的隧道
- X:支持撤销注册
- I:外地代理支持区域注册
本文作者:Leaos
本文链接:https://www.cnblogs.com/tuilk/p/16304031.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。