ICMP详解

ICMP 全称是Internet Control Message Protocol,也就是互联网控制报文协议。

网络包在复杂的网络传输环境里,常常会遇到各种问题。当遇到问题的时候,总不能死的不明不白。所以需要传出消息,报告遇到了什么问题,这样才可以调整传输策略,以此来控制整个局面。

ICMP 主要的功能包括:确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被废弃的原因和改善网络设置等。

在 IP 通信中如果某个 IP 包因为某种原因未能达到目标地址,那么这个具体的原因将由 ICMP 负责通知。

ICMP 的这种通知消息会使用 IP 进行发送。

因此,从路由器 2 返回的 ICMP 包会按照往常的路由控制先经过路由器 1 再转发给主机 A。收到该 ICMP 包的主机 A 则分解 ICMP 的首部和数据域以后得知具体发生问题的原因。

ICMP 包头格式

ICMP 报文是封装在 IP 包里面,它⼯作在网络层,因而不保证可靠的提交。

ICMP 包头的类型字段,大致可以分为两大类:

  • 一类是用于诊断的查询消息,也就是「查询报文类型」
  • 另一类是通知出错原因的错误消息,也就是「差错报文类型」

常见的 ICMP 类型:

类型 内容 种类
0 回送应答 查询报文
3 目标不可达 差错报文
4 源端被关闭 差错报文
5 重定向或改变路由 差错报文
8 回送请求 查询报文
11 超时 差错报文

查询报文类型

回送消息用于进行通信的主机或路由器之间,判断所发送的数据包是否已经成功到达对端的一种消息,ping命令就是利用这个消息实现的。

可以向对端主机发送回送请求的消息(ICMP Echo Request Message,类型 8),也可以接收对端主机发回来的回送应答消息(ICMP Echo Reply Message,类型 0)。

相比原生的 ICMP,这里多了两个字段:

  • 标识符:用以区分是哪个应用程序发 ICMP 包,比如用进程 PID 作为标识符;
  • 序号:序列号从 0 开始,每发送一次新的回送请求就会加 1, 可以用来确认网络包是否有丢失。

在选项数据中,ping 还会存放发送请求的时间值,来计算往返时间,说明路程的长短。

差错报文类型

几个常用的 ICMP 差错报文的例子:

  • 目标不可达消息 —— 类型 为 3
  • 原点抑制消息 —— 类型 4
  • 重定向消息 —— 类型 5
  • 超时消息 —— 类型 11

目标不可达消息

IP 路由器无法将 IP 数据包发送给目标地址时,会给发送端主机返回一个目标不可达的 ICMP 消息,并在这个消息中显示不可达的具体原因,原因记录在 ICMP 包头的代码字段。

由此,根据 ICMP 不可达的具体消息,发送端主机也就可以了解此次发送不可达的具体原因。

6 种常见的目标不可达类型的代码:

  • 0:网络不可达
  • 1:主机不可达
  • 2:协议不可达
  • 3:端口不可达
  • 4:需要进行分片但设置了不分片

网络不可达代码为 0:

  • IP 地址是分为网络号和主机号的,所以当路由器中的路由器表匹配不到接收⽅ IP 的网络号,就通过 ICMP 协议以网络不可达(Network Unreachable)的原因告知主机。

自从不再有网络分类以后,网络不可达也渐渐不再使用了。

主机不可达代码为 1:

  • 当路由表中没有该主机的信息,或者该主机没有连接到网络,那么会通过 ICMP 协议以主机不可达(Host Unreachable)的原因告知主机。

协议不可达代码为 2:

  • 当主机使用 TCP 协议访问对端主机时,能找到对端的主机了,可是对端主机的防火墙已经禁止 TCP 协议访问,那么会通过 ICMP 协议以协议不可达的原因告知主机。

端口不可达代码为 3:

  • 当主机访问对端主机 8080 端口时,这次能找到对端主机了,防火墙也没有限制,可是发现对端主机没有进程监听 8080 端口,那么会通过 ICMP 协议以端口不可达的原因告知主机。

