您的位置:

IP数据报详解

一、IP数据报的定义

IP数据报是互联网协议(IP)中的一个基本概念,它是网络传输层中用于在计算机网络中进行传输的数据单元。IP数据报由源主机分段并通过互联网传输到目标主机,其中每个段都可能有不同的路径,通常也可能经过中转主机。

二、IP数据报首部

IP数据报首部是每个IP数据报中的头部信息,包含20个字节。其结构如下:

|              20 Bytes              |
+-----------------------------------+
|      Version      | Header Length |
+-----------------------------------+
|     Differentiated Services Field |
+-----------------------------------+
|              Total Length         |
+-----------------------------------+
|           Identification          |
+-----------------------------------+
|    Flags    | Fragment Offset     |
+-----------------------------------+
| Time to Live |    Protocol        |
+-----------------------------------+
|            Header Checksum        |
+-----------------------------------+
|            Source Address         |
+-----------------------------------+
|          Destination Address      |
+-----------------------------------+

三、IP数据报是哪一层

IP数据报是互联网协议中的网络层协议。

四、IP数据报首部长度

IP数据报首部长度固定为20字节,但是IP数据报的数据部分长度是可变的。

五、IP数据报报头

IP数据报报头由版本、首部长度、不同服务字段、标识、片偏、TTL、协议、源IP地址和目标IP地址组成,共20字节。其中不同服务字段用来指定所要求的服务的优先级,TTL是生存时间(Time To Live)的缩写,标识用于唯一地标识正在传输的数据片段。

六、IP数据报传输图示

IP数据报传输图示

七、IP数据报格式

一个标准的IP数据报包含一个20字节的首部和一个不定长的负载。其格式如下:

+------------+--------------+
|   Header   |   Payload    |
+------------+--------------+

八、IP数据报分片

由于IP数据报所能承载的负载大小有限,如果发送的数据大于MTU(Maximum transmission unit),则需要进行分片。在分片的过程中,IP数据报首部中的标识和片偏字段就成为了关键字。

九、IP数据报分析题

请分析下面的IP数据报:

0000   45 00 04 36 2c 4b 40 00 34 06 05 f3 ac 10 01 0b 
0010   ac 10 01 01 05 5b 11 ea 00 1e 36 da 59 7a 56 5e 
0020   b4 8d 58 50 18 ff ff 21 b9 00 00

分析结果如下:

  • 版本:4
  • 首部长度:5(20字节)
  • 不同服务字段:0
  • 总长度:1078字节(0x436)
  • 标识:0x2c4b
  • 片偏:0
  • TTL:52
  • 协议:6(TCP)
  • 源IP地址:172.16.1.11
  • 目标IP地址:172.16.1.1

十、IP数据报抓包选取

以下是Wireshark抓包显示的IP数据报(其中红框内的部分为IP数据报首部信息):

IP数据报抓包选取

完整代码示例

// 创建IP数据报
def create_ip_packet(source_ip, dest_ip, payload):
    packet = b''
    # 版本(IPv4)和首部长度(20字节)
    version = 4
    ihl = 5
    packet += struct.pack('!B', (version << 4) + ihl)
    # 不同服务字段
    packet += b'\x00'
    # 总长度(数据部分size + 首部size)
    total_length = len(payload) + 20
    packet += struct.pack('!H', total_length)
    # 标识、标志(2位)和片偏(13位)
    identification = random.randint(0, 65535)
    flags = 0
    fragment_offset = 0
    packet += struct.pack('!H', identification)
    packet += struct.pack('!H', (flags << 13) + fragment_offset)
    # TTL、协议(TCP)和头部校验和
    ttl = 64
    protocol = socket.IPPROTO_TCP
    packet += struct.pack('!B', ttl)
    packet += struct.pack('!B', protocol)
    packet += struct.pack('!H', 0)
    # 源IP地址和目标IP地址
    packet += socket.inet_aton(source_ip)
    packet += socket.inet_aton(dest_ip)
    # 计算假首部校验和
    pseudo_header = b''
    pseudo_header += socket.inet_aton(source_ip)
    pseudo_header += socket.inet_aton(dest_ip)
    pseudo_header += struct.pack('!B', 0)
    pseudo_header += struct.pack('!B', protocol)
    pseudo_header += struct.pack('!H', total_length - 20)
    # 计算真正的头部校验和
    packet += checksum(pseudo_header + packet)
    # 将数据部分添加到IP数据报中
    packet += payload
    return packet