IC
协议篇--- 第三篇:杂谈ICMP。
------本文档献于要离职的公司,在这400多个日子,虽然经历了很多事情,但是我也获得了很 多,感谢你。是该说再见的时候。祝你依然欣欣向荣,再见!
icmp协议是日常中经常见到与使用的,遇到网络不通来ping下,测试网络连通性。ping就是一个小工具,系统自带,运行于内核,调用icmp协议来实现的。通过echo来发送请求,通过是否收到echo-reply来查询网络层的连通性。当然icmp主要不止是用来传递查询报文,主要还是用来回复差错报文的,告诉源设备(或者源设备上的应用程序)什么问题导致的问题。
ICMP---Internet Control Message Protocol。即互联网控制信息协议。基于网络层的一种协议,用来传递查询报文与差错报文的一种协议,根据RFC792的定义:
“The Internet Protocol (IP) is used for host-to-host datagram service in a system of interconnected networks called the Catenet. The network connecting devices are called Gateways. These gateways communicate between themselves for control purposes via a Gateway to Gateway Protocol (GGP). Occasionally a gateway or destination host will communicate with a source host, for example, to report an error in datagram processing. For such purposes this protocol, the Internet Control Message Protocol (ICMP), is used. ICMP, uses the basic support of IP as if it were a higher level protocol, however, ICMP is actually an integral part of IP, and must be implemented by every IP module.”
先 先看看ICMP协议的剧本格式:
Type |
Code |
Checksum |
|
Data |
所有icmp的报文,前面4个字节都是固定的,而后面的内容由具体的type与code来决定。
type与code都为8个bit,而checksum为16个bit,包含icmp头部与数据部分。
ICMP的报文类型与代码的含义:(这张图片是搜索得来,如果有侵权行为,请及时通知我。)
上面的有些类型已经不在用或者不被操作系统支持了,但是大部分类型操作系统还是支持的,我这里会举些例子。包括:目的不可达,重定向,ttl超时。过滤并强行禁止等等。
操作系统选择为:
1、cisco router(类似于freebsd系统)
2、linux(部分是centos,部分是ubuntu)
3、windows(xp,本来想加入win7的,可惜win7上没有装抓包软件)
在这里需要有个概念:既然ICMP是用来传递差错报文与查询报文,
1、那首先需要是有源设备主动发送报文
2、有设备回复差错报文或者查询报文
如果没有设备回复差错报文或者查询报文会怎么办,其实就是没有收到icmp报文。windows或者路由器会以"....."打印在屏幕上,而linux会一直停在那种状态。
在lan内,ping不通,很多人认为没有办法找原因,其实不然:
1、lan之内,有直连的路由,不可能出现网络不可达的问题
2、如果是主机:有可能是没有封装成包发出去,也有可能是过滤(软件防火墙之类的)
3、如果是网络设备,有可能是过滤了(ACL之类的)
首先上top:
我用gns3桥接宿主机与虚拟机,所以的设备都可以到达宿主机所处的网络,即:192.168.0.0/16这个网段中。
虚拟机:ubuntu
宿主机:xp
路由器:R1,R2
主机过滤:
首先让这些访问一个开着防火墙的操作系统
windows
可以从arp表中发现,包是可以封装的,也实际发出了,但是没有回应,主机没有回复icmp 差错报文的能力。
这里注意下每个包的发出时间。。。
linux
没有回复icmp的查询报文,只有发出89个packet。当然这里有R2将自己的mac做为destination主机的mac。
router
路由器以。。。。。为结束。注意timeout in seconds。
主机不存在:
刚才的是主机过滤,现在是主机不存在,看结果
w windows
linux
(这里就测试同一网段的)
router
看到结果了吧。
总结:
如果ping不通目的主机,有可能是目的主机过滤,也有可能是目的主机不存在。发出icmp的echo包没有收到回复与没有封装成包未能发出,windows与router都不会显示出具体那种的问题,只会以“request time out”或者“。。。。。”打印到屏幕。而linux如果没有封装成包发出,系统会自己提示“destination host Unreachable”,而没有收到回复,会一直发送报文,直到手动停止。所以,光凭回显内容是不能确认的,可以结合arp-cache来确认。如果发出了,可以得到对方的mac,如果连目的的mac都没有获得,就可以确定得知包是没有发出的。
上面提示注意每个包发出的时间,也就是每个包发出的间隔,也就是:
PING的超时时间
在我学习时,有人告诉我,ping超时是30s超时的,而超时时间是按2的次方的指数增长的。
即 0 2 4 8 16 加起来共30s,即系统在调用ping程序时,系统也在计时,因为系统不会为每个程序单独一个时间,而是以500ms为单位,如在400ms的时候,调用ping,会等待4个500ms(但实际并不是在500ms这个点发出的,如果还会加100ms的),如果没有收到回复的包,就认为这个包得不到回复,打印到屏幕:超时。而我抓了几个系统发出的包,却没有发现这样的指数增长,而是有一个固定的超时时间。
windows 默认为5s
linux 默认为1s
cisco router 默认为2s,这里我改成了4s(具体可以看上面的扩展ping)
至于为什么是有的默认发4个包,有的一直发,有的发5个包,这个我还真不了解,可能是系统默认是这样吧(我瞎猜的,让程序员去搞source code研究研究吧)
差错报文
icmp的差错报文始终包含产生差错报文的ip头部以及产生icmp差错报文的ip数据报的前8个字节(即ip头部后面的8个字节)。这样接受到该报文的模块可以把它与某个特定的协议(根据ip数据包的协议字段来判断)与用户进程(根据包含在ip数据报中tcp或者udp首部的port号来判断)联系到一起。
回复差错报文也有几个条件:
1、差错报文本身不能回复差错报文(查询报文可能会),如果可以,网络中都形成差错报文的风暴了。
2、目的地址为broadcast或者multicast不会产生差错报文。
3、链路层的广播(即FFFF.FFFF.FFFF)不会产生差错报文
4、非ip分片的第一片不会产生差错报文(分片只有ip头部与数据部分了,谁出错都不知道给谁)
5、源主机不是单个主机的数据报。也就是说source不能是零地址,回环地址,广播地址,组播地址。
由于过滤产生的差错报文
1、在R1的fa1/0口设置了in方向的ACL。(windows)
R1向宿主机发送的icmp差错报文。
具体是type=3,code=13的,由于过滤,导致的目的不可达。将source报文的ip首部及产生差错的ip数据报的前8个字节(这里是icmp的头部:标识符与序列号)
2、在R1的fa0/0口设置了in方向的ACL。(router)
router的收到差错报文只有3个(u。u。u),其中2个。,是因为超时没有收到报文。也可以验证下router的icmp超时时间。看58与59这两个报文间隔时间(3s,与我上面设置的时间一样)
看到没有,将上面那个报文的ip头部及导致出错的8个字节包含,让源知道,是那个协议或者应用程序发出的报文收到出错信息了。
3、在R1的fa2/0口设置了in方向的ACL。(linux)
看linux也是发出多少个报文,就收到多少差错报文。
总结:同样是由于过滤导致的目的不可达。路由器与主机(windows与linux)并不相同,主机是每发一个请求包就收到一个差错报文,而router是发送一个请求报文收一个差错报文,再发第二个请求报文,却没有收到任何报文直到超时,如此轮询。router是怎么区别这2者的呢,我看可能有根据seq来区分,router的seq起始是0,而主机是从1开始。
不可达的第2种情况:端口不可达。
这里是我的宿主机给open DNS发送的端口不可达。type=3,code=3的icmp差错报文。原因就是我主机并没有59400这个端口处于listening状态。另外端口不可达包含的东西很多,上面的报文居然把dns的请求都包含进来了。。。
不可达的第2种情况:目的主机被强行禁止。
其实这里就是端口没有处于listening状态,我个人感觉跟端口不可达没有什么区别。因为我这里是用windows访问linux的。也许会出现这样的情况。
这里提一句,tcp压根不理睬icmp的差错报文(除了源站抑制以外),因为tcp有自己方式---指针中reset字段置1来解决端口不存在问题。
回复的差错报文,包含了tcp的端口。tcp继续发,不理睬icmp报文。
不可达的第3种情况:需要分片但是df位被置1禁止分片
在“话说校验和(checksum)”一文中,我细说了分片的,主要是上层或者本层的数据报过大,超过了接口MTU的值,所以必须要分成多片来传输。分片是除第一片有4层头部或者协议的头部外,其他片只有ip头部与数据部分,分片是ip 头部中标识符与偏移位(以及3位标志位)共同起作用的。
设置接口mtu值为100.
这里插一句:串口可以直接改接口MTU值,因为它是P2P的,只有一个接收者,而MA环境只能改IP MTU值,因为一个接口改了,所有的接口都要更改,不然MTU不匹配,是接收不到报文的,所以MA就没有改接口MTU的值。
由网关回复的需要分片但设置不能分片的icmp差错报文。
这里还提示next hop的MTU值是100.
重定向
重定向是个很有意思的差错报文,在一个网段内,指的网关有误,网关发现有到达目的很有效的路径(出口),回复给source一个重定向报文,让其访问该目的直接走更有效的那个接口,当然,如果主机不理睬该报文,该网关还是为源设备转发报文,但是还是向源设备发送重定向报文。
重定向报文中共有3个ip地址,1、是谁给源设备发送的ip地址(现网关)。
2、到达目的的更有效的ip地址(新网关)。
3、目的设备的ip地址。
路由追踪
路由追踪---Traceroute,用来查询中途经过那些节点,也是利用icmp的差错报文;来实现的,这里要先提下ip 头部中的TTL(time to live生存时间)字段。这个字段本来的单位是时间(s),每经过1s,就减1,而对于现在高速的网络,经过一台路由器可能是按ms来算,所以TTL这个单位改为(HOP),每经过一台layer 3设备,TTL减1.每个系统的TTL时间并一致(windows为128,linux为64,freebsd为255等等)
Traceroute是通过发送UDP的报文,通过访问目的的一个高端口(这个端口如果处于监听状态就玩玩了),将ttl设置递增(起始为1),以接受ttl超时获得每一跳入口地址,到达目的后回复一个端口不可达的报文得知到达目的地。
这里不得不说,windows的tracert,microsoft是修改了Traceroute的代码,采用icmp的echo与echo-relay得知到达目的地,这点比用UDP的端口不可达优化了点,但是现实网络中禁止icmp协议大行其道,获得的中间节点的地址就少了写。
这里依然采用router,linux,windows来比较。
Windows:
tracert
TTL超时,一般是每次源设备发送3个包(这里做了修剪):
Linux:
linux与unix差不多,使用traceroute,也有发行版有tracert以及tracert6等等
linux发送的udp报文,高端口。以及回复的TTL超时差错报文
Router
router发出udp报文,这里我修改目的的端口从10000开始。一般TTL小于5的packet,抓包软件都会警告的。(ttl过小啊)
还会遇到这样icmp差错报文,Type=11,Code=1的ttl超时,这个是很少见的,因为ttl=1或者ttl=0时,是不会继续传输的,而是发送icmp差错报文(TTL超时)给源设备。因为ttl=1就不会传输的。所以ttl=0就没有遇见过。
这个包具体是校验错误,却以ttl超时的回复源设备。
具体的报文为:
回复的是ip 头部检验错误,这种应该直接丢弃,而不是回复TTL超时,有点不解。可以看到ip 头部中的TTL=126.这个包不止是ip头部校验错误,连icmp部分也校验错误。