作者:一天  首发公众号:网络之路博客(ID:NetworkBlog

前言

学习了IP协议后,都知道IP协议本身是不提供可靠性保障的,那么数据包在这么复杂的互联网环境中传输,总会遇到问题,如果遇到问题后,被丢弃、无回应,可能作为工程师的我们来说都不知道发生了什么事,更别提普通用户了,所以数据包发送出去如果被丢弃、或者某些原因造成的不可达,需要一种协议来进行通知原因,这个协议就是这篇要讲解的ICMP。

ICMP有啥功能

ICMP全称叫做Internet Control Message Protocol (互联网控制报文协议),主要功能用于确认IP包是否成功抵达目的地、如果中途出现意外,进行报告通知发送者,好让维护人员根据原因得到解决办法。比如IP数据包由于某种原因未能抵达目的地,由于什么原因导致的由ICMP负责通知,这也我们在实际中排错跟测试最常用到的一个协议。

​(1)ICMP包格式


网络世界中的侦察兵----ICMP_百度


1、类型:表示ICMP报文的种类,ICMP的类型有很多

2、代码:在同一个类型中可能有多个组合,用代码来详细区分

3、校验和:校验ICMP的包是否有错误

4、根据类型和代码组合最终的数据内容。

ICMP类型字段,主要分为两大类

  • 一类用于诊断的查询报文【查询报文类型】,上一篇我们用的Ping工具就是属于查询类型
  • 一类是通知出错的原因【差错报文类型】,这个排错中非常有用

由于类型比较多,这里了解几个实际中经常用到的ICMP类型。

网络世界中的侦察兵----ICMP_端口号_02


查询报文类型

回送消息主要用于通信的主机或者网络设备之间,用于判断所发送的数据包是否成功抵达对方的一种消息,我们上一篇用到Ping命令就是使用的这个消息来实现,这里来详细了解下Ping的原理。


网络世界中的侦察兵----ICMP_端口号_03


用模拟器搭建一个这样的环境(已经用过几次了,这个基本的连线,拖设备应该都会了哈),然后各个PC设置好地址,接入到交换机,全部启动。

网络世界中的侦察兵----ICMP_端口号_04

开启对应的抓包,来看看icmp的报文的内容


网络世界中的侦察兵----ICMP_百度_05


使用PC1去ping一下PC2。


网络世界中的侦察兵----ICMP_服务器_06


通过过滤只看ICMP的包,发现总共有10个,5个Request ,5个Replay,先来关键字段的内容。

网络世界中的侦察兵----ICMP_服务器_07

  • Type(类型):Request为8,replay为0,经常有面试问到,ICMP的 ECHO Request与ECHO Replay的Type是多少。
  • Code(代码):固定为0
  • Identifier(标识符):不同的操作系统标识不太一样,作用就是用于区分是哪个进程发送的,比如我同时开了2个窗口Ping不同的地址,那就需要进行区分,否则混乱了,导致结果不一样。(上面查看的是1与2的包,会发现,标识符是一样的,因为去的时候是这个标识符,回来的也是这个,发送方就知道这个是哪个进程发送出去的了,在把结果回显到对应的程序窗口里面)
  • Sequence(序号):序号默认从0或者1开始(不同操作系统不太一样),它的作用是每发送一次新的请求就加1,回应这个请求的序列为相同,这样可以用来确认数据包是否有丢失的情况,比如发送的请求了2个请求,序号为1跟2,但是回应只收到了2,那么对应的1就表示丢失了(这个丢弃会在对应的程序窗口中显示代码原因,原因有多种,这个在后续会慢慢遇到)
  • DATA(数据):默认发送32个字节,里面为ICMP实际的内容,一串数据,但是里面包含了一个重要的信息,往返的时间,这个就非常重要,为什么说Ping能够帮助我们测试网络是否稳定,就是因为这个往返时间,这个时间能够表示当前网络环境是否稳定,良好。(比如Ping网关往返时间1分钟,那显然就不正常了,说明这个网络存在问题)


网络世界中的侦察兵----ICMP_端口号_08

模拟器中PC存在一个小问题,发送的ping是独立的,等于一个包一个独立的标识符,所以抓包看到的有5个不同的标识符,但是在Windows系统里面,一个窗口进程Ping的话,都是相同的标识符的

网络世界中的侦察兵----ICMP_字段_09

大家有兴趣的话可以自己电脑用wireshark抓取网卡,然后Ping下看看,上图是博主ping百度,抓包得到的,可以看出来id都是为0x0001,序列号每一组(去跟回都是相同的,每发出一个+1),从窗口回显的内容中还可以得到几个有用的信息

  • 时间:看图显示的时间在31~33ms(毫秒),也就是从我的电脑发出,抵达百度服务器,在从百度服务器返回到我电脑总共花费的时间,这个数值越大,表示时间越长,网络质量不好。
  • TTL:这个在IP头部字段里面已经了解过了,不同的操作系统默认值不太一样,这里TTL为54,跟64接近,可以判断出百度的服务器的TTL为64(有可能为一台Linux服务器),从TTL也能表示出从我这到百度服务器中间经过了10个三层的网络设备,因为TTL在经过一个三层设备的时候会减1。
  • Ping程序使用的ICMP里面的Echo Request(类型8)和Echo Replay(类型为0)


博主经验分享:这个时间怎么去根据数值来判断当前网络的好坏呢?

  • 有线网络:通常有线网络在Ping网关的时候,时间值=正常在1~3ms的范围,在Ping互联网的时候(比如百度、163等服务器),时间值=正常在10~80ms的范围(偏远地区测试的结果相对会高些,这个属于正常范围,比如江苏地区的Ping taobao的服务器,可能值就在10多ms,但是新疆地区Ping taobao服务器,可能值就在60~80ms的范围了)
  • 无线网络:无线网络测试的话,由于干扰因素比较多,所以相对有线来说值不太一样,Ping内网的话,在干扰较少的情况下通常是1~10多ms范围,偶尔有一个大的值出现,这个属于正常,对于外网的话,通常是10~100ms,偶然一个大的值出现也属于正常。
  • 如果说一个网络中,使用有线网络去测试Ping内网的网关在几十、几百ms那说明这个网络存在问题,就需要去解决了,通常我们把这个时间也叫做延时。


差错报文类型:(介绍相对比较重要的)目标不可达消息(类型为3)、超时消息(类型为11),这些在排错篇会有详细的演示。


(1)目标不可达消息(Destiantion Unreachable Message)类型3

这个在排错中非常有用,所以这里详细介绍下几个常见的类型,在网络中,发送的数据包有可能中途设备由于策略或者路由等问题无法将IP发送给目的地址,这个时候中途处理的设备会给发送者主机返回一个目标不可达的ICMP消息,这个消息中包含了具体的原因,通过ICMP的不同代码字段来表示。所以,最终发送者主机也可以根据这些代码知道不可达的具体原因,然后呈现在程序对应的窗口中回显出来,提供给管理者人员。


网络世界中的侦察兵----ICMP_字段_10


网络不可达代码 0

这个不常用,因为这个代码是在IP分为A、B、C类的时候,路由器通过类别来区分网络号,如果路由表中没有,就以ICMP协议,通告网络不可达(NetworkUnreachable)告诉主机,后面打破了网络分类后,这个代码就很少见了。


主机不可达代码 1

当一个数据包经过三层设备时,通过查询路由表中发现没有该主机的信息(或者主机没有连接到网络),那么会通过ICMP协议,通告主机不可达(HostUnreachable)告诉主机原因。


协议不可达 代码 2

某个终端使用TCP协议访问对端主机时,数据包已经抵达目的端了,但是由于目的主机的防火墙禁止了该TCP协议的访问,则目标主机会以ICMP协议,通告协议不可达的原因告诉发送者。


端口不可达代码 3

某个终端访问对端主机的9999端口号访问时,数据包已经抵达目的端了,防火墙也没有限制,但是可能对端主机没有开启对应端口号的服务,所以进程没有去监听这个9999端口号,那么该主机会通过ICMP协议,通告端口不可达来告诉发送者原因。


需要分片,但设置了不分片位代码4

某个终端发送了一个IP数据包,将IP位的分片DF位变成1,如果数据包超过了中途设备能够传输的大小时,由于标志位置一,不能处理则直接丢弃,并且通过ICMP协议通告一个不可达消息类型,代码为4,告诉发送终端。


上面这些就是在实际中经常会遇到的一些报错,可以通过这些代码进行区分,可能目前看着有点不太明白,这个没事,在后续的内容中会多次遇到,当遇到后,我会在提及,这样印象会更加深刻。

(2)超时消息(ICMP Time exceeded Message)--类型11

在学习IP协议字段的时候,其中一个字段叫做TTL(Time to Live,生存周期),它的值经过一个三层设备就会减1,直到变成0后被丢弃,丢弃的设备会发送一个ICMP超时消息来通知主机,告知该包已经被丢弃。


网络世界中的侦察兵----ICMP_标识符_11


这个实验有电脑的都可以操作,在CMD里面,ping www.baidu.com -i 1,这个的意思是访问百度TTL设置成1,中间就被丢弃了,因为TTL经过一个三层设备会减去1,这里为1,过了一台就变成0了,可以看到这个值是192.168.255.254返回告诉TTL 传输中过期,这个就是ICMP的超时消息,只是电脑的进程收到以后,把结果回显在了窗口里面。


(3)traceroute

在ICMP中除了Ping程序以外,还有一个程序使用率非常频繁,就是traceroute(Linux中是这个命令,在wind中叫做tracert,不同网络设备厂家上面也有点差异),那这个有什么作用呢?


探测经过了哪些设备,记录下地址。


网络世界中的侦察兵----ICMP_标识符_12


比如博主这台电脑,通过本地抵达百度服务器中间经过的所有设备的IP,这个在实际用处很大,比如A去往B不通,通过tracerroute看是不是走的对应的路径,有可能由于中间设备配置错误,导致它走了其他的线路出去了,这样就判断出来问题了。


它的原理就是利用IP包的生存期限,如上面主机tracertwww.baidu.com的时候主机会发送一个UDP的报文,目标端口号为高端口号(3000以上),并且把IP头部的TTL值改成1,遇到第一个网络设备的时候,变为0了,就会被丢弃,第一个网络设备会返回一个ICMP差错报文,类型是时间超时,比如图上的192.168.255.254就是出口的路由器,这样发送主机就得到了第一台设备的IP地址(入口的)


接下来主机继续发送TTL=2的数据包,这样在经过第二个三层设备的时候就会被丢弃,同时也会返回ICMP的差错报文,主机就知道了第二个路由器的地址,如图上的192.168.1.1,如此的重复,直到到达目的主机。


在图上会发现有请求超时的,这就是中途设备为了安全性关闭了ICMP报文的差错返回信息,这样就得不到信息了。


那么UDP的报文是干嘛用的呢,TTL值已经能够获取到中间设备的地址信息了,这个数据包最终是会抵达目的主机的,当目标主机收到这个UDP的包时,由于自己没有对应的服务,会返回一个端口不可达的ICMP差错报文信息,所以当发送者收到一个端口不可达这样的差错报文时,就知道这个数据包已经抵达目的主机了,否则发送方无法判断是否抵达了目的主机,会一直发送这个包,这样就失去了该功能的作用了。


在Windows主机中实用的命令

可能有的朋友还不知道在Windows中如何使用Ping命令与tracert命令,其实很简单


Ping命令

在CMD里面直接输入ping,其实会显示很多参数


网络世界中的侦察兵----ICMP_服务器_13


除了经常使用ping ccieh3c.com来测试目标主机是不是可通的,另外一个就是ping ccieh3c.com -t,-t的意思是持续Ping,通常在测试网络稳定性的时候会用到。


Tracert命令

网络世界中的侦察兵----ICMP_端口号_14


建议使用trcert -d ccieh3c.com, -d的作用是不解析地址的主机名,否则你会发现解析起来非常的慢。


作者:一天,公众号:网络之路博客(ID:NetworkBlog)。让你的网络之路不在孤单,一起学习,一起成长。