01
简介
在《IP协议详解》入门文章中,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成。其中一个重要的模块就是网际报文控制协议(InternetControl Message ProtocoL,ICMP )。
首先说明,ICMP只是保证数据被送达的一个重要模块,它并没有完全解决IP协议的不可靠性。ICMP解决的问题有:
1、IP协议本身不提供差错报告和差错控制机制来保证数据报递交的有效性,在路由器无法递交一个数据报,或者数据报生存时间为0时,路由器都会直接丢弃掉这个数据报。尽管路由器IP层认为这样的处理是合理的(可以提高数据报处理效率),但是在很多情况下,源主机还是期望在数据报递交出现异常的情况下得到相关的失败信息,以便进行重传或者其他处理。
2、IP协议缺少一个辅助机制,即主机的管理和查询机制。在某些情况下,源主机需要确定另一个主机或者路由器是否是活跃的,对于不活跃的主机,就没有必要再向它发送数据报了,因为这是徒劳的。在另外一些情况下,一个主机的管理员期望能获得另一个主机或老路由器上的信息,以根据这些信息进行主机自身的配置、数据报发送控制等。
从TCP/IP的分层结构上来看,它同IP协议一样处于网络层,但ICMP协议有自己的一套报文格式,且它需要使用IP协议来递交报文,即ICMP报文是放在P数据报中的数据区域发送的,从这点看来,ICMP协议又有点像一个传输层协议,因为ICMP报文的目的不是目的主机上的某个应用程序,它不为应用程序提供传输服务,ICMP报文的目的是目的主机上的网络层处理软件。
在这一点,我找到的不同资料的不同的说法,这个不是本文讨论的重点,本文对于ICMP协议数据哪一层不持观点。
02
协议结构
ICMP数据包由8bit的错误类型和8bit的代码和16bit的校验和组成,校验算法和IP首部检验和算法相同。而前16bit就组成了ICMP所要传递的信息。
从功能上划分,ICMP报文可以分为两大类:ICMP差错报告报文和ICMP查询报文,分别用于解决上面说到的两个问题。
差错报告报文主要用来向IP数据报源主机返回一个差错报告信息,这个错误报告信息产生的原因是路由器或主机不能对当前数据报进行正常的处理,例如无法将数据报递交给有效的协议上层,数据报因为生存时间TTL为0而被删除等。
查询报文用于一台主机向另一台主机查询特定的信息,通常查询报文都是成对出现的,即源主机发起一个查询报文,在目的主机收到该报文后,会按照查询报文约定的格式为源主机返回一个应答报文。
尽管在大多数情况下,错误的包传送应该给出ICMP报文,但是在特殊情况下,是不产生ICMP错误报文的。如下
- ICMP差错报文不会产生ICMP差错报文(IMCP查询报文)(防止IMCP的无限产生和传送)
- 目的地址是广播地址或多播地址的IP数据报。
- 作为链路层广播的数据报。
- 不是IP分片的第一片。
- 源地址不是单个主机的数据报。这就是说,源地址不能为零地址、环回地址、广播地 址或多播地址。
虽然里面的一些规定现在还不是很明白,但是所有的这一切规定,都是为了防止产生ICMP报文的无限传播而定义的。
03
差错报文
由上图可见,差错报文有很多类型,此文重点讲解目的站不可到达报文和数据报超时报文。
3.1、目的站不可到达
当路由器不能给数据报找到合适的路由路径,或者主机不能将数据报递交给上层协议时,相应的IP数据报就会被丢弃,然后一个目的站不可达差错控制报文将会被返回给源主机。目的站不可达差错可以由很多因素引起,例如网络不可达、主机不可达、协议不可达、端口不可达等等,可以在报文首部中的代码字段指出具体原因。
代码字段记录了引起差错的原因,在ICMP目的不可达报文的数据区域,装载了引起目的站不可达的IP数据报首部及数据报数据区的前8个字节,当源主机收到这样一份ICMP报文后,它能根据报文数据区中的数据判断是哪个数据报出现了问题。为什么还需要装载引起差错的数据报数据区的前8个字节呢?因为这8个字节恰好覆盖了TCP报文或UDP报文中的端口号字段,IP层能够根据这个端口号把ICMP报文传递给具体的上层处理。
下图是目的站不可到达代码字段常见取值和意义。
这里有几个形象的说法,类比送快递
- 网络不可达:找不到小区呀?
- 主机不可达:找到小区,但是找不到门牌号?
- 协议不可达:找到小区,找到门牌号,但是名字没对上,人家叫王小二,快递名字是王小三啊!
- 端口不可达:找到小区,找到门牌号,名字也对,但是东西不对,打开快递,人家买的电视,这是冰箱啊!
3.2、数据报超时
数据报超时可以用来防止数据报在网络中被循环的路由,在P首部中都有一个生存时间计数器(TTL),数据报每被转发一次,TTL的值便会减1,当TTL的值被减为0时,数据报会被网络丢弃,同时一个ICMP超时报文会被返回给源主机。
数据报超时代码字段取值和意义
04
查询报文
常见的ICMP查询报文有以下几种:回送请求或回答、路由器询问和通告、时间戳请求或回答、信息请求或回答、地址掩码请求或回答。
其中查询报文有以下几种用途:
- ping查询
- 子网掩码查询
- 时间戳查询(可以用来同步时间)
其中子网掩码查询以前主要在主机启动时使用,主机能确定自身在网络环境中IP地址、地址掩码、路由器状况等信息,现在,DHCP协议已经能够完全实现这些功能,此文不再讲解。
4.1、ping
ping可以说是ICMP的最著名的应用,ping这个单词源自声纳定位,而这个程序的作用也确实如此,它利用ICMP协议包来侦测另一个主机是否可达。当我们不打开浏览器,想确认主机是否能访问某个网站时,通常会ping一下这个网站。ping会回显出一些有用的信息。一般的信息如下:
ping的原理是用类型码为8的ICMP发请求,受到请求的主机则用类型码为0的ICMP回应。ping程序来计算间隔时间,并计算有多少个包被送达。用户就可以判断网络大致的情况。我们可以看到,ping给出来了传送的时间和TTL的数据。上面我直接ping的baidu,因为走的路由少,没有丢包,延时也很低,有兴趣地可以ping一下国外的网站比如sf.NET,就可以观察到一些丢包的现象,而程序运行的时间也会更加的长。
wireshark抓包分析ping使用的ICMP协议
在这里分享一下wireshark的抓包文件,大家可以自行分析一下
链接:https://pan.baidu.com/s/1iscl00pd-fqJQT9ZVbafyg 提取码:fy6p
(提示:公众号不支持外链接,请复制链接到浏览器下载)
ping还给我们一个看主机到目的主机的路由的机会。这是因为,ICMP的ping请求数据报在每经过一个路由器的时候,路由器都会把自己的ip放到该数据报中。而目的主机则会把这个IP列表复制到回应ICMP数据包中发回给主机。但是,无论如何,IP头所能纪录的路由列表是非常的有限。如果要观察路由,我们还是需要使用更好的工具,就是要讲到的Traceroute(windows下面的名字叫做tracert)。
4.2、Traceroute
Traceroute是用来侦测主机到目的主机之间所经路由情况的重要工具,也是最便利的工具。由VanJacobson编写的Traceroute程序是一个能更深入探索TCP/IP协议的方便可用的工具。尽管不能保证从源端发往目的端的两份连续的IP数据报具有相同的路由,但是大多数情况下是这样的。Traceroute程序可以让我们看到IP数据报从一台主机传到另一台主机所经过的路由。Traceroute程序还可以让我们使用IP源路由选项。
前面说到,尽管ping工具也可以进行侦测,但是,因为IP头的限制,ping不能完全的记录下所经过的路由器。所以Traceroute正好就填补了这个缺憾。
Traceroute的原理是非常非常的有意思,它收到目的主机的IP后,首先给目的主机发送一个TTL=1的UDP(UDP后面文章讲解)数据包,而经过的第一个路由器收到这个数据包以后,就自动把TTL减1,而TTL变为0以后,路由器就把这个包给抛弃了,并同时产生一个主机不可达的ICMP数据报给主机。主机收到这个数据报以后再发一个TTL=2的UDP数据报给目的主机,然后刺激第二个路由器给主机发ICMP数据报。如此往复直到到达目的主机。这样,traceroute就拿到了所有的路由器ip。从而避开了ip头只能记录有限路由IP的问题。
我在办公室的网络
当我在IP为192.168.0.105的PC上执行
代码语言:javascript复制tracert 192.168.2.1
如下显示
wireshark抓包显示,IP为192.168.0.105的PC首先发送了TTL为1的ICMP数据包。
备注:
- 由于tracert命令执行时间较长,wireshark抓取了PC其他通信的数据包,需要使用icmp过滤一下。
- 我只抓取了PC的数据包,大家有条件可以抓取一下网关为192.168.0.1的WAN口的数据,可以使用另外一台PC配合带端口镜像的交换机抓取WAN口的数据。
在这里我分享一下wireshark的抓包文件,大家可以分析一下抓取的其他数据。
链接:https://pan.baidu.com/s/1iscl00pd-fqJQT9ZVbafyg 提取码:fy6p
(提示:公众号不支持外链接,请复制链接到浏览器下载)
我上面的测试,只有两级路由,我们可以直接测试百度。
大家可以测试一下最后的IP,这个IP就是百度服务器的IP。这个IP应该是不同的主机,不同的地域不一样的,大家可以试一下。
红框中的星号是因为有的路由器压根不会回这个ICMP。这也是使用Traceroute测试一个公网的地址,看不到中间路由的原因。
有人要问,我怎么知道UDP到没到达目的主机呢?这就涉及一个技巧的问题,TCP和UDP协议有一个端口号定义,而普通的网络程序只监控少数的几个号码较小的端口,比如说80,比如说23,等等。而traceroute发送的是端口号>30000(真变态)的UDP报,所以到达目的主机的时候,目的主机只能发送一个端口不可达的ICMP数据报给主机。主机接到这个报告以后就知道,主机到了,所以说Traceroute是一个骗子一点也不为过。
05
ICMP洪水
在《IP协议详解》中,我们讲解了IP攻击,在《ARP协议》中,我们讲解了ARP攻击,下面我们讲一下ICMP洪水。
足够快的数据包速度 足够的带宽,这才是洪水。洪水,顾名思义,是速度极快的,当一个程序发送数据包的速度达到了每秒1000个以上,它的性质就成了洪水产生器,洪水数据是从洪水产生器里出来的,但这样还不够,没有足够的带宽,再猛的洪水也只能像公路塞车那样慢慢移动,成了鸡肋。要做真正的洪水,就需要有一条足够宽的高速公路才可以ICMP请求需要一些服务器资源来处理每个请求并发送响应。请求还要求传入消息(回应请求)和传出响应(回应– 回复)两者都有带宽。
别以为ICMP洪水无所不能,实际上,你展开洪水攻击时,攻击程序在消耗对方带宽和资源时,也在消耗你的带宽和资源。这只是个看谁撑得住的攻击而已。
防范ICMP洪水的方法:
- 在路由器上对ICMP数据包进行带宽限制,将ICMP占用的带宽控制在一定的范围内,这样即使有ICMP攻击,它所占用的带宽也是非常有限的,对整个网络的影响将会非常少;
- 在主机上设置ICMP数据包处理规则,如果允许,可以拒绝向所有的ICMP数据包服务。
END