news 2026/9/23 1:39:34

基于 Scapy 构建自定义网络工具与扩展:从自动化脚本到 add-on 交互式环境

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 Scapy 构建自定义网络工具与扩展:从自动化脚本到 add-on 交互式环境
  • 网络
  • 网络安全

【免费下载链接】scapy

Scapy: the Python-based interactive packet manipulation program & library.

项目地址:https://gitcode.com/gh_mirrors/sc/scapy
点击查看免费下载

本文是 Scapy 官方文档 Build your own tools(构建你自己的工具) 的深度实战解读。你将在本文中掌握三类核心能力:把 Scapy 作为库嵌入你自己的 Python 脚本(实现 ping 探测、ARP 扫描、流量监控等自动化工具);精确控制 Scapy 日志系统与输出详细度;以及不修改 Scapy 源码、以独立 add-on 文件扩展协议与函数,并通过interact()启动带自定义 banner 的交互式控制台。

写在前面:Scapy 扩展的两条路径

Scapy 的价值不仅在于交互式命令行,更在于它提供了两条清晰的扩展路径,本文覆盖官方文档的全部内容:

  1. 在你的工具中使用 Scapy:将scapy.all作为 Python 库导入,编写独立的自动化脚本;
  2. 以 add-on 方式扩展 Scapy:把自定义协议类、辅助函数写在一个单独的文件中,不修改 Scapy 源码,并通过interact()将其注入到交互式会话中。

官方文档(doc/scapy/extending.rst)明确表示:"You can also extend Scapy without having to edit its source file",这正是两种路径的共同基石。下面逐一展开。

在你的工具中使用 Scapy

把 Scapy 嵌入你自己的工具非常简单:导入所需模块,直接调用即可。其底层能力由 scapy/sendrecv.py(发送与接收)、scapy/layers/inet.py(IP/ICMP 等网络层协议)和 scapy/packet.py(包构建与解析)等模块支撑。

示例一:ICMP 回显探测

第一个例子接收一个 IP 地址或主机名作为参数,发送 ICMP 回显请求包,并显示完整解析后的返回包:

#! /usr/bin/env python import sys from scapy.all import sr1, IP, ICMP p = sr1(IP(dst=sys.argv[1]) / ICMP()) if p: p.show()

要点说明:

  • sr1()发送一层(Layer 3)数据包并等待第一个响应,返回解析后的应答包;p.show()以分层缩进方式打印包的完整字段;
  • 使用/操作符组合IP(dst=...)ICMP(),这是 Scapy 构建协议栈的标准语法;
  • sr1()超时未收到应答(默认超时行为由conf相关参数控制),pNone,脚本因此做了判空保护。

示例二:ARP ping 并输出 LaTeX 表格(arping2tex)

这是一个更完整的实战工具:对指定网段执行 ARP ping,并将结果格式化为 LaTeX 表格输出:

#! /usr/bin/env python # arping2tex : arpings a network and outputs a LaTeX table as a result import sys if len(sys.argv) != 2: print("Usage: arping2tex <net>\n eg: arping2tex 192.168.1.0/24") sys.exit(1) from scapy.all import srp, Ether, ARP, conf conf.verb = 0 ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=sys.argv[1]), timeout=2) print(r"\begin{tabular}{|l|l|}") print(r"\hline") print(r"MAC & IP\\") print(r"\hline") for snd, rcv in ans: print(rcv.sprintf(r"%Ether.src% & %ARP.psrc%\\")) print(r"\hline") print(r"\end{tabular}")

