You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何创建大于64KB的TCP数据包并保存为pcap文件?

如何创建大于64KB的TCP数据包并保存为pcap文件?

我明白你遇到的问题了——Scapy默认会严格遵循TCP/IP协议规范:IP层的总长度字段是16位(最大值65535,对应约64KB,包含IP头和负载),TCP伪头的长度校验也依赖这个16位字段,所以当你尝试构造超大数据包时,Scapy的自动校验逻辑就会抛出'H' format requires 0 <= number <= 65535的错误。

要构造这种不符合协议规范但用于测试的超大TCP数据包,我们可以通过两种方式实现:


方法1:绕过Scapy的自动协议校验

我们可以关闭Scapy的自动校验和计算、重写协议层的处理逻辑,强制让它生成并保存不符合规范的数据包:

from scapy.all import *
import socket

# 1. 关闭Scapy的自动校验与地址检查
conf.checkIPaddr = False
conf.checkTCPsum = False
conf.checkUDPsum = False

# 2. 重写IP层的post_build方法,跳过自动长度计算
original_ip_post_build = IP.post_build
def custom_ip_post_build(pkt, pay):
    # 直接返回原始IP头+负载,不自动计算总长度
    return pkt + pay
IP.post_build = custom_ip_post_build

# 3. 重写TCP层的post_build方法,跳过自动校验和计算
original_tcp_post_build = TCP.post_build
def custom_tcp_post_build(pkt, pay):
    # 直接返回原始TCP头+负载,不自动计算校验和
    return pkt + pay
TCP.post_build = custom_tcp_post_build

# 4. 构造超大数据包
big_payload = Raw(RandString(size=120000))
big_packet = IP(src="127.0.0.1", dst="192.168.2.71", chksum=0) / \
             TCP(sport=123, dport=456, chksum=0) / \
             big_payload

# 5. 写入pcap文件
wrpcap("/tmp/big_tcp_scapy.pcap", [big_packet])

# 6. 恢复Scapy的原始处理逻辑(避免影响后续操作)
IP.post_build = original_ip_post_build
TCP.post_build = original_tcp_post_build

代码解释:

  • 关闭Scapy的各类校验开关,避免它因为"非法"的长度或校验和报错
  • 重写post_build方法:这是Scapy在生成最终数据包字节流前的处理钩子,默认会自动计算IP长度、TCP校验和等字段,我们直接跳过这些步骤,保留原始的头部与负载拼接结果
  • 手动设置chksum=0,明确告诉Scapy不要自动计算校验和

方法2:手动构造pcap文件(无工具限制)

如果Scapy的限制还是太严格,我们可以完全绕过工具,手动构造pcap文件的所有字节内容,这种方法能生成任何格式的数据包:

import struct
import random
import time

# 1. 构造原始的IP+TCP+超大负载字节流
# 简化版IP头(不计算校验和)
ip_header = struct.pack('!BBHHHBBH4s4s',
    0x45,          # 版本(4) + IHL(5,即20字节IP头)
    0,             # TOS字段
    0,             # 总长度(我们不设置,直接用实际总长度)
    0,             # 标识ID
    0,             # 标志+片偏移
    64,            # TTL
    6,             # 协议类型:TCP
    0,             # IP校验和(设为0)
    socket.inet_aton('127.0.0.1'),
    socket.inet_aton('192.168.2.71')
)

# 简化版TCP头(不计算校验和)
tcp_header = struct.pack('!HHLLBBHHH',
    123,           # 源端口
    456,           # 目的端口
    0,             # 序列号
    0,             # 确认号
    5 << 4,        # 数据偏移(5,即20字节TCP头) + 保留位
    0,             # 标志位
    65535,         # 窗口大小
    0,             # TCP校验和(设为0)
    0              # 紧急指针
)

# 120KB的随机负载
big_payload = bytes(random.getrandbits(8) for _ in range(120000))
raw_packet = ip_header + tcp_header + big_payload

# 2. 构造pcap文件的全局头部
pcap_global_header = struct.pack('!IHHIIII',
    0xa1b2c3d4,    # 魔术数字,标识大端格式的pcap文件
    2, 4,          # pcap版本2.4
    0,             # 时区偏移(0表示UTC)
    0,             # 时间戳精度
    262144,        # SnapLen:设置为256KB,确保能容纳超大数据包
    2              # 数据链路类型:以太网(大多数pcap文件的默认类型)
)

# 3. 构造单个数据包的头部
ts_sec = int(time.time())
ts_usec = 0
packet_len = len(raw_packet)
pcap_packet_header = struct.pack('!IIII',
    ts_sec,        # 时间戳(秒)
    ts_usec,       # 时间戳(微秒)
    packet_len,    # 文件中保存的数据包长度
    packet_len     # 原始数据包的实际长度
)

# 4. 写入pcap文件
with open('/tmp/big_tcp_raw.pcap', 'wb') as f:
    f.write(pcap_global_header)
    f.write(pcap_packet_header)
    f.write(raw_packet)

代码解释:

  • 直接构造IP、TCP头的字节流,完全跳过任何协议校验
  • 手动生成pcap文件的全局头和数据包头部:pcap文件有固定的格式,只要遵循这个格式就能被Wireshark、tcpreplay等工具识别
  • SnapLen设置为足够大的值(比如256KB),确保能容纳我们的超大数据包

注意事项

  1. 这种超大数据包完全不符合TCP/IP协议规范,正常网络中根本不会存在,只能用于测试网络设备对异常数据包的处理能力
  2. 用Wireshark等工具打开生成的pcap文件时,会弹出协议错误的警告,这是正常现象,因为数据包本身就是非法的
  3. 如果需要用tcpreplay等工具重放,确保工具的配置允许处理超大数据包(比如调整缓冲区大小)

火山引擎 最新活动