乐于分享
好东西不私藏

Scapy库实战 | 发包工具(源码)

Scapy库实战 | 发包工具(源码)

一、什么是Scapy?

Scapy 是一个强大的Python网络数据包处理库,可以用来构造、发送、捕获和分析网络数据包。它就像是网络世界的"瑞士军刀",让我们能够随心所欲地操控网络流量。

💡 核心优势

  • 支持多种协议(ARP、ICMP、TCP、UDP、IPv6等)

  • 可以构造任意复杂的数据包

  • 支持数据包发送和接收

  • 强大的数据包分析能力

二、核心模块解析

2.1 数据包构造基础

在Scapy中,数据包是通过协议层叠加来构造的:

Python                  # 最简单的数据包结构                  packet = Ether() / IP() / TCP()                  # 带数据的TCP包                  packet = Ether(src="8c:1f:64:c3:45:9A", dst="56:ce:f4:e0:06:aa") / \                  IP(src="192.168.1.100", dst="192.168.1.200") / \                  TCP(dport=80, sport=12345, flags="S") / \                  b"Hello, Scapy!"

关键协议层说明

协议层

Scapy类

作用

Ether

Ether()

以太网帧,包含MAC地址

Dot1Q

Dot1Q(vlan=100)

VLAN标签

IP

IP(src, dst)

IPv4数据包

IPv6

IPv6(src, dst)

IPv6数据包

TCP

TCP(dport, sport, flags)

TCP段

UDP

UDP(dport, sport)

UDP数据报

ICMP

ICMP()

ICMP消息

2.2 数据包发送

Scapy提供了多个发送函数,最常用的是 sendp()

Python                  from scapy.all import sendp                  # 发送单个数据包                  sendp(packet, iface="eth0")                  # 发送多个数据包                  for _ in range(10):                  sendp(packet, iface="eth0")

发送函数对比

函数

说明

适用场景

send()

第三层发送

IP层以上

sendp()

第二层发送

包含以太网帧

sr()

发送并接收响应

需要响应的场景

sr1()

发送并接收一个响应

快速测试

三、实战:发包工具核心实现

3.1 数据包生成器架构

Python                  class PacketGenerator:                  def __init__(self, config):                  self.config = config                  self._build_context()                  def _build_packet(self, *layers):                  """构建数据包:Ether + VLAN + 协议层"""                  ether = Ether(src=self.src_mac, dst=self.dst_mac)                  if self.vlan:                  return [ether, self.vlan] + list(layers)                  return [ether] + list(layers)                  def _send(self, packet, count):                  """发送数据包"""                  for _ in range(count):                  sendp(packet, iface=self.iface)

3.2 常见协议实现

ARP请求

Python                  def _send_arp(self):                  # ARP请求包构造                  arp = ARP(                  op=1,# 1=请求,2=响应                  hwsrc=self.src_mac,# 源MAC                  psrc=self.src_ip,# 源IP                  hwdst='00:00:00:00:00:00',# 目标MAC(广播)                  pdst=self.dst_ip# 目标IP                  )                  packet = self._build_broadcast_packet(arp)                  sendp(packet, iface=self.iface)

ICMP请求

Python                  def _send_icmp(self):                  # ICMP Echo请求                  packet = self._build_packet(                  IP(src=self.src_ip, dst=self.dst_ip),                  ICMP()# 默认是Echo请求                  )                  sendp(packet, iface=self.iface)

TCP数据包

Python                  def _send_tcp(self):                  # TCP SYN包(flags=24表示PSH+ACK)                  packet = self._build_packet(                  IP(src=self.src_ip, dst=self.dst_ip),                  TCP(dport=self.dst_port, sport=self.src_port, flags=24),                  b"Hello from Scapy!"# 应用层数据                  )                  sendp(packet, iface=self.iface)

3.3 高级特性:IP分片

IP分片是网络中的重要概念,当数据包超过MTU时需要分片传输:

Python                  def _send_ip_fragment(self, proto="tcp"):                  layer = UDP(dport=self.dst_port, sport=self.src_port) if proto == "udp" else TCP(...)                  # 构造三个分片                  fragments = [                  # 第一个分片(flags=1表示还有后续分片)                  IP(flags=1, frag=0, id=1) / layer / data[:1432],                  # 第二个分片                  IP(flags=1, frag=180, id=1) / layer / data[1432:2864],                  # 最后一个分片(flags=0表示没有后续分片)                  IP(flags=0, frag=360, id=1) / layer / data[2864:]                  ]                  for frag in fragments:                  sendp(frag, iface=self.iface)

分片原理

  • flags=1:表示还有后续分片(MF位)

  • frag:分片偏移量(单位是8字节)

  • id:分片标识,相同ID的分片会被重组

3.4 IPv6扩展头

IPv6支持多种扩展头,如路由头和分片头:

Python                  def _send_ipv6_router_frag_udp(self):                  # IPv6路由扩展头 + 分片扩展头 + UDP                  packet = IPv6(src=self.src_ip, dst=self.dst_ip) / \                  IPv6ExtHdrRouting(nh=44, segleft=2, addresses=["2001:db8::3", "2001:db8::4"]) / \                  IPv6ExtHdrFragment(nh=17, m=1, offset=0, id=1) / \                  UDP(dport=self.dst_port, sport=self.src_port) / \                  b"IPv6 Router Fragment Test"                  sendp(packet, iface=self.iface)

四、使用方法

4.1 命令行模式

Bash                  # 发送ARP请求                  python -m scapy_traffic -i eth0 -t arp -c 10 -di 192.168.1.1                  # 发送TCP流量                  python -m scapy_traffic -i eth0 -t tcp -c 100 -si 10.0.0.1 -di 10.0.0.2 -sp 12345 -dp 80                  # 发送IPv6 NDNS                  python -m scapy_traffic -i eth0 -t ndns -c 50 -si 2001:db8::1

4.2 Python API模式

Python                  from scapy_traffic import TrafficSender, TrafficConfig                  # 创建配置                  config = TrafficConfig(                  type="tcp",                  iface="eth0",                  src_ip="192.168.1.100",                  dst_ip="192.168.1.200",                  src_port=12345,                  dst_port=80,                  count=10                  )                  # 发送流量(5个并发线程)                  sender = TrafficSender()                  sender.send(config, thread_count=5)

五、支持的协议类型

协议类型

说明

适用场景

arp

ARP请求

网络发现、MAC地址获取

icmp

ICMP请求

连通性测试

tcp

TCP数据包

TCP协议测试

udp

UDP数据包

UDP协议测试

ip

裸IP包

基础IP层测试

ip_frag_tcp/udp

IP分片

MTU测试

igmpv2/igmpv3

IGMP组播

组播协议测试

ndns/ndna

IPv6 ND

IPv6邻居发现

nh_frag_tcp/udp

IPv6分片

IPv6 MTU测试

nh_router_udp

IPv6路由

IPv6路由扩展测试

六、总结

🎯 工具价值

  • 协议测试:支持IPv4/IPv6多种协议,满足网络设备测试需求

  • 性能测试:支持多线程并发发送,模拟高流量场景

  • 自动化集成:提供Python API,易于集成到自动化测试框架

  • 灵活配置:支持自定义IP、端口、VLAN等参数

💡 学习建议

  • 从简单的ARP/ICMP开始,理解数据包构造原理

  • 尝试修改协议字段,观察网络行为变化

  • 使用Wireshark抓包,验证发送的数据包结构

  • 扩展支持新的协议类型

📮 互动时间

你在网络测试中遇到过哪些有趣的问题?欢迎在评论区留言分享!

如果觉得这篇文章对你有帮助,欢迎点赞、在看、转发三连支持!

如需工具源码,请私信我获取!

关注我,获取更多网络技术干货! 🔍