抓取 ping 时的网络请求
数据较短不需要分片
在 MacOS 上,我们可以使用命令: ping baidu.com 来测试与 baidu.com 的连接否有问题,ping 将会发送 ICMP 包,我们如果可以抓到就可以对 ICMP 包进行分析。
在 MacOS 上,我们可以使用 ping baidu.com -s <packetsize> 来指定发送的数据的大小,例如我们可以指定发送 800 字节的数据:
ping baidu.com -s 800我可以让它发送四次数据包然后停止。这里我们发现,虽然我们指定的是 800 字节的数据,但他实际显示,这里传输了 808 字节,这是因为,这里算上了 8 字节的 ICMP 头部,所以这是合理的。

在 wireshark 中,我们就抓到了 8 个包,因为 ping 是需要发送数据过去并且得到响应的,这里就是一个请求一个响应,总计 8 个。
并且可以发现,请求的源 IP 地址是 10 开头的地址,这是因为我使用的是校园网,所以这实际是一个内网 IP。
还可以发现,这里我们抓到的数据包长度是 842字节,这比 808 字节还要长,这是因为在 ICMP 的外围,还有一个 20 字节的 IP 头,而 wireshark 是在数据链路层抓数据帧,因此还会抓到 14 字节的以太网头部(目的 Mac + 源 Mac + 类型),加起来刚好 842 字节。

我们随便点开一个检查一下,可以看到网络层的数据包总共 828 字节(800 字节数据 + 8 字节ICMP 头部 + 20 字节 IP 数据包首部「只有固定部分」)。

数据较长需要分片
这一次我们只是发送了 800 字节,并没有超过以太网帧的 MTU,也就是没有超过 1500 字节,没有触发分片,加入我们这一次 ping 直接发送长度为 3000 的数据呢?这当然会触发分片,我们可以使用 ping baidu.com -s 3000 来发送一段 3000 字节的数据。

显示 Request timeout 了,实际上是因为包太大了,百度做了一定的防护,我们没办法发送这么大的数据过去,所以我们应该要换一个网址测试,这里选择 ke.qq.com,似乎腾讯的网址都比较大方,可以发送大一些的数据过去。
使用命令 ping ke.qq.com -s 3000 给 ke.qq.com 发送一段长度为 3000 字节的数据。

这次就可以了,总共发送了 4 次请求,wireshark 中也抓到请求,先过滤出 ICMP 协议的数据包,然后发现一共 8 条记录:

但是问题是,我们发现长度都是 82,而不是 3042!这其实很正常,还是以为 wireshark 抓包是在数据链路层开始抓的,然后对数据帧进行解析,显然这样抓到的数据已经是被分片以后的了。我们的过滤条件是 icmp,所以它实际上得到的结果只是包含了 IP Header、ICMP Header、部分 Data,想要得到全部的数据,我们就将过滤条件改为 `ip.addr <ke.qq.com 的 IP>`==

这样就可以得到全部的数据了:

这一个图的信息量极大,我们将会先对其中的第一部分进行单独细致地分析:

首先,我们发现从上到,先是两个 IPv4 数据包,然后是一个 ICMP,则实际上并不是说,我们真的是先给 ke.qq.com 发送两个 IPv4,然后再发送一个 ICMP,而是在网络上传输了三个 Fragment,然后 wireshark 抓取以后,在本地进行了重组,这里实际上是先生成了一个大的 ICMP 包,它包含了 IP Header、ICMP Header、 还有 3000 Bytes Data,总共加起来有 3028 字节,这显然已经超过了以太网帧的 MTU 1500 字节,于是内核对这个大包进行了分片,第一个分片包含了 IP Header(20 字节)、 ICMP Header(8 字节)、 1472 Bytes Data,第二个分片也是包含了 IP Header(20 字节) 和 1480 Bytes 字节, 第三个分片包含了剩下的 48 字节,然后因为最后一片已经可以确认这是一个完整的 ICMP 包了,所以这里就直接标记为 ICMP,我们还可以看到 75 和 76 在后面都标记了 Reassembled in #77 所以这实际上代表着 75 和 76 也是 ICMP 包组成的部分,ICMP 包比较大需要分片成这样再逐个传输过来而已:
