因特网控制报文协议协议(ICMP)

由于 IP 协议是一种不可靠的协议,无法进行差错控制,ICMP(Internet Control Message Protocol,因特网控制报文协议)设计的最初目的主要是用于IP层的差错报告。随着网络的发展,ICMP 增加了检测和控制功能,大量用于传输控制报文,包括拥塞控制、路径控制以及路由器或主机信息的探测查询。ICMP属于网络层协议,是IP协议的重要补充,但是不能用来传送应用程序数据,只能用来传送有关网络事件和变化的通知报文。本章对ICMP协议进行了介绍和分析,涉及报文类型与格式,以及ICMP应用。

ICMP运行在网络层,是TCP/IP协议簇不可或缺的一部分。RFC 792“Internet Control Message Protocol”是ICMP协议的正式规范文件。它提供了所有有效ICMP报文的基础规范,并定义了ICMP能够传递的信息和服务的类型。还有一些RFC文档对ICMP进行了补充和扩展。

image

如上图所示,ICMP与IP协议都位于网络层,但是ICMP在TCP/IP协议栈中的位置比IP协议略高一些,ICMP报文需要封装在IP数据报的数据部分进行传输。ICMP并不作为一个独立的层次,而只是作为IP层的一部分存在。

ICMP特性

根据RFC 792 文档,ICMP具有以下特性。

  • ICMP为路由器(网关)或目的主机提供了一种与源主机通信的机制。

  • ICMP报文采用了特殊格式的IP数据报,使用了特殊的关联报文类型和代码。

  • 在TCP/IP的某些实现中,ICMP是一项必需的要素,通常作为提供IP基础支持的一部分。

  • ICMP 仅仅报告有关非 ICMP 的 IP 数据报处理的错误。为防止出现有关错误消息的报文的无限循环,ICMP不传送有关自身的任何报文,并且仅仅提供任何分片数据报序列中第 1 个分片的报文。

ICMP报文封装

ICMP 本身是网络层协议。虽然它可以接受来自上层(TCP、UDP)的请求,但并不直接封装来自上层协议的数据,而是将请求转变为ICMP报文。它也不是直接将报文传送给链路层,而是首先要封装成IP数据报,然后再交给链路层封装成数据链路层中的帧,这就是所谓两级封装。包含ICMP报文的IP数据报首部的协议字段值为1,指出数据区内容为ICMP报文。ICMP报文的封装如下图所示。

image

IP软件一旦接收到ICMP报文,就立即交给ICMP模块进行处理。ICMP模块可以形成应答报文,也可以交给上层的应用程序或协议去处理。

ICMP报文格式

ICMP 传输的数据单元称为报文。ICMP 报文由首部和数据两个部分组成。首部为定长的 8字节,前 4字节是通用部分,后个字节随报文类型的不同有所差异。ICMP报文的一般格式如下图所示。

image

1.ICMP首部字段

ICMP 分为通用部分与其他部分。首部通用部分由类型(Type)代码(Code)校验和(Checksum)3个字段构成。

  • 类型字段占1字节(8位),用于指示ICMP报文的类型。例如,0表示回送应答(Echo Reply),3表示目的地不可达(Destination Unreachable)。关于ICMP报文的具体类型可以在IANA网站http://www.iana.org/assignments/icmp-parameters/查看。除了RFC 792规定的报文类型外,其他一些RFC文档(如RFC 950、RFC 1256)规定了一些新的类型。
  • 代码字段占1 字节(8 位),提供关于报文类型的进一步信息。例如,对于报文类型 3 来说,代码0表示网络不可达,代码1表示网络不可达。
  • 校验和字段占2 字节,提供整个ICMP 协议报文的校验和。校验方法与IP 数据报首部校验和算法相同。校验和以16位为单位进行计算,校验和的初始值为0,用1的补码算法对16位小数据块进行求和,最后再对结果求补码,便得到了报文的校验和。与IP数据报首部校验和不同的地方是ICMP协议校验和是整个报文的校验和,另外使用校验和进行校验的设备不是中间的路由器,而是最终的目的地。

首部其他部分为4字节,针对每一种报文类型都是特定的。大部分差错报告报文未用到这一部分,参数错报告报文用到其中的一个字节作指针,请求应答报文对利用这4字节匹配请求与应答报文。不使用时将不使用的部分填0。后面在介绍各类ICMP报文将详细介绍。

2.ICMP数据区

