dufaxing To be a better man

PING包数据解析



KYHHbj.png

博客地址

1.前言

PING(Packet Internet Groper)是基于 ICMP(Internet Control Message Protocol,互联网控制报文协议) 的网络诊断工具,用于测试主机之间的连通性、测量往返时间(RTT)及检测丢包。

在不借助抓包工具等情况下,也可通过空口协议栈中数据链路层数据码流分析RRT时延。


2 数据分析

在ICMP协议中,标识符(Identifier)和序列号(Sequence Number)是匹配PING请求(Echo Request)与回复(Echo Reply)的关键字段。

2.1 ICMP Echo请求/回复报文结构

ICMP头部(Echo类型)的格式如下(以IPv4为例):

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |     Code      |          Checksum             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Identifier          |        Sequence Number        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Data... (可变长度,PING默认包含时间戳或填充字符)          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • Type

    • 8 = Echo Request(请求)

    • 0 = Echo Reply(回复)

  • Code:始终为0

  • Checksum:ICMP报文的校验和。

  • Identifier(标识符):2字节,用于标识会话(通常为进程ID或自定义值)。

  • Sequence Number(序列号):2字节,用于标识同一会话中的不同报文。


2.2 标识符和序列号的作用

(1) Identifier(标识符)

  • 功能:区分不同主机或进程的PING会话。

    • 在Linux/Windows中,PING命令默认将标识符设置为进程ID(例如ping进程的PID)。

    • 同一主机的多个PING进程会使用不同标识符,避免回复混淆。

  • 示例

    • 进程A的PING标识符=0x1234,进程B的PING标识符=0x5678

    • 回复报文必须携带与请求相同的标识符。

(2) Sequence Number(序列号)

  • 功能:标识同一会话中的报文顺序,用于检测丢包或乱序。

    • 每发送一个Echo Request,序列号递增(通常从0开始)。

    • 回复报文必须携带与请求相同的序列号。

  • 示例

    • 第一次PING:序列号=0x0001

    • 第二次PING:序列号=0x0002


2.3 匹配请求与回复的流程

以抓包数据为例(16进制显示ICMP头部):

请求帧(Echo Request)

Type=08, Code=00, Checksum=ABCD  
Identifier=00 01  (0x0001)  
Sequence=00 01    (0x0001)  
Data=...

回复帧(Echo Reply)

Type=00, Code=00, Checksum=1234  
Identifier=00 01  (0x0001)  ← 必须与请求一致  
Sequence=00 01    (0x0001)  ← 必须与请求一致  
Data=...                    ← 数据内容通常原样返回

匹配规则

  1. 回复的IdentifierSequence必须与某个请求完全一致。

  2. 通过这两个字段,可以唯一确定一个请求的回复,即使网络中同时存在多个PING会话。


2.4 总结

  • 标识符:区分不同PING会话(如多进程场景)。

  • 序列号:标识同一会话中的报文顺序。

  • 匹配关键:通过Identifier + Sequence唯一关联请求与回复,确保RTT计算的准确性。

RRT = 相同标识符与序列号下,回复报文接受时间-请求报文发送时间

3 IPV4举例

完整的 Ping 请求(Echo Request)和回复(Echo Reply)的数据链路层(Ethernet + IP + ICMP)数据包示例,包含 RTT(Round-Trip Time)时延计算 的详细解析。假设通信双方如下:

  • 主机A(发送请求)

    • MAC: 00:11:22:33:44:55

    • IP: 192.168.1.100

  • 主机B(回复)

    • MAC: AA:BB:CC:DD:EE:FF

    • IP: 8.8.8.8

3.1 Ping 请求(Echo Request)

完整数据包(Hex 格式)

FFFFFFFFFFFF 001122334455 0800 4500005400004000FF01 0000 C0A80164 08080808 0800 F5CA 0001 0001 6162636465666768696A6B6C6D6E6F70

关键字段解析:

字段 说明
Ethernet 目标 MAC FFFFFFFFFFFF 广播地址(实际场景中为网关或目标 MAC)。
Ethernet 源 MAC 001122334455 主机A的 MAC。
IP 协议 0800 IPv4。
IP 源地址 C0A80164 192.168.1.100。
IP 目标地址 08080808 8.8.8.8。
ICMP 类型 08 Echo Request。
ICMP 标识符 0001 用于匹配请求与回复(通常为进程 ID)。
ICMP 序列号 0001 请求序号。
数据部分 616263…6F70 ASCII 数据 “abcdefghijklmnop”。

3.2 Ping 回复(Echo Reply)

完整数据包(Hex 格式)

001122334455 AABBCCDDEEFF 0800 4500005400004000FF01 0000 08080808 C0A80164 0000 FDCA 0001 0001 6162636465666768696A6B6C6D6E6F70

关键字段解析:

字段 说明
Ethernet 目标 MAC 001122334455 主机A的 MAC。
Ethernet 源 MAC AABBCCDDEEFF 主机B的 MAC。
IP 协议 0800 IPv4。
IP 源地址 08080808 8.8.8.8。
IP 目标地址 C0A80164 192.168.1.100。
ICMP 类型 00 Echo Reply。
ICMP 标识符 0001 与请求包一致。
ICMP 序列号 0001 与请求包一致。
数据部分 616263…6F70 原样返回请求的数据。

3.3 RTT(Round-Trip Time)时延计算

RTT 是 从发送 Echo Request 到接收 Echo Reply 的时间差,通常由 ping 工具自动计算。以下是手动计算方法:

(1)抓包工具记录时间戳

  • Wireshark 会显示每个包的时间戳(如 Frame 1Frame 2 的时间差)。

  • tcpdump 输出示例:

12:00:00.000000 IP 192.168.1.100 > 8.8.8.8: ICMP echo request, id 1, seq 1, length 64
12:00:00.002400 IP 8.8.8.8 > 192.168.1.100: ICMP echo reply, id 1, seq 1, length 64

(2)手动计算(需高精度时间戳)

如果通过代码抓包(如 Python 的 scapy),可记录发送和接收时间:

from scapy.all import *
import time

# 发送 Echo Request
send_time = time.time()
send(IP(dst="8.8.8.8")/ICMP(type=8, id=1, seq=1)/"abcdefghijklmnop")

# 捕获 Echo Reply
def callback(pkt):
    if pkt[ICMP].type == 0 and pkt[ICMP].id == 1 and pkt[ICMP].seq == 1:
        recv_time = time.time()
        rtt = (recv_time - send_time) * 1000  # 转为毫秒
        print(f"RTT: {rtt:.2f} ms")

sniff(filter="icmp and host 8.8.8.8", prn=callback, timeout=1)

输出示例:

RTT: 2.41 ms

4 IPV6举例

4.1Ping 请求(Echo Request)

ping请求包完整数据码流

以下为IPV6 ping包码流

aabbccddeeff00112233445586dd6000000000203a4020010db8000000000000000000000120010db80000000000000000000000028000f42cabcd00016162636465666768696a6b6c6d6e6f7071727374757677616263646566676869

整个数据包(包括以太网帧头、IPv6报头、ICMPv6报文)的十六进制码流进行分段解释

// 以太网帧头 (Ethernet Header) - 目标MAC和源MAC
// 假设目标MAC为 00:11:22:33:44:55, 源MAC为 aa:bb:cc:dd:ee:ff
aa bb cc dd ee ff 00 11  22 33 44 55

86 dd                  //IVP6

// IPv6 报头 (IPv6 Header)
6x 00 00 00           // 版本(6), 流量类别(0), 流标签(0)
00 20                 // 载荷长度 (32 bytes, 即ICMPv6报文长度)
3a                    // 下一个报头 (58 = 0x3a, 代表ICMPv6)
40                    // 跳数限制 (64)
20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 01 // 源地址: 2001:db8::1
20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 02 // 目标地址: 2001:db8::2

// ICMPv6 Echo Request 报文
80                    // 类型 (128 = Echo Request)
00                    // 代码 (0)
f4 2c                 // 校验和 (Checksum), 这是计算后的示例值,实际中会变化
ab cd                 // 标识符 (Identifier)
00 01                 // 序列号 (Sequence Number)

// 数据载荷 (Data Payload)
61 62 63 64 65 66 67 68  69 6a 6b 6c 6d 6e 6f 70  // abcdefghijklmnop
71 72 73 74 75 76 77 61  62 63 64 65 66 67 68 69  // qrstuvwabcdefghi

字段含义详解

我们将数据包分层解析:

A. 以太网帧头 (Ethernet Header)

字段 值 (十六进制) 含义
目标MAC地址 00 11 22 33 44 55 数据帧要发送到的设备的物理地址。
源MAC地址 aa bb cc dd ee ff 发送数据帧的设备的物理地址。
以太网类型 86 dd 指明上层协议是 IPv6。 (IPv4 是 08 00)

B. IPv6 报头 (IPv6 Header) - 固定40字节

字段 值 (十六进制) 含义
版本 (Version) 6 IP协议版本号,6代表IPv6。
流量类别 (Traffic Class) 00 类似于IPv4的TOS字段,用于QoS。  
流标签 (Flow Label) 00 000 用于标识同一“流”的数据包。
载荷长度 (Payload Length) 00 20 16进制 0x0020 = 十进制32。表示IPv6报头之后的数据长度(即ICMPv6报文长度)。
下一个报头 (Next Header) 3a 16进制 0x3a = 十进制58。表示紧接在IPv6报头后的下一个协议是 ICMPv6。
跳数限制 (Hop Limit) 40 16进制 0x40 = 十进制64。类似于IPv4的TTL,每经过一个路由器减1,减到0则丢弃。
源地址 (Source Address) 2001:0db8…0001 数据包的起源IPv6地址。 (2001:db8::1)
目标地址 (Destination Address) 2001:0db8…0002 数据包的目标IPv6地址。 (2001:db8::2)