需要进行分片但设置了不分片位代码为 4:

  • 发送端主机发送 IP 数据报时,将 IP 首部的分片禁止标志位设置为 1。根据这个标志位,途中的路由器遇到超过MTU 大小的数据包时,不会进行分片,而是直接抛弃。

随后,通过一个 ICMP 的不可达消息类型,代码为 4 的报文,告知发送端主机。

原点抑制消息

在使用低速⼴域线路的情况下,连接 WAN 的路由器可能会遇到网络拥堵的问题。ICMP 原点抑制消息的目的就是为了缓和这种拥堵情况。

当路由器向低速线路发送数据时,其发送队列的缓存变为零而⽆法发送出去时,可以向 IP 包的源地址发送一个 ICMP 原点抑制消息。

收到这个消息的主机借此了解在整个线路的某一处发生了拥堵的情况,从而增大 IP 包的传输间隔,减少网络拥堵的情况。

然而,由于这种 ICMP 可能会引起不公平的网络通信,一般不被使用。

重定向消息

如果路由器发现发送端主机使用了「不是最优」的路径发送数据,那么它会返回一个 ICMP 重定向消息给这个主机。

在这个消息中包含了最合适的路由信息和源数据。这主要发生在路由器持有更好的路由信息的情况下。路由器会通过这样的 ICMP 消息告知发送端,让它下次发给另外一个路由器。

超时消息

IP 包中有一个字段叫做 TTL(Time To Live,生存周期),它的值随着每经过一次路由器就会减 1,直到减到 0 时该 IP 包会被丢弃。

此时,路由器将会发送一个 ICMP 超时消息给发送端主机,并通知该包已被丢弃。

设置 IP 包生存周期的主要目的,是为了在路由控制遇到问题发生循环状况时,避免 IP 包⽆休止地在网络上被转发。

此外,有时可以用 TTL 控制包的到达范围,例如设置一个较小的 TTL 值。

ping — 查询报文类型的使用

接下来,我们来看ping的发送和接收过程。

同个⼦网下的主机 A 和 主机 B,主机 A 执行ping主机 B 后,我们来看看其间发送了什么。

ping命令执行的时候,源主机首先会构建一个 ICMP 回送请求消息数据包。

ICMP 数据包内包含多个字段,最重要的是两个:

  • 第一个是类型,对于回送请求消息而⾔该字段为 8;
  • 另外一个是序号,主要用于区分连续 ping 的时候发出的多个数据包。

每发出一个请求数据包,序号会自动加 1。为了能够计算往返时间 RTT,它会在报文的数据部分插⼊发送时间。

然后,由 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 地址后,由数据链路层构建一个数据帧,目的地址是 IP 层传过来的 MAC 地址,源地址则是本机的 MAC 地址;还要附加上一些控制信息,依据以太网的介质访问规则,将它们传送出去。

主机 B 收到这个数据帧后,先检查它的目的 MAC 地址,并和本机的 MAC 地址对比,如符合,则接收,否则就丢弃。

接收后检查该数据帧,将 IP 数据包从帧中提取出来,交给本机的 IP 层。同样,IP 层检查后,将有用的信息提取后交给 ICMP 协议。

主机 B 会构建一个 ICMP 回送响应消息数据包,回送响应数据包的类型字段为 0,序号为接收到的请求数据包中的序号,然后再发送出去给主机 A。

在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明目标主机不可达;如果接收到了 ICMP 回送响应消息,则说明目标主机可达。

此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。

针对上面发送的事情,总结成了如下图:

当然这只是最简单的,同一个局域网里面的情况。如果跨网段的话,还会涉及网关的转发、路由器的转发等等。

但是对于 ICMP 的头来讲,是没什么影响的。会影响的是根据目标 IP 地址,选择路由的下一跳,还有每经过一个路由器到达一个新的局域网,需要换 MAC 头里面的 MAC 地址。