ICMP 数据区因不同的报文类型有所不同。在报告差错时,携带原始出错数据报的首部和数据的前8字节,通常这些信息包括了该数据报的关键信息(前8字节一般为上层协议的首部信息),主要是引起差错的原始数据包部分内容。在请求和应答报文中,携带与请求和应答相关的额外信息,也就是基于查询类型的其他信息。

ICMP功能

IP 协议是尽最大努力的服务,它将数据报从最初的源节点交付到最终的目的节点。但是 IP协议不负责完成差错控制功能,ICMP就是为此设计的,用于在IP主机、路由器之间传递控制报文,从而实现IP层的差错控制。这些控制报文虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。ICMP协议配合IP协议使用,主要具备以下两个功能。

image

报告差错

ICMP 协议主要用于报告路由器或目的主机在处理 IP 数据报时可能遇到的一些问题。在 IP数据报传输过程中引发错误的原因可能是通信线路故障、通信设备故障、路由器中的路由表错误,或者网络处理能力不足等。这些故障一般表现为数据报不能到达目的地、超时或拥塞等。一旦发现传输错误,发现错误的网络节点立即向源主机发送ICMP报文以报告出错情况,便于源主机采取适当的处理措施。当然,源主机本身通常并不能解决这些问题,这就需要有网络管理人员判断和解决。

路由器或目的主机以一对一的模式向源主机报告发生数据报传输错误的原因。出现差错时目的主机可能根本不可到达,因而不能向目的主机报告差错原因;或者出现差错时也不清楚差错由哪一台路由器引起,因而也不向中间的路由器报告差错原因。 注意ICMP在IP层仅仅涉及与传输路径和可达相关的差错问题,而不解决数据本身的差错问题。

ICMP差错报告弥补了IP协议的不可靠问题。ICMP协议只负责报告差错,而将纠正错误的工作留给上层协议去做,数据报的差错报告只发送给发出该数据报的源主机。ICMP 差错报告作为普通的IP数据报传输,并不享受特别的优先级和可靠性保证,另外在产生差错报告的同时会丢弃出错的IP数据报。

所有差错报告报文都包括一个数据区,帮助源主机或管理人员发现引起错误的原因。差错报告报文的数据区包括原始数据报(发出差错报告的主机或路由器所收到的IP数据报)的首部加上该数据报中的前8字节(64位)的数据。原始数据报中的首部用于向接收差错报告的源主机提供关于该数据报本身的信息。该数据报的前8字节用于提供关于TCP或UDP端口号和TCP序列号的信息。这两种信息便于源主机将差错情况通知给上层的TCP或UDP协议。ICMP根据收到的IP 数据报形成差错报告报文,然后再封装成 IP 数据报发送给源主机。差错报告报文的数据区如下图所示。

image

注意

携带ICMP差错报告报文本身的数据报不会再产生ICMP差错报告;分片的数据报如果不是第一个分片,则不会产生ICMP差错报告;具有多播地址或特殊地址(127.0.0.0或0.0.0.0)的数据报也不会产生ICMP差错报告。

目的地不可达

当路由器无法根据路由表转发IP数据报或者主机无法向上层协议和端口提交IP数据报时,将丢弃当前的数据报,并产生目的地不可达(Destination Unreachable)差错报告,向源主机报告出错信息。此类报文格式如下图所示。

image

目的地不可达报文的类型为 3,代码字段取值为 0~15,将目的地不可达的情形细分为 16 种情况,具体说明见下表。

代码说明
0网络不可达,可能是由于硬件故障
1主机不可达,可能是由于硬件故障
2协议不可达,将IP数据报交付上层协议(TCP等)时,上层协议不在运行中,这说明网络和主机都可达。这种报文只能由目的主机产生
3端口可达,目的主机上与该端口对应的应用程序(尽管)不在运行种,这说明网络、主机和协议都可达
4抓包无法分片,数据报的发送方已指明该数据包不能分片,但不进行分片又不可能进行路由选择
5源路由失败,在源路由选项中定义的一个或多个路由器无法通过
6目的网络未知,路由器根本没有关于目的网络的信息
7目的主机位置,路由器根部不知道网络主机的存在
8源主机被隔离
9与目的网络的通信被禁止
10与目的主机的通信被禁止
11对特定的服务类型(TOS),网络不可达
12对特定的服务类型(TOS),主机不可达
13因设置过滤而使主机不可达
14因非法的优先级而是主机不可达

