ICMP Echo Reply 消息中的附加字节

Additional bytes in ICMP Echo Reply message

我正在对 ICMP Echo 消息进行一些调查工作。

下面是十六进制转储的屏幕截图。 (请原谅我非常糟糕的注释。)

我从一个从原始套接字读取数据的 Python 3 程序中获得了这个。

这是一小段代码,详细说明了初始数据包的发送方式

mySocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
mySocket.settimeout(self.__ipTimeout)
mySocket.bind(("", 0))
mySocket.setsockopt(IPPROTO_IP, IP_TTL, struct.pack('I', self.getTtl()))  # Unsigned int - 4 bytes
packet = b''.join([self.__header, self.__data])
mySocket.sendto(packet, (self.__destinationIpAddress, 0))

然后阅读

recvPacket, addr = mySocket.recvfrom(1024)


这里有一些关于 ICMP Echo 数据包的信息:http://www.networksorcery.com/enp/protocol/icmp/msg0.htm

还有维基百科 link 到 IPv4 header:https://en.wikipedia.org/wiki/IPv4#IHL

IPv4 header 的长度为 20 个字节。 IHL 4 位值证实了这一点。数据包中的第一个字节是 0x45。这是 IPv4 的“4”和 IPv4 的 5 * 32 位字的“5”header。 (160 位 = 20 字节。)

稍后我们在数据包中找到“08 00”,这是 ICMP 回显请求数据包的开始。 ICMP header 是 8 个字节,并以红色突出显示。有点奇怪,这个数据包以 ICMP 代码 8 开头,因为这是回应请求,而不是回复。

后面的8个字节是用户时间戳。 (用户数据的一部分。)其后是大小写字母。 (52 字节的用户数据。)

有28字节数据不明。我是否遗漏了什么,例如网络层中的另一个 header?

此处的某些值似乎可能是合理的。例如,我们有序列 C0 A8 00 23,它是一个有效的本地网络地址 192.168.0.35。 (发送机器的地址。)

还有一系列零可能类似于 ICMP Echo Reply 的开始,但以下其余数据似乎没有多大意义。为什么标识符是45 00,序列号是00 58。我想这些是可能的值,但我不明白为什么它们有意义。

在这种情况下回复的设备是 Virgin Media Superhub。我猜这台设备可能会发回格式错误的 ping 数据包?

我们构建了一个 ICMP header。 Type = 8,Code = 0。我们向其中添加一些用户数据。用户数据长度为60。header长度为8。这是68字节的数据。

我们通过原始套接字将其发送到另一台机器。 sendto() 函数添加一个 IPv4 header.

数据包现在是 88 字节长。

如果超过 TTL,将生成类型 11、代码 0 的 ICMP 消息。此 ICMP 消息后附加的数据是已发送的超过 TTL 的整个数据包。 (包括 IPv4 header。)

这个新的 ICMP header 封装在一个新的 IPv4 header 中。这意味着我们返回的数据包的总长度为:88 + 8 + 20 = 116。原始数据包的 88 个字节,加上 ICMP 类型 11 的 8 个字节,再加上 20 个字节的 IPv4。

上图中没有突出显示的东西是8字节的ICMP Type 11,加上原始的IPv4 header。