说了这么多,可以看出ping这个程序是使用了 ICMP 里面的 ECHO REQUEST(类型为 8) 和 ECHO REPLY(类型为 0)。

ping 常用命令

ping的作用主要为:

  1. 用来检测网络的连通情况和分析网络速度
  2. 根据域名得到服务器 IP
  3. 根据ping返回的 TTL 值来判断对方所使用的操作系统及数据包经过路由器数量

我们通常会用它来直接ping ip地址,来测试网络的连通情况。

各值解释:

  • bytes值:数据包大小,也就是字节。
  • time值:响应时间,这个时间越小,说明你连接这个地址速度越快。
  • TTL 值:Time To Live, 表示 DNS 记录在 DNS 服务器上存在的时间,它是 IP 协议包的一个值,告诉路由器该数据包何时需要被丢弃。可以通过Ping返回的 TTL 值大小,粗略地判断目标系统类型是 Windows 系列还是 UNIX/Linux 系列。

默认情况下,Linux 系统的 TTL 值为 64 或 255,WindowsNT/2000/XP 系统的 TTL 值为 128,Windows98 系统的 TTL 值为 32,UNIX 主机的 TTL 值为 255。

ping命令除了直接ping网络的ip地址,验证网络畅通和速度之外,它还有这些用法。

ping -t

不间断地ping指定计算机,直到管理员中断。

ping -a

ping -a解析计算机名与 NetBios 名。就是可以通过ping它的ip地址,可以解析出主机名。

ping -n count

在默认情况下,一般都只发送四个数据包,通过这个命令可以自己定义发送的个数,对衡量网络速度很有帮助,比如我想测试发送 10 个数据包的返回的平均时间为多少,最快时间为多少,最慢时间为多少。

ping -l size

默认的情况下 Windows 的ping发送的数据包大小为32byte,最大能发送65500byte。当一次发送的数据包大于或等于65500byte时,将可能导致接收方计算机宕机。所以微软限制了这一数值;这个参数配合其它参数以后危害非常强大,比如攻击者可以结合-t参数实施 DOS 攻击。

tracert

ping 工具只能测试目的设备的连通性,但是看不到数据包的传输路径。所以在网络不通的情况下,无法知道网络问题发生在哪个位置。tracert工具可以查看数据包的整条传输路径,包括途中经过的中间设备。

IP 头部的 TTL 字段是为避免数据包循环转发而设计的。每经过一个路由器,数据包头中的 TTL 值减 1。如果 TTL 值为 0 则丢弃报文,并向源设备回应一个Time Exceeded消息,告知错误类型。tracert就是基于 TTL 字段和 ICMP 协议实现的。在 Windows 中命令是tracert,在 Unix、MacOS 中命令是traceroute

使用tracert命令时,源设备的tracert逐跳发送数据包,并等待每一个响应报文。发送第一个数据包时,TTL 值设为 1。第一个路由器收到数据包后 TTL 值减 1 ,随即丢弃数据包,并返回一个Time Exceeded消息。源设备的tracert收到响应报文后,取出源 IP 地址,即路径上的第一个路由器地址。然后tracert发送一个 TTL 值为 2 的数据包。第一个路由器将 TTL 值减 1,并转发数据包。第二个路由器再将 TTL 值减 1,丢弃数据包并返回一个Time Exceeded消息。tracert收到响应报文后,取出源 IP 地址,即路径上的第二个路由器地址。类似步骤,tracert逐跳获得每一个路由器的地址,并探测到目的设备的可达性。

tracert过程也是双向的消息通信,只有双向都成功传输时,才能正确探测路径。另外主机安装了防火墙,也可能造成路径探测失败。

在 Windows 电脑上使用tracert命令,并查看返回信息。

同步抓包进行验证。

打赏
  • Copyrights © 2017-2023 WSQ
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信