其中RFC 792仅定义了代码0~5。代码6~12由RFC 1122 “Requirements for Internet Hosts Communication Layers(Internet 对主机的要求——通信层)”定义,代码 13~15 由 RFC 1812“Requirements for IP Version 4 Routers(对IPv4 路由器的要求)”定义。

代码为2或3的目的地不可达报文只能由目的主机产生,而其余代码的报文只能由路由器产生。

目的地不可达分为4个不同的层次,从大到小依次为网络不可达、主机不可达、协议不可达和端口不可达。网络不可达可能是路由表有问题或者是目的地址有错。主机不可达可能是信宿机不在运行中或信宿机不存在等,出现主机不可达说明网络是可达的。协议不可达的原因是将IP数据报向上层协议提交时上层协议未在运行中,协议不可达说明网络和主机都可达。端口不可达是因为目的主机上与该端口对应的应用程序不在运行中,端口不可达说明网络、主机和协议都可达。

某些情况下目的地不可达是检测不出来的。例如,在不提供应答机制的以太网上,路由器就不知道数据报是否送达了目的主机或下一跳路由器。路由器无法检测出分组没有交付的所有问题。

超时

在数据报的传输过程中,首部的TTL(生存时间)值用于防止数据报因路由表的问题而无休止地在网络中传输。当TTL值为0时,路由器会丢弃当前的数据报,并产生一个ICMP超时(Time Exceeded)报文发送给源主机。

在目的主机进行分片重组时会启动重组计时器,一旦重组计时器超时,目的主机就会丢弃当前正在重组的数据报,然后产生一个ICMP数据报超时报告,并向源主机发送该超时报告。

超时报文格式与目的地不可达报文格式相同,只是类型值和代码不同。其类型值为11,代码为0或1。在超时报文中,代码0表示TTL超时,即TTL字段值为0,只能由路由器产生。代码1表示分片重组超时,即在规定的时间内没有收到所有的分片,这只能由目的主机使用。

参数问题

一旦路由器或主机发现错误的数据报首部和错误的数据报选项参数时,便丢弃该数据报,并向源主机发送参数问题(Parameter Problem)报文。参数问题主要是数据报首部字段值不明确或空缺。参数问题报文格式如下图所示,类型值为12,代码为0~2。

image

参数问题报文的格式与目的地不可达报文相同,只是类型值为12,代码为0~2,重要的是它还提供一个指针(Pointer)字段。

代码 0 表示数据报首部中的某个字段的值有错或不明确(存在二义性),这时ICMP报文首部的指针指向数据报中有问题的字节,如果这个值为0,则第1个字节是无效字段。

代码1表示数据报首部中缺少某一选项所必须具有的部分参数,此时的ICMP报文没有指针字段。这是由RFC 1108“U.S.Department of Defense Security Options for the Internet Protocol”定义的。

代码2表示长度无效(Bad Length),即数据报结构存在无效长度,此时的ICMP报文没有指针字段。 参数问题报文既可由路由器产生,也可由目的主机产生。

源抑制

IP 是无连接协议,源节点事先并不了解中间的路由器和接收方的处理能力以及缓冲区大小,而且在数据报传输过程中没有采用任何流量控制机制。因此,当大量的数据报进入路由器或目的主机时,会造成缓冲区溢出,即出现拥塞(Congestion)。ICMP利用源抑制(Source Quench,又译为源站抑制或源点抑制)的方法来进行拥塞控制,减缓源节点(发送方)发出数据报的速率。

ICMP的源抑制报文就是为了给IP协议增加一种流量控制而设计的。当路由器或主机因拥塞而丢弃数据报时,它就向数据报的源节点发送源抑制报文。此报文有两个目的,一是通知源节点数据报已被丢弃,二是警告发送方在路径中的某处出现了拥塞,因而源节点必须抑制发送过程,这实际上是拥塞发生后的事后控制。

源抑制报文的格式如下图所示。类型值为4,代码为0。数据区为引起源抑制的IP数据报部分信息。

image

源抑制包括以下3个阶段。

  • 发现拥塞阶段。路由器对缓冲区进行监测,一旦发现拥塞,立即向相应的源节点发送ICMP源抑制报文。通常在缓冲区满时丢弃当前的数据报,每丢弃一个数据报,都要向该数据报的源节点(发送方)发送一个源抑制报文。源节点收到源抑制报文后,获知拥塞已经发生,而且所发送的数据报已被丢弃。
  • 解决拥塞阶段。源节点根据收到的源抑制报文中的原数据报的首部信息决定对发往某特定目标节点的数据流进行抑制,通常按一定规则降低发往该目标节点的数据报传输速率。
  • 恢复阶段。拥塞解除后,源节点逐渐恢复数据报传输速率。在规定的时间段内未收到关于某目标节点的源抑制报文,源节点就认为发往该目标节点的拥塞已经解除。

由于各个源节点的发送速率相差较大,源抑制的效果未必很好,另外源抑制报文本身会消耗网络带宽。默认情况下,大多数路由器不会发送源抑制报文。

重定向报文

路由器和主机都必须有路由表,以便决定路由器的地址或下一跳路由器的地址。路由器上的路由表能够动态更新,及时反映网络结构的变化,这是由路由器之间定期交换路由信息来实现的。但是,主机数量非常大,动态更新主机的路由表会产生不可接受的通信开销,而且主机还不一定全天在线,即使要动态更新路由表也不现实,因此主机通常使用静态路由选择,而不是通过路由协议进行动态更新。主机所在的网络可能与多个路由器相连,主机在发送信息时也要根据其路由表来选择下一跳路由器,为解决主机路由表的更新问题,ICMP 提供了重定向(Redirect)机制

主机并不总是在线,主机路由表所给出的下一跳路由器可能并不是去往目的地最佳的下一跳路由器,当主机的下一跳路由器收到数据报后,根据其路由表判断本路由器是否是去往目的地最佳选择,如果不是,该路由器仍然会向目的节点所在网络转发该数据报,但在转发的同时会产生一个ICMP重定向报文,通知源主机修改它的路由表,而重定向报文中将给出源主机最佳下一跳路由器的IP地址。 ICMP重定向机制如下图所示。

image

主机A要向主机B发送数据报,路由器2显然是最有效的路由选择,但是主机A没有选择路由器2。数据报被发送到路由器l而不是路由器2,在查找路由表后发现数据报应当通过路由器2。它将数据报发送到路由器,并同时向主机A发送重定向报文。这样主机A的路由表被更新了。重定向报文又称改变路由报文。

ICMP重定向报文的格式如下图所示。类型值为5。代码为0~3,代表不同的重定向方式,具体含义见表5-4。数据区为引起重定向的IP数据报部分信息。

image

重定向报文代码及其含义:

代码说明
0为网络(或子网)重定向数据报,指名了存在一条抵达指定网络的更好路径。由于路由器不能确定目的地址的哪一部分是网络地址部分、哪一部分是主机地址部分,因此他们在ICMP重定向应答种使用代码1
1为主机重定向数据报,知名存在一条抵达指定主机的更好路径。这是网络上最常见的ICMP重定向报文
2为TOS(服务类型)和网络重定向数据报,知名存在一条使用所需TOS抵达指定网络的更好路径。由于路由器不能确定目的地址的哪一部分是网络部分、哪一部分是主机部分,因此它们在ICMP重定向应答中使用代码3来解决TOS问题
3为服务类型和主机重定向数据报,指明存在一条使用所需TOS抵达指定主机的更好路径

当主机开始连网工作时,其路由表中的项目数很有限,通常只知道默认路由器这一个路由器的IP地址。在ICMP重定向机制的作用下,经过不断积累逐渐充实和完善其路由表。ICMP重定向机制使得主机的路由表成为一个动态且优化的路由表。

ICMP 重定向报文是由路由器向同一个本地网络上的主机发送的。虽然重定向报文算是一种差错报告报文,但它与其他种差错报文不同。路由器产生ICMP重定向报文的时候并不丢弃原数据报,数据报被送到适当的路由器。被刷新的路由表项与重定向报文数据部分指示的IP数据报首部中的目的地址相关。

查询报文

ICMP 协议也用于查询,帮助主机或管理员从一个路由器或主机得到特定的信息,这些报文是以请求与应答方式成对出现的,一方主动向另一方发出查询请求,而另一方将查询结果报告给请求方。

与差错报告以一对一的方式向源主机发送信息不同,ICMP 的请求和应答报文对可以在任何两个网络节点之间传输,可以以一对多的方式进行传输,如广播或多播。TCP/IP网络中的任何主机或路由器都可以向其他主机或路由器发送请求并获得应答,便于管理员、应用程序对网络进行检测,诊断和控制。

除差错报告外,ICMP 还能对某些网络问题进行诊断,这是通过使用由请求与应答报文对形成的查询报文来完成的。在ICMP查询报文中,一个节点发送请求报文,然后由目的节点用特定的格式进行应答。利用获得的应答信息,可以对网络进行故障诊断和控制。RFC 792定义的信息请求或信息查询(Information Request or Information Reply)报文用于主机引导时获取 IP 地址,现在这种ICMP报文已经不用了,其功能已由RARP和BOOTP/DHCP来完成。这里介绍4对常用的查询报文。

除差错报告外,ICMP 还能对某些网络问题进行诊断,这是通过使用由请求与应答报文对形成的查询报文来完成的。在ICMP查询报文中,一个节点发送请求报文,然后由目的节点用特定的格式进行应答。利用获得的应答信息,可以对网络进行故障诊断和控制。RFC 792定义的信息请求或信息查询(Information Request or Information Reply)报文用于主机引导时获取 IP 地址,现在这种ICMP报文已经不用了,其功能已由RARP和BOOTP/DHCP来完成。这里介绍四种常用的查询报文。

回送与回送应答报文

回送(Echo)与回送应答(Echo Reply)报文的目的是对网络进行诊断和测试。在RFC 792中使用“Echo”这个术语,相对于“Echo Reply”来说实际上是一种请求,因而又称为回送请求(Echo Request)。发送方(主机或路由器)向接收方(另一台主机或路由器)发送一个回送报文,其数据区包含发送方给定的数据,接收方收到该请求后形成回送应答报文返回给发送方,其数据区包含回送报文中所带的数据。发送方根据应答报文中的数据可以确定双方是否可以正常通信。

回送和回送应答报文可用来确定是否在IP层能够正常通信,不仅可以用来测试主机或路由器的可达性,还可以测试IP协议的工作情况。发送方如果能够成功地收到接收方对回应请求的应答,不但说明目标可达,而且说明双方的ICMP软件和IP软件工作正常,另外还说明回应请求与应答所经过的中间路由器能够正常接收、处理和转发数据报。

ICMP回送与回送应答报文使用相同的格式,如下图所示。

image

类型8表明是回送(请求)报文,类型0表明是回送应答报文,代码都是0。**标识符(Identifer)序列号(Sequence)**字段用于匹配回送应答报文与回送报文。这两个字段值在协议中没有正式定义,标识符一般为发起请求进程的进程ID,序列号在发送每一个回送(请求)报文时被增加。可供选择的数据字段包含一个消息,这个报文必须由接收方在回送应答报文中完全一样地重复着。

TCP/IP网络系统所提供的ping命令大多是利用ICMP回送与回送应答报文来实现的,该命令通常用于测试目的主机或路由器的可到达性。这里使用Wireshark抓取Windows计算机上一个ping命令执行过程中的一系列数据包。相关的数据包列表如图5-11所示,数据包按请求(Echo request)和应答(Echo reply)成对产生。标识符(Identifier)均为0x0200(512),序列号(Sequence number)初始值为256,每发送一个回送(请求)报文时再增加256。

展开一个回送请求报文(以序号为1的数据包为例)进行分析,结果如下图所示。

image

这里列出各字段详细数据,其中标识符和序列号都使用十进制和十六进制两种类型表示,而且还提供两种不同的字节存储顺序,BE全称Big-endian,译为大端序,即数据的高位字节存放在地址的低端,低位字节存放在地址高端;LE全称Little-endian,译为小端序,即数据的高位字节存放在地址的高端,低位字节存放在地址低端。

时间戳与时间戳应答报文

时间戳(Timestamp)时间戳应答(Timestamp Reply)报文用于两个网络节点(主机或路由器)之间的时钟同步。发送方通过获取接收方的时间戳信息,将该信息和发送方的时间戳信息进行比较后,再估算两者的时钟差异。

ICMP时间戳与时间戳应答报文使用相同的格式,如下图所示。

image

类型13表明是时间戳(请求)报文,类型14表明是时间戳应答报文,代码都是0。**标识符(Identifer)序列号(Sequence)**字段用于匹配时间戳应答报文与时间戳报文。

3个时间戳字段都是32位长,以毫秒为单位从 世界时间(UT) 午夜0点起计时。虽然32位最大可以计数到4294967295,但时间戳的计数值不能超过86400000,即24小时。

源节点产生时间戳(请求)报文,在请求报文离开时在发起时间戳字段填入当前时间,其他两个时间戳字段则都填入0。