该脚本用到三个关键机制:

  • conf.verb = 0静默模式conf是 Scapy 的全局配置对象(定义于 scapy/config.py),其中verb字段控制输出详细度。源码注释(scapy/config.py#L984)写明其取值范围为 0(几乎静默)到 3(详细),默认值为 2。设置为 0 可以让脚本输出保持干净;
  • srp()二层收发srp()发送 Layer 2 帧(区别于一层的sr1()),返回二元组(answered, unanswered),即ansunans。通过广播目的 MACff:ff:ff:ff:ff:ff加上ARP(pdst=网段)实现网段扫描,timeout=2秒控制等待时间;
  • sprintf()格式化rcv.sprintf("%Ether.src% & %ARP.psrc%")按模板提取应答包中的源 MAC 与源 IP,逐行拼接成 LaTeX 表格行。

示例三:ARP 流量实时监控回调

下面的工具会持续监听本机所有接口,并打印捕获到的所有 ARP 请求(包括来自 Wi-Fi 网卡 monitor 模式下 802.11 帧中的 ARP)。注意sniff()store=0参数,避免在内存中无谓地保存全部报文:

#! /usr/bin/env python from scapy.all import * def arp_monitor_callback(pkt): if ARP in pkt and pkt[ARP].op in (1, 2): # who-has or is-at return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%") sniff(prn=arp_monitor_callback, filter="arp", store=0)

要点说明:

  • sniff()是 Scapy 抓包入口(实现在 scapy/sendrecv.py)。prn指定对每个捕获包调用的回调函数,回调的返回值会被打印;filter使用 BPF(Berkeley Packet Filter)语法只捕获 ARP 流量;store=0让数据包不被保存在内存列表中,适合长时间运行的监控型工具;
  • ARP in pkt检查数据包中是否包含 ARP 层;pkt[ARP].op取 ARP 操作码,1 表示 who-has(请求)、2 表示 is-at(应答);
  • if ARP in pkt之所以必要,是因为在 monitor 模式下,Wi-Fi 帧(802.11)可能承载着不同链路层协议,需要先确认内部确有 ARP 层再访问字段。

配置 Scapy 的日志系统

Scapy 会自动基于 Python 标准库的logging模块配置一个 logger。这个 logger 是定制化的,支持颜色输出和频率过滤等特性。默认情况下(非交互模式)日志级别为WARNING,你可以通过以下方式修改,例如设为CRITICAL以几乎禁用所有日志:

import logging logging.getLogger("scapy").setLevel(logging.CRITICAL)

需要理解的两点:

  • 默认级别因模式而异:官方文档特别提示,交互模式下默认日志级别为INFO。这与 scapy/config.py#L967 中的logLevel配置项直接相关——该配置项是一个带拦截器(Interceptor)的属性,级别变化会触发_loglevel_changer回调(scapy/config.py#L915)来同步调整底层log_scapy的实际级别;
  • CRITICAL 的边界:官方文档明确指出"Scapy simply won't work properly if a CRITICAL failure occurs",即 CRITICAL 用于严重故障,设为该级别后正常运行时几乎无日志输出,但如果真发生 CRITICAL 级错误,Scapy 可能无法正常工作——因此该设置适合对输出有洁癖的稳定脚本,调试期建议保留WARNING甚至INFO

用 add-on 扩展 Scapy:自定义协议与 interact()

当你需要新增协议、函数等任何内容时,直接写进 Scapy 源码当然可以,但官方文档明确不推荐这种方式:"But this is not very convenient. Even if those modifications are to be integrated into Scapy, it can be more convenient to write them in a separate file." 更优雅的做法是写成独立文件:

  1. 编写包含自定义内容(协议类、辅助函数等)的 Python 文件;
  2. 让该文件可执行,并在if __name__ == "__main__":分支中调用 Scapy 的interact()函数,把自定义命名空间与自定义 banner 注入交互式会话。

官方文档给出的完整 add-on 示例:

#! /usr/bin/env python # Set log level to benefit from Scapy warnings import logging logger = logging.getLogger("scapy") logger.setLevel(logging.INFO) from scapy.all import * class Test(Packet): name = "Test packet" fields_desc = [ShortField("test1", 1), ShortField("test2", 2)] def make_test(x, y): return Ether() / IP() / Test(test1=x, test2=y) if __name__ == "__main__": interact(mydict=globals(), mybanner="Test add-on v3.14")

自定义协议类的结构

Test继承自Packet基类(scapy/packet.py#L82),核心组成:

  • name:协议的人类可读名称,显示在show()等输出中;
  • fields_desc:字段描述列表,定义了该包的二进制布局。这里使用两个ShortField(16 位短整数),字段名分别为test1(默认值 1)与test2(默认值 2)。ShortField等基础字段类定义在 scapy/fields.py(例如 scapy/fields.py#L1319),同族还包括ByteField(scapy/fields.py#L1062)、IntField(scapy/fields.py#L1349)等,可按需组合出不同的包结构。

interact() 如何把自定义内容注入会话

interact()定义于 scapy/main.py#L648,签名如下:

def interact(mydict=None, argv=None, mybanner=None, mybanneronly=False, loglevel=logging.INFO):

其工作流程(对应 scapy/main.py 的实现)可以概括为:

  1. 进入交互模式:设置conf.interactive = True、加载默认主题(scapy/main.py#L661-L663),并将conf.logLevel设为传入的loglevel(默认logging.INFO,这与交互模式下默认 INFO 级别的行为一致);
  2. 解析命令行选项:支持-h(帮助)、-H(无花哨 banner)、-c/-C(自定义/禁用启动文件)、-p/-P(自定义/禁用预启动文件)、-d(降低日志级别)等参数(scapy/main.py#L674-L691);
  3. 注入自定义命名空间:调用init_session(mydict=mydict, ret=True)(scapy/main.py#L713)。在 scapy/main.py#L530-L532 可以看到,mydict中的键值会被更新进scapy_session,因此你在 add-on 中通过globals()传入的自定义类(Test)和函数(make_test)都会成为交互控制台中的可用名字;
  4. 拼接自定义 banner:当mybanner非空时,会追加到默认 banner 之后;若同时设置mybanneronly=True,则默认 banner 被清空、只显示你的自定义 banner(scapy/main.py#L857-L861);
  5. 选择交互式 shell:根据conf.interactive_shell(可选ipythonbpythonptpythonptipythonpythonauto)启动对应的解释器,默认auto模式下依次探测 IPython → bpython → ptpython,都不存在时回退到标准 Python shell(scapy/main.py#L741-L778)。

运行效果

把上面的代码保存为test_interact.py并赋予可执行权限后运行,会得到官方文档所示的输出:

# ./test_interact.py Welcome to Scapy (0.9.17.109beta) Test add-on v3.14 >>> make_test(42,666) <Ether type=0x800 |<IP |<Test test1=42 test2=666 |>>>

可以看到:默认 banner 之后紧跟着自定义 banner "Test add-on v3.14";make_test(42, 666)直接可用,返回的是Ether/IP/Test三层叠放的包对象,test1=42test2=666正是传入的自定义字段值。这样,你就拥有一个带个人定制协议的交互式 Scapy 环境,无需改动 Scapy 任何源码。

小结与进一步探索

本文覆盖了官方文档 doc/scapy/extending.rst 的全部核心内容:作为库嵌入脚本(ICMP 探测、ARP ping + LaTeX 输出、ARP 监控回调)、日志级别控制(logging.getLogger("scapy").setLevel(...)conf.verb)、以及以 add-on 方式扩展(自定义Packet子类 +interact(mydict=globals(), mybanner=...))。这些能力相互独立又可自由组合——例如你可以在自动化脚本中conf.verb = 0保持输出干净,也可以把调试期日志设为INFO借助频率过滤器观察告警。

如果你想深入底层,建议继续阅读:

  • scapy/packet.py:Packet基类与/组合操作符的构造与解析机制;
  • scapy/sendrecv.py:sr1srpsniff等收发与抓包函数的完整实现;
  • scapy/fields.py:ByteFieldShortFieldIntField等字段类家族,是自定义协议布局的基础;
  • scapy/main.py:interact()init_session()与启动文件(startup file)机制的完整实现;
  • scapy/config.py:conf全局配置,包括verblogLevelinteractive等开关的默认值。
  • 网络
  • 网络安全

【免费下载链接】scapy

Scapy: the Python-based interactive packet manipulation program & library.

项目地址:https://gitcode.com/gh_mirrors/sc/scapy
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 1:38:37

Java汽车推荐系统实战:Spring Boot+Redis+MySQL构建数据驱动闭环

简介&#xff1a;本资源是一套面向计算机专业本科生的Java毕业设计实战项目——个性化汽车推荐系统&#xff0c;聚焦推荐算法工程化落地&#xff0c;适用于软件开发、数据挖掘与智能系统方向的学习与课程设计。项目采用Spring BootMyBatis技术栈构建后端服务&#xff0c;前端基…

作者头像 李华
网站建设 2026/9/23 1:37:57

Forest Pack 7 植被分布系统原理与工业级配置指南

简介&#xff1a;本资源是Forest Pack 7官方帮助文档PDF&#xff0c;面向3ds Max中高级用户、建筑可视化设计师、游戏场景美术师及影视特效从业者&#xff0c;解决大规模自然与城市环境建模中树木、植物、岩石、人群等对象高效散布与真实渲染的核心难题。文档共1个PDF文件&…

作者头像 李华
网站建设 2026/9/23 1:37:07

Flet flet-video 的 VideoSpacer 控件栏弹性间隔布局指南

前端跨平台桌面应用移动开发 【免费下载链接】flet Build realtime web, mobile and desktop apps in Python only. No frontend experience required. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/fl/flet 点击查看 免费下载 导读 VideoSpacer 是 Flet 官方视频扩…

作者头像 李华