scapy 读包能补什么
scapy 是 Python 的报文构造与解析库,读包时把每帧解析成带层次的对象。当 tshark 的过滤与统计字段表达不了你要的口径时——比如按自定义键分组、跨协议做关联、按业务规则判重——写几十行脚本反而比拼命令行更快。它适合一次性分析任务,不适合当作常规采集工具。
基本信息
| 语言与安装 | Python 3,pip install scapy(解析 pcap 需要 libpcap) |
|---|---|
| 整体读取 | rdpcap 把文件读成报文列表,适合中小文件 |
| 流式读取 | PcapReader 逐帧迭代,内存占用与文件大小无关 |
| 写回文件 | wrpcap 把报文列表写回 pcap,便于裁剪样本 |
| 常用字段 | p[IP].src、p[TCP].dport、p[TCP].flags、p.time 等 |
| 兼容性 | pcapng 需对应的读取器,或先转成 pcap 再读 |
典型使用场景
- 自定义统计口径:按源目网段、按业务标识分组统计次数与字节,出 tshark 给不了的报表
- 跨协议关联:把某个请求的应答时间戳与前一层的连接事件对起来做端到端耗时
- 样本构造:从大文件里挑出符合特征的报文子集另存,做成固定回归样本
- 字段体检:批量检查某字段是否存在异常值,如端口为 0、TTL 为 0 的畸形包
- 教学演示:用几行代码把报文层次打印出来,直观说明封装关系
读包与统计示例
读包与统计示例
from scapy.all import PcapReader, TCP, IP
count = 0
ports = {}
with PcapReader('a.pcap') as pr: # 流式读取,避免一次性载入
for p in pr:
if IP in p and TCP in p and p[TCP].dport == 443: # 先判层再取字段
count += 1
ports[p[IP].src] = ports.get(p[IP].src, 0) + 1
print('443 目标包数:', count) # 与 tshark 口径交叉验证
print('发起端分布:', sorted(ports.items(), key=lambda kv: -kv[1])[:5])常用接口速查
| 接口 | 作用 | 提示 |
|---|---|---|
| rdpcap | 整文件读入列表 | 大文件会占用大量内存 |
| PcapReader | 逐帧迭代 | 推荐用于大文件 |
| wrpcap | 写出 pcap | 仅写出的报文会被重新序列化 |
| p.time | 报文时间戳 | 浮点秒,可自行做时间差 |
| p.summary | 单行摘要 | 适合快速打印排错 |
| haslayer | 判断是否含某层 | 截断包可能缺层,先判断再取值 |
自写脚本容易被当成权威口径,出结论前先用同一个过滤条件跑一遍 tshark 交叉核对数字,两边对得上再往上报。
抓包时设置过 snaplen 的文件里,超出截断长度的报文会缺少应用层字段,脚本必须对字段缺失做判断,否则会抛出异常或统计出偏小的数字。