目标节点产生时间戳应答报文,将时间戳(请求)报文中的发起时间戳值复制到应答报文同样的字段中,然后在接收时间戳字段中填入在收到这个请求报文时的时间,最后应答报文离开时在发送时间戳字段中填入当前时间。

为了估算节点之间的时钟差异,首先要计算出时间戳和时间戳应答的往返延迟,然后据此计算出单程传输延迟,最后由两个节点的时间戳和单程传输延迟来计算出它们之间的时间差,从而实现时钟的同步。具体公式如下。

往返时间=当前时间-发起时间戳-(发送时间戳-接收时间戳)
单程时延=往返时间÷2
时间差=接收时间戳-(发起时间戳+单程时延)

值得一提的是,后来的 网络时间协议(NTP) 提供更健壮、用途更广泛的时间同步方法。

地址掩码请求与应答报文

地址掩码请求(Address Mask Request)地址掩码应答(Address Mask Reply)报文用于获得主机或路由器的子网掩码,具体由RFC 950“Internet Standard Subnetting Procedure(Internet标准子网划分程序)”规定。

主机向网络中的路由器发送地址掩码请求报文以期获得它的子网掩码。如果主机知道该路由器的地址,就把请求报文直接发送给该路由器;如果主机不知道,则广播这个报文。路由器收到地址掩码请求报文,就以地址掩码应答报文进行响应,向主机提供所需的掩码,将这个掩码应用到完整的IP地址上就可得到子网地址。

地址掩码请求与应答报文的格式如下图所示。

image

类型17表示地址掩码请求,类型18表示地址掩码应答,代码为 0。标识符和序列号字段用于匹配地址掩码应答报文与请求报文。在请求报文中,地址掩码字段填入全 0。当路由器把地址掩码应答报文发回给主机时,应答报文中的该字段就包含真正的子网掩码(32位)。

路由器请求与路由器通告报文

初始化路由表的一种方法是直接在配置文件中指定静态路由,另一种方法是利用ICMP路由器请求(Router Solicitation)和路由器通告(Router Advertisement)报文来获得路由器的IP地址。主机在启动以后通过广播或多播发出路由器请求报文,一台或多台路由器以路由器通告报文作为响应。通过路由器请求和通告报文还可以知道路由器是否处于活动状态。这个报文对具体由RFC 1256“ICMP Router Discovery Messages(ICMP路由发现报文)”规定。在介绍这个报文对之前先了解一下路由器发现与路由器通告的机制。

1.路由器发现与路由器通告

典型情况下,IP主机通过默认网关参数的手工配置和重定向报文来获得路由信息。没有设置默认网关的主机启动时,默认会将一个 ICMP 路由器请求报文发送到所有路由器的 IP 广播地址224.0.0.2上,目的在于定位本地路由器,这就是所谓的ICMP路由器发现(ICMP Router Discovery)。收到请求报文的路由器将使用ICMP路由器应答报文回应给源主机。如果路由器不支持ICMP路由器发现协议的路由器部分,主机的ICMP路由器请求将得不到应答。位于部署多个IP路由器的网络上的IP主机可能会收到多个应答,每一个本地连接的路由器上都会给出一个应答。典型情况下,主机作为默认网关接收和使用第一个应答。当然已经配置了默认网关的主机不需要执行ICMP路由器发现。

在 Windows 系统中有两个注册表设置能够用于控制路由器发现。

第1个是HKEY LOCAL MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<网卡名称>\Perform-RouterDiscovery表项,设置是否允许ICMP路由发现,默认值1表示允许,修改为0将关闭路由发现。

第2个是HKEY LOCAL MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<网卡名称>\PerformRouterDiscovery\SolicitationAddressBCast表项,设置发送路由器请求是使用子网广播地址,还是使用所有路由器的多播地址,默认值0表示多播,修改为1将使用子网广播。这两个注册表项项值类型为DWORD,不过Windows默认没有提供这两个注册表项。

某些路由器能够被配置为周期性地发送ICMP路由器通告报文,以允许主机被动地获悉可用路由。可以对路由器进行配置,让其周期性地向所有主机多播地址224.0.0.1发送未经请求的ICMP路由器通告。这些通告一般包括发送该通告的路由器的IP地址,还有一个生存期限字段,指示接收主机应该保持该路由项多长时间。默认生存期限为30分钟,过期路由项将从路由表中删除,主机可以发送一个新的路由器请求报文,或者等待并被动地侦听ICMP路由器通告报文。

