TCP/IP协议族详解(四)

本系列文章是教程:TCP、IP协议族详解的学习笔记。

该系列大概分为下面几个部分:

  • 1、TCP/IP协议4层结构以及每层的作用
  • 2、IP协议详解
  • 3、ARP协议和RARP协议详解
  • 4、ICMP协议详解
  • 5、TCP协议详解
  • 6、UDP协议详解

本文主要介绍TCP/IP网络体系中网络层的ICMP协议。

1、IP协议的缺点

  • 无差错报告和差错纠正机制
  • 缺少一种为主机和管理查询的机制

例如:当 IP 数据报在网络中超过了它的 TTL,那么路由器就会将这个数据报丢弃,但是没有对这个丢弃操作返回错误报告。 为了弥补 IP 协议的这些缺点,所以就产生了 ICMP 协议。需要注意的是:ICMP 没有纠正错误的机制

2、ICMP协议的数据封装格式

它的大概封装格式如下: ICMP的封装

ICMP 本身是网络层协议。但是,它的报文不是如设想的那样直接传送给数据链路层,实际上,ICMP 报文首先封装成IP数据报, 然后再传送给下一层。在IP 数据报中的协议字段值是 1 就表示其IP数据是 ICMP 报文。通过抓包可以证实这一点。

  1. 通过 ping www.baidu.com 命令,使计算机产生 ICMP 报文;
  2. 通过 Wireshark 抓包,筛选 ICMP 协议,此时抓包的结果如下图所示: ICMP的封装

3、ICMP报文种类

差错报告报文

可以理解成是错误信息 error,它总是把差错报告返回给原始的数据源。常用的错误类型有:

  • 类型3:终点不可达,例如:无法到达目的地,可能是硬件错误、软件设置错误等等原因导致
  • 类型4:源点抑制,例如:发送方发送速率太快,但是某个路由器接受速率过慢,那么这个路由器就会返回一个 ICMP,通知发送方速率要慢一点
  • 类型5:路由重定向,例如:当路由器发现数据报走的不是最佳路由,就会返回一个 ICMP 报告,让发送方下次不要走这里了
  • 类型11:超时,例如:发生了路由环路,从而导致 TTL 变为 0 值
  • 类型12:参数问题,例如:数据报的首部被篡改或者丢失

我们使用tracert www.baidu.com这个命令,然后抓一些 ICMP 包,如下图,可以看到很多黑色的结果,即差错报告。 ICMP的差错报告

差错报文的要点:

  • 对于携带 ICMP 差错报文的数据报,不再产生 ICMP 差错报文
  • 对于分片的数据报,如果不是第一个分片,则不产生 ICMP 差错报文
  • 对于具有多播地址(224.0.0.0-239.255.255.255)的数据报,不产生 ICMP 差错报文
  • 对于具有特殊地址如(127.0.0.0或0.0.0.0)的数据报,不产生 ICMP 差错报文

查询报文

常用的类型有:

  • 类型8或者0:返回请求或回到,例如常用的 ping 命令
  • 类型13或14:时间戳请求或回答,注意:需要两方的时间必须与标准时间同步
  • 类型17或18:地址码(掩码)请求或回答,不太常用(过时)
  • 类型10或9:路由器查询通告

4、ICMP头部格式

ICMP两种报文种类有着不同的头部格式,但区别不大,前 4 个字节是一样的,不同的只有后面4个字节。

查询报文头部格式

ICMP查询报文头部格式如下,主要包括两个部分:8 byte + 32 byte 的数据。格式如下图: ICMP的查询报文头部格式

通过抓包证实一下:

  1. 运行 ping www.baidu.com,开始抓包
  2. 筛选 ICMP 协议包,结果如下: ICMP抓包结果
  3. 字段解释:
    • 第1个字节:值为08,表示这是一个查询报文
    • 第2个字节:值为00
    • 第3、4个字节:值为0x4d14,表示头部校验和
    • 第5、6个字节:值为0x0001,注意:这里要分大端和小端格式,一般windows和linux都是小端,所以,这里应该看:Identifier(LE):256(0x0100)
    • 第7、8个字节:值为0x4700,同上,也需要分大小端。
    • 后面的32个字节为测试数据

差错报告报文头部格式

ICMP差错报文头部格式如下(通用格式),这里需要注意的一点是,差错报告报文的格式除了前4个字节, 后面的字节所对应的意义是根据type值code值发生变化的。

ICMP的差错报文头部格式

