1.概述
在我们的日常生活中,我们一般使用ping命令来判断与对方的网络是否通畅,其实大多数人都只是在用,没有深究其原理,下面我们抱着知其然,知其所以然的态度来学习学习。
2. ICMP协议
PING就是基于ICMP协议工作的,要明白PING,我们首先来熟悉一下ICMP协议
2.1 ICMP是什么?
ICMP全称就是互联网控制报文协议,这里有一个关键词—-控制。
网络包在复杂的网络传输环境里,经常会遇见各种问题,那么遇见问题了要怎么办呢?我们需要把消息传出去,报告到底出现了什么问题,这样才可以调整传输的策略,控制局面。
2.2 ICMP都有啥功能
ICMP的主要功能:确认IP包是否已经成功送达目标地址;报告发送过程中的IP包被废弃的原因以及改善网络设置等。
在IP通信的整个过程中,如果某一个IP包因为某种原因没有到达目的地址,那么具体的原因将会有ICMP负责通知。
如上图所示:主机A向主机B发送数据包的过程中,路由器2由于某些原因没能获取到主机B的MAC地址,这个时候路由器2就向主机A返回一个ICMP目标不可达的数据包,说明发给B的包没有成功。
2.2 ICMP包头格式
在上面的那个例子中,ICMP由路由器2发给路由器1,最后传给主机A,主机A拆解ICMP的首部和数据域后就能得知问题发生的原因了。
ICMP的报文是封装在IP包里面的,属于网络层。IP数据报文如下:
我们把它详细的拆解开来就是这样的:
我们从包头的类型字段开始说起,大致可以分为两大类;
查询报文类型:是用于诊断的查询消息。
差错报文类型:通知出错原因的错误消息
这两种类型分别包含不一样的内容:
下面我们来分析一下这两种类型:
(1)查询报文类型:
回送消息------内容0(回送应答)和8(回送请求)
回送消息用于通信的主机和路由器之间,它是判断所发送的消息是否已经成功送达对端的一种消息,ping命令就是利用回送消息实现的。
只要正常的返回了ICMP的回送响应,则代表了发送端主机到接收端主机可达。
ICMP的回送和请求报文相比于原生的ICMP,多了两个字段:
标识符:用以区分是哪个应用程序发的ICMP包,一般直接用进程号PID作为标识符;
序号:由0开始,每发送一次新的回送请求就会加1,可以用来确认网络包是否丢失。
在选项数据中,ping还会存放发送请求的时间值,计算往返时间。
(2)差错报文类型
差错报文有4个小类型:
目标不可达消息------类型3
原点抑制消息--------类型4
重定向消息-------类型5
超时消息--------类型11
1.目标不可达消息(3)
如果路由器没有办法将IP数据包发送给目标地址的时候,会给发送端主机返回一个目标不可达的ICMP消息。并说明具体不可达的原因,记录在代码字段。对于目标不可达类型的代码:
网络不可达的代码为 0
主机不可达的代码为 1
协议不可达的代码为 2
端口不可达的代码为 3
需要进行分片但是没有分片的代码为 4
什么是网络不可达?
IP地址分为网络号和主机号,当路由器中的路由表匹配不到接收方IP的网络号,就通过ICMP协议以网络不可达的原因告诉主机。
什么是主机不可达?
当路由表中没有该主机的信息,或者该主机没有连接到网络。就会通过ICMP以主机不可达的原因告知主机。
什么是协议不可达?
当主机使用TCP协议访问对端主机时,能找到对端主机了,可是对端主机的防火墙禁止TCP协议访问,就会通知主机协议不可达。
什么是端口不可达?
当主机访问对端的8080端口,这次可以找到对面主机了,防火墙也没限制,但是对端主机没有进程监听8080端口,就会返回端口不可达。
需要进行分片但未设置分片位就比较简单好理解了。即数据包的大小超过MTU,但是分片标志位又禁止分片。
2.原点抑制消息(4)
当路由器向低速线路发送数据的时候,其发送队列的缓存变为0而无法发送出去的时候。可以向IP包发送一个ICMP原点抑制消息,收到这个消息的主机借此了解整个线路在某一处发生拥堵的情况,增大IP包传输的间隔,减少拥堵。
3.重定向消息(5)
当路由器发现了发送端主机使用的不是最优路径发送数据,那么他就会返回一个ICMP重定向消息给这个主机。这个消息还包含了最合适的路由信息和源数据,告诉主机下次应该走最优的路线。
4.超时消息(11)
IP包中有一个字段叫做TTL(生存周期),它的值每经过一个路由器就会-1,直到为0时这个IP包就会被丢弃,此时路由器会发送一个ICMP超时消息给主机,通知他这个包已经被丢弃了。
那么生存周期的目的是什么呢?就是在路由控制遇到问题发生循环状况的时候,避免IP包无休止的在网络上被转发。我们也可以使用TTL控制包到达的范围。
3.PING –查询报文类型的使用
接下来,我们就重点看一下PING的发送和接收过程。
PING命令在执行的时候,源主机首先会构建一个ICMP 回送请求消息(8)的数据包。
ICMP数据报最重要的两个字段:
第一个是类型:对于回送请求消息而言该字段为8;
另外一个是序号,用于区分连续ping的时候发出的多个数据包。
每发出一个请求数据包,序号就会自动+1,为了能够计算往返时间RRT,报文的数据部分会插入发送时间。
组包完成之后,ICMP协议将这个数据包连同地址192.168.1.2一起交给IP层,IP层将以192.168.1.2作为目的地址,本机IP为源地址,协议字段设置为1(ICMP协议),再加上一些控制信息,就构成了一个IP包。
接下来就需要加入MAC头。在本地的ARP地址映射表中如果可以查找出IP地址192.168.1.2所对应的MAC地址,就可以直接使用。如果没有,就需要ARP广播查询MAC地址。获取到MAC地址之后,数据链路层就会构建一个数据帧。目的MAC是IP层传过来的,源地址则是本机MAC,再附加一些控制信息,根据以太网的介质访问规则,将他们传出去。
在规定的时间内,源主机如果没有接到ICMP的应答包,则说明目标主机不可达;如果接收到了ICMP的回送响应,则说明目标主机可达。
这个时候源主机就会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是ICMP数据包的时间延迟了。
最后张图总结一下PING的过程:这张图中的PING过程是在一个局域网里面的情况。如果跨网段的话,可能会涉及到网关的转发,路由器的转发等。这对于ICMP来说,不过是根据IP地址,选择路由的下一跳,还有就是每经过一个路由器达到一个新的局域网,需要更换MAC头里面的MAC地址。
我们使用wireshark抓取一个PING的网络包看一下:
可以看见上面两步是模组向本地DNS服务器查询目标主机的IP地址,然后本地DNS返回了IP地址
下面就是PING的交互流程。我们先看一下以太网头:
可以看见里面包含了源主机的目标主机的MAC地址。
再看一下IP头:
里面包含了协议类型 1 和源,目标IP地址以及一些控制信息。
再看一下ICMP请求报文:
可以看见type是8 ,这正是回送请求类型。
(大家有没有注意过这个LE,TE是什么呢?查阅了资料发现原来wireshark考虑到window系统与Linux系统发出的ping报文(主要指ping应用字段而非包含IP头的ping包)的字节顺序不一样(windows为LE:little-endian byte order,Linux为BE:big-endian)),也就是我们所说的大小端序。wireshark666!!!
总结一点:PING其实就是使用了ICMP中的回送应答和回送请求。(0和8).