2.ICMP路由器请求报文

image

如上图所示,路由器请求报文格式最为简单,类型值为10,代码为0,不需要提供类型和代码之外的信息。此类报文默认情况下发送到全路由器多播地址224.0.0.2。在某些情况下,主机可以被配置为将这些报文发送到广播地址上(在本地路由器不能处理多播数据包的情况下)。还有一个32位的字段暂时保留(Reserved),该值设置为0,对方接收时将忽略。

3.ICMP路由器通告报文

收到路由器请求报文的一台或多台路由器就使用路由器通告报文广播其路径选择信息。即使没有路由器请求报文,路由器也可以定期广播或多播路由器通告报文。路由器发送出通告报文时,它不仅通告自己的存在,而且通告它所知道的所有在该网络上的路由器。

路由器通告报文如下图所示。

image

类型值为9,代码为0。路由器通告报文的数据区可以包含多个地址信息。首部中的地址数目(Num Addrs)字段指明该报文所含的路由器地址的个数。一个地址项由一个4字节的IP地址和一个4字节的优先级(Precedence)字段组成,地址长度(Addr Entry Size)字段指明每个路由器地址项所占32位字(4字节)的数目,一般为2,表示2个4字节。生存时间(Lifetime)字段以秒为单位,指明所通告路由器地址的有效时间。

ICMP应用

ICMP 最常见的用法是对网络进行测试和故障诊断。两个最著名的实用程序——Ping 和Traceroute就是依靠ICMP完成连通性测试和路由跟踪。另一方面,攻击者也能将ICMP用于网络侦察活动以获取网络地址和活动进程,ICMP安全问题不容忽视。

使用Ping测试网络连通性

许多用户都有过Ping命令的经历,但可能并不清楚它实际上是ICMP回送(Echo)请求与应答的一种形式。Ping的执行过程简单,首先客户端将请求包发送给目的网络,一旦接收之后,目的主机返回应答数据。

ICMP 回送请求报文包括以太网首部、IP 首部、ICMP 首部,以及一些不确定的数据。该报文的发送是一个真正的尽最大努力交付的过程。绝大多数Ping程序向目的节点发送一系列的请求报文,以期获得平均响应时间。响应时间以毫秒为单位,不能作为节点之间典型往返时间,而是当前往返时间的一个快照。

Windows 系统所带的 Ping 程序默认连续发送 4 个带有回送应答超时值为 1 秒的 ICMP 回送请求包。回送应答包中包含了32字节数据,其中有响应节点(主机或路由器)的IP地址、应答报文的字节数、往返时间,以及TTL值。

Windows的Ping命令的语法格式如下。

ping [-t] [-a] [-n count] [-l size] [-f] [-i ttl] [-v tos] [-r count] [-s count] [[-j computer-list] | [-k computer-list]] [-w timeout] destination-list

各参数含义说明如下。

  • -t:测试指定的计算机直到人为中断为止。可以使用组合键<Ctrl>+<C>强制中断,也可使用<Ctrl>+<Break>暂停,查看信息,再按任一键继续。
  • -a:将IP地址解析为计算机名。
  • -n count:设置要发送ECHO数据包数,用count表示,默认值为4。
  • -l size:发送缓存区的大小,由size指定,默认为32 字节,最大值是65527 字节。
  • -f:在数据包中设置不分段标志,这样数据包就不会被路由上的网关分段。
  • -i ttl:设置生存时间,由ttl指定。
  • -v tos:设置服务类型,由tos指定。
  • -r count:设置要记录的路由器的数目,由count指定,可以指定最少1台,最多9台计算机。
  • -s count:设置时间戳的路由器数目,由count指定。
  • -j computer-list:由computer-list指定的计算机列表(不严格按照列表顺序)作为ping数据包的路由路径。
  • -k computer-list:由computer-list指定的计算机列表(严格按照列表顺序)作为ping数据包的路由路径。允许的最大数量为9。
  • -w timeout:指定超时间隔,单位为毫秒。默认为1000 毫秒,即1 秒。如果通过ping 探测的远程系统经过长时间延迟的链路,则响应可能会花更长的时间才能返回,可以使用-w选项指定更长时间的超时。
  • destination-list:指定要测试的目的计算机的域名或IP地址。 使用Ping命令测试网络连通性的具体步骤如下。