C. ICMPv6 Echo Request 报文

字段 值 (十六进制) 含义
类型 (Type) 80 16进制 0x80 = 十进制128。表示这是一个 ICMPv6 Echo Request (回显请求) 报文。
代码 (Code) 00 对于Echo请求和回复,此字段始终为0。
校验和 (Checksum) f4 2c 用于检测ICMPv6报文和部分IPv6报头在传输过程中是否有错误。
标识符 (Identifier) ab cd 由发送进程设置,用于匹配请求和回复。例如,ping6 命令的进程ID。
序列号 (Sequence Number) 00 01 从0开始,每发送一个新的Echo请求就递增1,用于检测丢失或乱序的包。
数据 (Data) 61 62 63 … 可选的数据载荷。接收方在Echo Reply中必须原样返回此数据。这里是我们填充的32字节的字母序列。

4.2 Ping 回复数据包 (Echo Reply)

ping回复包完整数据码流

001122334455aabbccddeeff86dd6000000000203a4020010db8000000000000000000000220010db80000000000000000000000018100a1b2abcd00016162636465666768696a6b6c6d6e6f7071727374757677616263646566676869
// 以太网帧头 (Ethernet Header) - MAC地址与请求包方向相反
// 源MAC (原目标MAC): 00:11:22:33:44:55
// 目标MAC (原源MAC): aa:bb:cc:dd:ee:ff
00 11 22 33 44 55 aa bb  cc dd ee ff 86 dd

// IPv6 报头 (IPv6 Header) - 地址与请求包方向相反
6x 00 00 00           // 版本(6), 流量类别(0), 流标签(0)
00 20                 // 载荷长度 (32 bytes, ICMPv6报文长度)
3a                    // 下一个报头 (58 = 0x3a, ICMPv6)
40                    // 跳数限制 (64)
20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 02 // 源地址: 2001:db8::2
20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 01 // 目标地址: 2001:db8::1

// ICMPv6 Echo Reply 报文
81                    // 类型 (129 = Echo Reply) *这是关键变化*
00                    // 代码 (0)
[新的校验和]           // 校验和必须重新计算,此处为示例值 `a1 b2`
ab cd                 // 标识符 (Identifier) *不变*
00 01                 // 序列号 (Sequence Number) *不变*

// 数据载荷 (Data Payload) *原样返回*
61 62 63 64 65 66 67 68  69 6a 6b 6c 6d 6e 6f 70  // abcdefghijklmnop
71 72 73 74 75 76 77 61  62 63 64 65 66 67 68 69  // qrstuvwabcdefghi

字段含义详解

字段含义详解 (重点说明变化部分)

A. 以太网帧头 (Ethernet Header)

字段 值 (十六进制) 含义
目标MAC地址 aa bb cc dd ee ff 这是请求包的源MAC。回复包需要发回给最初的发送者。
源MAC地址 00 11 22 33 44 55 这是请求包的目标MAC。回复由这台主机发出。
以太网类型 86 dd 上层协议依然是 IPv6。

B. IPv6 报头 (IPv6 Header)

字段 值 (十六进制) 含义
版本/流量类别/流标签 60000000 与请求相同。
载荷长度 0020 32字节。ICMPv6回复报文长度与请求相同。
下一个报头 3a ICMPv6。
跳数限制 40 64。通常操作系统会设置一个默认值(如64或255)。
源地址 (Source Address) 2001:0db8…0002 这是请求包的目标地址 (2001:db8::2)。现在作为回复的源。
目标地址 (Destination Address) 2001:0db8…0001 这是请求包的源地址 (2001:db8::1)。现在作为回复的目标。

C. ICMPv6 Echo Reply 报文

字段 值 (十六进制) 含义
类型 (Type) 81 16进制 0x81 = 十进制129。这是最核心的变化,表明这是一个 ICMPv6 Echo Reply (回显答复) 报文。
代码 (Code) 00 对于Echo回复,此字段始终为0。
校验和 (Checksum) a1 b2 必须重新计算。因为ICMPv6类型字段变了(128->129),且IPv6的源/目标地址也对调了,校验和是基于伪首部和整个ICMPv6报文计算的,所以一定会变化。这里的值是示例。
标识符 (Identifier) ab cd 必须与请求包完全一致。这样请求方才能将回复与特定的Ping进程匹配。
序列号 (Sequence Number) 00 01 必须与请求包完全一致。用于标识这是哪个请求序列的回复。
数据 (Data) 61 62 63 … 必须与请求包完全一致。原样返回发送的数据载荷,用于验证数据完整性。

参考文献

ICMP报文通用格式

IPv4报文格式

IPv6报文格式


Similar Posts

上一篇 PDCP加解密DEMO

Comments