互联网控制消息协议

互联网协议族的核心协议之一。主要用于IPv4网络,以指示网络操作中的错误消息

互联网控制消息协议(英語:Internet Control Message Protocol,缩写:ICMP)是互联网协议族的核心协议之一。它用于网际协议(IP)中发送控制消息,提供可能发生在通信环境中的各种问题反馈。通过这些信息,使管理者可以对所发生的问题作出诊断,然后采取适当的措施解决。

ICMP [1]依靠IP來完成它的任务,它是IP的主要部分。它与传输协议(如TCPUDP)显著不同:它一般不用于在两点间传输数据。它通常不由网络程序直接使用,除了 pingtraceroute 这两个特別的例子。IPv4中的ICMP被称作ICMPv4,IPv6中的ICMP则被称作ICMPv6

技術細節

ICMP是在 RFC 792 中定义的互联网协议族之一。通常用于返回的错误信息或是分析路由。ICMP错误消息总是包括了源数据并返回给发送者。ICMP错误消息的例子之一是TTL值过期。每个路由器在转发数据报的时候都会把IP包头中的TTL值减1。如果TTL值为0,“TTL在传输中过期”的消息将会回报给源地址。每个ICMP消息都是直接封裝在一个IP数据包中的,因此,和UDP一样,ICMP是不可靠的。

虽然ICMP是包含在IP数据包中的,但是对ICMP消息通常会特殊处理,會和一般IP數據包的處理不同,而不是作為IP的一個子協議來處理。在很多時候,需要去查看ICMP消息的內容,然後發送適當的錯誤消息到那個原來產生IP數據包的程序,即那個導致ICMP訊息被傳送的IP數據包。

很多常用的工具是基於ICMP消息的。traceroute 是通過發送包含有特殊的TTL的包,然後接收ICMP超時消息和目標不可達消息來實現的。 ping 則是用ICMP的"Echo request"(类别代码:8)和"Echo reply"(类别代码:0)消息來實現的。

ICMP报文結構

報頭

ICMP報頭從IP報頭的第160位開始(IP首部20字节)(除非使用了IP報頭的可選部分)。

Bits160-167168-175176-183184-191
160TypeCode校驗碼(checksum)
192Rest of Header
  • Type - ICMP的類型,标识生成的错误报文;
  • Code - 進一步劃分ICMP的類型,该字段用来查找产生错误的原因.;例如,ICMP的目標不可達類型可以把這個位設為1至15等來表示不同的意思。
  • Checksum - Internet校驗和(RFC 1071),用於進行錯誤檢查,該校驗和是從ICMP頭和以該字段替換為0的數據計算得出的。
  • Rest of Header - 報頭的其餘部分,四字節字段,內容根據ICMP類型和代碼而有所不同。

填充數據

填充的數據緊接在ICMP報頭的後面(以8位為一組):

  • Linux的"ping"工具填充的ICMP除了8個8位元組的報頭以外,默认情况下還另外填充數據使得總大小為64字節。
  • Windows的"ping.exe"填充的ICMP除了8個8位元組的報頭以外,默认情况下還另外填充數據使得總大小為40字節。

报文类型

类型代码状态描述查询差错
0 - 响应回显0Echo响应 (被程序ping使用)
1 and 2未分配保留
3 - 目的不可達0目标网络不可达
1目标主机不可达
2目标协议不可达
3目标端口不可达
4要求分段并设置DF flag标志
5源路由失败
6未知的目标网络
7未知的目标主机
8源主机隔离(作废不用)
9禁止访问的网络
10禁止访问的主机
11对特定的TOS 网络不可达
12对特定的TOS 主机不可达
13由于过滤 网络流量被禁止
14主机越权
15优先权终止生效
4 - 源端关闭0弃用源端关闭(拥塞控制)
5 - 重定向0重定向网络
1重定向主机
2基于TOS 的网络重定向
3基于TOS 的主机重定向
6弃用备用主机地址
7未分配保留
8 - 请求回显0Echo请求
9 - 路由器通告0路由通告
10 - 路由器请求0路由器的发现/选择/请求
11 - ICMP 超时0TTL 超时
1分片重组超时
12 - 参数问题:错误IP头部0IP 报首部参数错误
1丢失必要选项
2不支持的长度
13 - 时间戳请求0时间戳请求
14 - 时间戳应答0时间戳应答
15 - 信息请求0弃用信息请求
16 - 信息应答0弃用信息应答
17 - 地址掩码请求0弃用地址掩码请求
18 - 地址掩码应答0弃用地址掩码应答
19保留因安全原因保留
20 至 29保留Reserved for robustness experiment
30 - Traceroute0弃用信息请求
31弃用数据报转换出错
32弃用手机网络重定向
33弃用Where-Are-You(originally meant for IPv6
34弃用Here-I-Am(originally meant for IPv6)
35弃用Mobile Registration Request
36弃用Mobile Registration Reply
37弃用Domain Name Request
38弃用Domain Name Reply
39弃用SKIP Algorithm Discovery Protocol, Simple Key-Management for Internet Protocol
40Photuris, Security failures
41实验性的ICMP for experimental mobility protocols such as Seamoby [RFC4065]
42 到 255保留保留
235实验性的RFC3692( RFC 4727
254实验性的RFC3692( RFC 4727
255保留保留

源站抑制

源站抑制报文旨在请求发送方降低发往路由器或主机的报文发送速率。在接收的过程中,当接收方没有足够的接收缓冲区来处理接收到的报文,或者接收这个报文会导致临近其本身的缓冲区限制时,就会触发源站抑制报文。

数据被从一个或一群主机高速地发往网络上的一个路由器,虽然路由器有缓冲机制,但是路由器的缓冲区大小通常(由于物理内存有限的原因)被限制。因此,如果路由器的通信量过大,路由器最终会(由于内存耗尽,导致必须丢弃掉接收到的数据报)无法继续处理超过输入缓冲区限制的部分数据,直到路由器缓冲队列有空余空间可以存放新的数据报。但是由于网络层(Network Layer)缺乏確認訊息(ACK)机制,因此客户端无法获知数据是否成功抵达接收方。所以研究者提出了源站抑制这一补救措施来解决这一问题:当路由器发现流入数据速率远远高于流出数据速率时,会发送ICMP源站抑制报文给源站,通知源站应该降低其数据传输速度或等待一定时间后再尝试发送更多数据。当源站接收到ICMP源站抑制报文时会减慢数据发送的速度,或者在再次尝试发送数据前等待一定的时间,使得路由器能够(在处理完当前接收到的数据之后)清空输入缓冲队列。

但是因为有研究表明“源站抑制是一种无效的(不公平的)补救措施“,所以路由的源站抑制报文已在1995年被RFC 1812页面存档备份,存于互联网档案馆)弃用。此外,(路由)转发和回应任何形式的源站抑制报文已在2012年被RFC 6633页面存档备份,存于互联网档案馆)弃用

源站抑制报文[1]
0001020304050607080910111213141516171819202122232425262728293031
类型(Type) = 4代码(Code) = 0检验和(Checksum)
未使用
IP数据报头部和源数据报数据的前8个字节

其中:

类型(Type) 必须设置为4
代码(Code) 必须设置为0
IP数据报头部 和其附加的数据用于发送端根据回应报文匹配对应的请求报文

重定向

关于ICMPv4 重定向报文如何工作的示例图

重定向 报文是网关发出的,用于要求主机或路由器改变数据报的传输路径的ICMP报文。ICMP 重定向是路由器将路由信息传达给主机的机制。这种类型的报文通知主机更新它的路由信息(请求主机改变其路由)。如果一个主机在通信时将数据报发送给了路由器R1,而R1将这个数据报转发给了另一个路由器R2,且主机到路由器R2之间有一条直连的路径(也就是说,此主机和路由器R2处于同一以太网段上),那么路由器R1会发送一条重定向报文给主机,来通知它到路由器R2可用路径里有一条更短、更优化的路径。这个主机在接收到这个重定向报文之后应该改变其路由至这个优化版本的路由信息,来将抵达这个目的地的数据报直接发送到路由器R2,并且路由器仍将原始数据报发送到预期目的地。[2]但是,如果一个数据报携带有路由信息,那么即使有更加优化的路径,路由器也不会发送重定向报文。并且,RFC 1122 指出,重定向报文应该只由网关发送,而不应该由互联网主机发送。[3]

重定向报文[1]:11
0001020304050607080910111213141516171819202122232425262728293031
类型(Type) = 5代码(Code)检验和(Checksum)
路由器的IP 地址
激发重定向报文的数据报IP首部及其数据的前8字节

其中:

类型(Type) 必须设置为 5.
代码(Code) 指定重定向的原因,见下表
代码(Code)描述
0针对网络的重定向报文
1针对主机的重定向报文
2针对网络和服务类型的重定向报文
3针对主机和服务类型的重定向报文
路由器的IP 地址(IP address) 是一个32位的网关IP地址,该地址指明了该数据报应该被重定向到的路由器地址。
激发重定向报文的数据报IP首部及其数据的前8字节(IP header) 用于收到重定向报文的主机根据回应报文匹配对应的请求报文,来确定该数据报的目的站地址。

超时

超时 报文是网关产生并发送给源站的ICMP报文,用于通知源站有数据报因为存活時間递减至0而被此网关丢弃。当主机等待数据报分片的过程中超时而无法重新组装数据报分片时也会产生该报文。

超时报文也用于traceroute工具来识别两个主机之间的路径上的网关。

超时报文[1]:5
0001020304050607080910111213141516171819202122232425262728293031
类型(Type) = 11代码(Code)校验和(Checksum)
路由器的IP 地址
激发超时报文的数据报IP首部及其数据的前8字节

其中:

类型(Type) 必须设置为 11
代码(Code) 指定重超时的原因,见下表
CodeDescription
0存活時間计数超时
1分片重装超时
激发超时报文的数据报IP首部及其数据的前8字节 这些信息用于源站根据收到的超时报文来确定具体哪个数据报已被丢弃。对于高层协议,比如用户数据报协议传输控制协议而言,额外的8字节数据指明了已被丢弃的数据报中的源端口与目的端口。

时间戳请求

时间戳请求 报文主要用于互联网机器(包括路由器和主机)之间同步时钟。起始时间戳是发送端最后一次改动该数据报的时间戳(为世界标准时午夜开始计算的毫秒数)。在该类型的报文中,接收时间戳和传输时间戳未被使用。

时间戳请求报文[1]:15
0001020304050607080910111213141516171819202122232425262728293031
类型(Type) = 13代码(Code) = 0检验和(Checksum)
标识符(Identifier)序号(Sequence number)
起始时间戳(Originate timestamp)
接收时间戳(Receive timestamp)
传输时间戳(Transmit timestamp)

其中:

类型(Type) 必须设置为 13
代码(Code) 必须设置为 0
标识符(Identifier) and 序号(Sequence) 用于在时间戳请求报文和时间戳回答报文之间建立关联
起始时间戳(Originate timestamp)世界标准时午夜开始计算的毫秒数。 如果没有可用的世界标准时参考,则可以将最高有效位设置为1以指示这是一个非标准时间值。

时间戳回答

时间戳回答 报文是对时间戳请求报文的回答报文。 时间戳回答报文由接收到的时间戳请求报文其中的起始时间戳和接收时间戳(回应端主机接收到请求报文并创建时间戳回应报文的时间,单位为毫秒)、传输时间戳(时间戳回答报文被发送出去的时间,单位为毫秒)组成。

时间戳回答报文[1]:15
0001020304050607080910111213141516171819202122232425262728293031
类型(Type) = 14代码(Code) = 0检验和(Checksum)
标识符(Identifier)序号(Sequence number)
起始时间戳(Originate timestamp)
接收时间戳(Receive timestamp)
传输时间戳(Transmit timestamp)

其中:

类型(Type) 必须设置为 14
代码(Code) 必须设置为 0
标识符(Identifier)序号(Sequence number) 用于在时间戳请求报文和时间戳回答报文之间建立关联。
起始时间戳(Originate timestamp) 是发送端最后一次改动该数据报的时间戳。
接收时间戳(Receive timestamp) 是回应端主机接收到请求报文并创建时间戳回应报文的时间,单位为毫秒。
传输时间戳(Transmit timestamp) 是最后一次修改回应报文并将其发送出去的时间,单位为毫秒。
所有的时间戳都是世界标准时午夜起始的毫秒数。如果这个时间不能表示为毫秒或者没有可用的世界标准时参考值,则可以使用任何格式的时间值并将最高有效位设置为1以指示这是一个非标准时间值。

地址掩码请求

地址掩码请求 报文是主机为了得到一个合适的子网掩码而发送到路由器的ICMP请求报文。

接收到此请求报文的机器应当发送一个地址掩码回答报文给源站。

地址掩码请求报文
0001020304050607080910111213141516171819202122232425262728293031
类型(Type) = 17代码(Code) = 0检验和(Checksum)
标识符(Identifier)序号(Sequence number)
地址掩码(Address mask)

其中:

类型(Type) 必须设置为 17
代码(Code) 必须设置为 0
地址掩码(Address mask) 可以为0

由于ICMP 地址掩码请求可能会被用于嗅探攻击来收集特定网络的信息,因此该报文默认情况下被Cisco IOS禁用。[4]

地址掩码回答

地址掩码回答 报文携带有地址掩码信息,用于回答地址掩码请求报文。

地址掩码回答报文
0001020304050607080910111213141516171819202122232425262728293031
类型(Type) = 18代码(Code) = 0校验和(Checksum)
标识符(Identifier)序号(Sequence number)
地址掩码(Address mask)

其中:

类型(Type) 必须设置为 18
代码(Code) 必须设置为 0
地址掩码(Address mask) 为待回答的地址掩码

源站不可达

源站不可达 报文是由主机或入站网关用于通知客户端出于目的站无法连接的报文。这些原因可能包括:物理连接失效(也即网络距离无限大),或指定的地址或端口处于非激活状态,或者数据报长度过长而导致必须分片但是IP首部指定了“不分片”选项导致无法分片。如果是TCP端口不可达,则会返回TCP RST,而不会返回此报文。如果是IP多播的情况,也不会返回此报文。

源站不可达报文[1]:3
0001020304050607080910111213141516171819202122232425262728293031
类型(Type) = 3代码(Code)检验和(Checksum)
未使用下一跳的MTU
激发ICMP地址不可达报文的数据报IP首部及其数据的前8字节

其中:

类型(Type) 必须设置为 3
代码(Code) 字段用于指示具体导致源站不可达的原因。见下表。
代码(Code)解释(Description)
0网络不可达
1主机不可达
2协议不可达
3端口不可达
4需要分片但是DF(Do not Fragment)置位
5源路由失败
6目的网络未知
7目的主机未知
8源主机被隔离
9与受到管理禁控的目的网络通信
10与受到管理禁控的目的主机通信
11对于指明的服务类型,网络不可达
12对于指明的服务类型,主机不可达
13出于管理目的禁止通信
14主机越权.
15优先权剥夺生效
Next-hop MTU 当需要分片但是DF(Do not Fragment)置位的错误发生时,包含了下一跳网络的MTU的值。
IP header 用于源站根据收到的源站不可达报文来确定具体哪个数据报引起了源站不可达错误。

參考

外部連結