(1)Ping 环回地址,验证是否在本地计算机上安装 TCP/IP 协议以及配置是否正确。执行命令ping 127.0.0.1。如果不能成功,应安装和配置TCP/IP之后重新启动计算机。

(2)Ping本地计算机,验证是否将当前计算机正确地添加到网络。

(3)Ping默认网关,验证默认网关是否运行以及能否与同一网段上的主机通信。

(4)Ping远程主机,验证能否通过路由器进行通信。如果有问题,可检查路由器配置,确认启用IP路由和路由器之间的连接正常。

注意

一般不允许Ping广播地址,防止所有接收主机都会响应发送方,并极有可能淹没它。目的节点也不响应发送到多播或广播地址的ICMP回送请求,防止淹没主机。

使用Traceroute跟踪路由

Tracert 是路由跟踪实用程序,用于确定 IP 数据包访问目的主机所采取的路径。Tracert 命令用IP生存时间(TTL)字段和ICMP错误消息来确定从一个主机到网络上其他主机的路由。Tracert通过向目标发送不同IP生存时间(TTL)值的ICMP回送请求报文,来确定到目的地所采取的路由。Tracert要求路径上的每个路由器在转发数据包之前至少将数据包上的TTL递减1。当数据包上的TTL减为0时,路由器应该将ICMP已超时的报文发回源主机。其语法格式如下。

tracert [-d] [-h maximum_hops] [-j computer-list] [-w timeout] target_name

各选项、参数含义说明如下。

  • -d:指定不将IP地址解析为计算机名称。
  • -h maximum_hops:设置搜索目标的最大跃点数。
  • -j computer-list:指定tracert数据包所采用路径中的路由器接口列表。
  • -w timeout:设置每次应答的等待时间,由timeout表示,单位是微秒。
  • target_name:目的计算机的名称或IP地址。

使用Tracert跟踪网络连接,Tracert命令按顺序列出返回ICMP超时报文的路径中的近端路由器接口列表。如果使用-d选项,则Tracert实用程序不在每个IP地址上查询DNS,这将大大加快Tracert命令的运行速度,这对于解决大型网络的问题非常有用。

Tracert扩展了Ping的功能,通过向目的地址发送具有不同生存时间的ICMP回送请求报文,来确定到达目的地的路由。Tracert一般用来检测故障的位置或节点,确定网络路径究竟在哪个环节上出了问题。如下图所示,这是一个在Windows计算机上使用Tracert命令跟踪到某个站点的路由的例子。从查询结果可知数据包经历了10个路由器或网关才到达目的地。

image

ICMP安全问题

ICMP 既然可以作为管理员检测和诊断网络的工具,攻击者也就用它来搜集网络信息,为此一些企业会限制ICMP流量来确保安全。例如,攻击者可通过发送Ping数据包(ICMP 回送请求)到某个范围内的每一台主机并关注其应答信息,完成IP主机的探查。发现目标之后再进行端口扫描。下面列出常见的ICMP安全问题。

1.ICMP重定向攻击

ICMP 能够用于操纵主机之间的网络流量。攻击者将流量重定向到自己的计算机上,完成任意数量的中间人攻击。攻击者对目标计算机器执行多种形式的网络攻击,例如,连接劫持、拒绝服务,并能够通过嗅探潜在地获取登录凭据。

2.ICMP路由器发现

ICMP 路由器发现为攻击者提供了另一种中间人攻击方法,本地网段很容易受到攻击。在路由器发现过程中,通过发送路由器请求报文来确定到达攻击者计算机的路径。攻击者使用路由器应答欺骗目的主机,指明它自己的主机实际上是请求的中间路由器,而不是网段上的实际路由器。由于这个过程中不进行认证,接收方无法确定这个应答是伪造的。

3.反向映射

ICMP 也让攻击者借助于反向映射来探测网络中的活动目标。当在攻击者与其潜在目标之间检测到过滤设备时,能够以非寻常方式查询路由设备,故意将数据包发送给空的网络地址。ICMP 是一个无状态协议,一旦接收到目的地为不存在主机的数据包,中间路由器将会放行该数据包通行(它并不知道更多的信息)。然而,一旦该数据包抵达内部路由器,该路由器对有效和可用网络地址知道更多,它将对每一个伪造请求立即以主机不可达报文作为应答。之后,攻击者可以从逻辑上推论出对应于活动主机的地址。 防止ICMP滥用对网络安全非常必要。