通过抓包证实一下:

  1. 运行 tracert www.baidu.com,开始抓包(注意:这里用的是tracert命令
  2. 筛选 ICMP 协议包,结果如下(后4个字节全部为0): ICMP抓包结果

关于查询报文和差错报文的type和code字段所代表的具体信息,这里不做详细的介绍,如果需要,可以查看本教程的课件。

5、ping命令使用详解

ping命令是基于ICMP的查询报文,分为回送请求和回送应答,请求类型为8,应答类型为0

现在我使用 ping www.baidu.com 命令 (windows 10系统),得到下面的结果:

C:\Windows\System32>ping www.baidu.com

正在 Ping www.a.shifen.com [14.215.177.39] 具有 32 字节的数据:
来自 14.215.177.39 的回复: 字节=32 时间=7ms TTL=54
来自 14.215.177.39 的回复: 字节=32 时间=8ms TTL=54
来自 14.215.177.39 的回复: 字节=32 时间=8ms TTL=54
来自 14.215.177.39 的回复: 字节=32 时间=7ms TTL=54

14.215.177.39 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 7ms,最长 = 8ms,平均 = 7ms

详细介绍下上面的过程:

  1. 首先通过 dns 服务,将域名解析成 IP 地址,也就是上面的 www.a.shifen.com [14.215.177.39]
  2. 然后 ping 命令发送一个带有 32 字节数据的 ICMP 请求包,收到回复后显示结果, 也就是上面的 来自 14.215.177.39 的回复: 字节=32 时间=7ms TTL=54, 其中字节表示测试数据长度(可以通过-l参数指定测试数据的大小,例如ping -l 1024 www.baidu.com); 时间表示包的往返时间(一去一来所用的时间); TTL为54(请求包的TTL为64),也就是回复的包进过了10个路由器。

通过抓包,可以证实上面的流程(我使用的是 ping -l 1024 www.baidu.com)。 ping抓包结果1 ping抓包结果2

注意:上图的 Length 是 1066,也就是包的总长度是 1066 byte。那么这个 1066 是怎么算出来的?

1066 = 1024 byte(ICMP 数据长度) + 8 byte(ICMP 头部长度) + 20 byte(IP 头部) + 14 byte(以太网头部)。

6、tracert命令详解

linux下的命令是 traceroute,windows 下使用 tracert。tracert 可以解决 ping 的不足,它能定位到某一个具体的某一台设备。

先介绍一下 tracert 命令的工作原理:命令发起方会依次对到达目的主机的路由路径中的路由节点发起一轮 ping 请求, 三次 ping 为一轮,每一轮的 TTL 值加以(第一轮为 1,第二轮为 2,…依次类推),逐个检查这条路由路径上每个路由节点。 最核心的一句话就是:它就是利用了路由器对 TTL 为 0 的包进行丢弃后,返回给源主机一个 ICMP 差错报告报文这一点来实现的。

大概流程如下图所示: tracert流程

下面通过一个实例来使用一下这个命令,并通过抓包,验证上面描述的流程。 打开CMD(win 10系统),运行命令tracert www.qq.com,等待一段时间,得到下面的结果。

C:\Windows\System32>tracert www.qq.com
通过最多 30 个跃点跟踪
到 www.qq.com [59.37.96.63] 的路由:
  1    <1 毫秒   <1 毫秒   <1 毫秒 192.168.2.1
  2     1 ms     1 ms     2 ms  192.168.3.1
  3     1 ms     1 ms     1 ms  192.168.1.1
  4     3 ms     9 ms     6 ms  100.64.0.1
  5     8 ms     6 ms     6 ms  218.19.193.181
  6     *        *        *     请求超时。
  7     7 ms    18 ms     6 ms  119.147.223.122
  8     *        *        *     请求超时。
  9     9 ms     8 ms     8 ms  14.17.2.62
 10     *        *        *     请求超时。
 11     *        *        *     请求超时。
 12     *        *        *     请求超时。
 13     *        *        *     请求超时。
 14     *        *        *     请求超时。
 15     8 ms     8 ms    11 ms  59.37.96.63

跟踪完成。

第一列是路由器的编号,也可以算作是请求包的TTL值,第2到第4列,分别表示这一轮的三次ping所花费的时间 (往返时间,*表示这个路由器没有响应,但是不能确定就是这个路由器有问题,可能是路由器设置了不处理ICMP协议), 第5列表示这一轮的目的路由节点的IP地址。跟踪结束后,停止抓包,通过分析抓包结果,与上面的工作原理是完全符合的。 tracert抓包1 tracert抓包2