pyshark使用技巧小结

  |  

PyShark 是一个Python库,它提供了一个方便的接口来使用Wireshark的命令行工具tshark进行包解析。它是基于Wireshark开发的,,你可以直接在Python中利用Wireshark强大的解析器处理捕获文件或实时数据流。但是网上对使用pyshark来分析http流量的说明文章太少,于是手动记录下。

pyshark的基础使用

1. 安装

1‑1. 先确保你已安装 Wireshark / tshark

1
2
3
4
5
6
7
8
# Debian/Ubuntu
sudo apt-get install wireshark tshark

# macOS (Homebrew)
brew install wireshark

# Windows
# 下载并安装 Wireshark,勾选 “tshark” 组件即可

注意:在 Linux 上,你可能需要把当前用户加入 wireshark 组或使用 sudo 执行 tshark。

1‑2. 安装 PyShark

1
pip install pyshark

如果你想要支持更高版本的 tshark,建议先更新 Wireshark,然后再安装/升级 pyshark。


2. 基本概念

对象 含义
FileCapture 从已有 .pcap/.pcapng 文件读取包
LiveCapture 在指定网络接口上实时捕获包
Packet 单个协议帧/数据包/数据报,提供访问字段的方法
Layer 协议层(Ethernet、IP、TCP 等),可通过属性或字典方式访问

3.基本使用

FileCaptureLiveCapture的读取方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import pyshark
from pathlib import Path

pcap_path = Path(r"att.pcapng")

# ① 检查文件是否存在
if not pcap_path.is_file():
raise FileNotFoundError(f"File {pcap_path} does not exist.")

# ②-1 创建捕获实例,使用 keep_packets=False 减少内存占用
capture = pyshark.FileCapture(
str(pcap_path),
keep_packets=False, # 不缓存已读取的包
display_filter='ip', # 只解析 IP 包(可根据需求调整)
)
##PS:从网卡中直接读取流量包
#capture 2 = pyshark.LiveCapture(interface='en0', display_filter="tcp.analysis.retransmission")

# ③ 遍历并安全访问字段
for pkt in capture:
try:
src_ip = pkt.ip.src #获得原地址
dst_ip = pkt.ip.dst #获得目的地址
protocol = pkt.transport_layer or 'Unknown' #传输层协议
print(f"Packet: {protocol} from {src_ip} to {dst_ip}")
except AttributeError as e:
# 该包没有 IP 层,或者某字段缺失
continue

# ④ 关闭资源(可选,因为捕获对象会在 GC 时自动关闭)
capture.close()

​ 代码说明,通过pyshark.FileCapturepyshark.LiveCapture 获得的 capture的变量是一个FileCapture对象,我们可以里理解为被pyshark的流量包文件对象。而代码中pkt变量是一个Packet对象可以理解为流量包文件每一个的每一个流量包。而流量包的读取顺序则是和 Wireshark中No.的顺序是相似的(在通过 display_filter过滤后流量包的读取顺序再用索引下标读取的话pyshark会对流量包重新排序)。

​ 而且pyshark.FileCapturepyshark.LiveCapture 通常情况下我们只需要input_file指定文件或interface指定对应网卡,就可以分析到流量包。但为了分析方便开发者加了扩展参数来自进行分析,我对pyshark.FileCapturepyshark.LiveCapture 的常见的参数/扩展参数总结如下:

参数 作用 默认值 使用建议 / 注意事项
keep_packets 是否在读取后保留已读的包对象。
True → 内存中保存所有 Packet;False → 只返回一个包,随后被 GC 回收。
True 大文件(GB+)时建议设为 False,以防内存爆炸。
input_file 指定要读取的捕获文件或 XML
可直接传入路径字符串、Path 对象或已打开的文件句柄(io.BufferedReader)。
None (必须提供) 只在 FileCapture 中使用;若为文件句柄,tshark 会从当前位置开始读。
ring_file_size 循环文件大小(kB)
当使用 output_file 或开启循环写入时,tshark 会把抓到的包写成一系列 “环形” 文件。
1024 kB (1 MiB) 对高流量捕获建议增大;过小会导致文件频繁切换、磁盘 I/O 增加。
num_ring_files 循环文件数量
保留的文件数,tshark 会在此数目后循环覆盖旧文件。
1 典型场景:想把最近 5 MiB 数据保存下来,只需 num_ring_files=5
ring_file_name 循环文件基础名
实际写出的文件会以 <name>.0, <name>.1, … 命名。
/tmp/pyshark.pcap 在 Windows 建议改为 C:\\temp\\pyshark.pcap,避免路径中的斜杠被误解析。
interface 抓包的网卡名称
如果不指定,tshark 会自动选第一个可用接口。
第一个可用接口 对多网卡机器一定要明确写 interface='eth0' 或者 en0(macOS)。
bpf_filter BPF 过滤器(Berkeley Packet Filter)
在捕获层面就筛选掉不需要的包,速度快。
None 示例:bpf_filter='tcp port 80';注意:BPF 与 Wireshark 的显示过滤不同。
display_filter Wireshark 显示过滤(tshark 层面的 -Y
在解析后再筛选,功能更强大但开销较大。
None 示例:display_filter='http.request';如果你只需要 IP/TCP/UDP 信息,可把它留空或使用 BPF。
only_summaries 仅生成包摘要
不解析完整协议层,速度快且内存占用低。
False 对日志收集、流量计数非常合适;但无法获取字段值,只能拿到 pkt.summary
disable_protocol 禁用某个协议的检测(tshark > 2)
可加速解析,尤其是你知道不需要某些大协议时。
None 用法:disable_protocol='ssl';如果禁用了错误协议,后续访问会报错。
decryption_key 对加密流量进行解密
用于 Wi-Fi 或 VPN 等加密捕获。
None 需要对应 encryption_type;若未正确设置,tshark 会忽略此字段。
encryption_type 指定加密标准
必须是 'WEP', 'WPA-PWD', 或 'WPA-PWK'(默认 WPA-PWK)。
'WPA-PWK' decryption_key 配合使用;若不匹配,解密失败。
tshark_path tshark 可执行文件的完整路径
如果系统 PATH 中没有 tshark 或你想指定特定版本。
自动搜索 在 Windows 上常用:r'C:\Program Files\Wireshark\tshark.exe'
output_file 把抓到的数据写入文件(可与 ring_file_* 配合)
即使你不想保存,也可以把它设为 None 或省略。
None 若同时指定了 ring_file_name,tshark 会将数据写成环形;否则直接写一个普通 pcap 文件。

Packet对象

再说回Packet对象,一个Packet本质上就对应一个流量包,在pyshark中提供了如下基础方法:

  • layers: 获取数据包Packe所有的协议
  • get_multiple_layers(layer_name): 获取数据包中指定名称的多个层(例如,一个数据包中可能有多个IP层)
  • get_raw_packet(): 获取原始的字节数据包
  • highest_layer: 返回数据包的最高协议层(例如,应用层协议名称)
  • pretty_print(): 以美观的格式打印数据包详情
  • show(): 类似于 pretty_print(),用于显示数据包详情
  • sniff_time: 数据包被捕获的时间戳
  • transport_layer: 返回传输层协议(如TCP或UDP)

Layer对象

这样我们从Packet对象获得到Layer对象,Layer对象对应会根据协议的不同,给我们提供不同的方法。比如TCP Layer协议对象会给我们提供:

  • srcport: 源端口号
  • dstport: 目标端口号
  • port: 可能是源端口或目标端口(取决于上下文)
  • seq: 序列号(可能经过相对处理)
  • seq_raw: 原始序列号
  • ack: 确认号(可能经过相对处理)
  • ack_raw: 原始确认号
  • nxtseq: 下一个序列号
  • stream: TCP流索引(等同于Wireshark中的tcp.stream
  • checksum: 校验和
  • checksum_status: 校验和状态
  • len: TCP段长度
  • hdr_len: TCP头部长度
  • time_relative: 相对于第一个数据包的时间
  • time_delta: 与前一个数据包的时间差
  • analysis: 分析信息
  • completeness: 连接完整性状态

IP Layer 协议会给我们提供ipv4相关网络成相关的协议的方法(ps:如果是ipv6 则是IPV6 Layer ,在pyshark中这里有区分的):

  • src: 源IP地址
  • dst: 目标IP地址
  • addr: 可能是源或目标IP地址(取决于上下文)
  • dst_host: 目标主机地址
  • version: IP版本(通常是4或6)
  • hdr_len: IP头部长度
  • dsfield: 区分服务字段(DS Field)
  • dsfield_dscp: 差分服务代码点(DSCP)
  • dsfield_ecn: 显式拥塞通知(ECN)
  • len: IP数据包总长度
  • id: 标识字段(用于分片和重组)
  • flags: 标志位

pyshark分析http流量

同样pyshark的提供了HTTP Layer的方法来对http流量进行分析。常见的方法如下:

用途 属性方法 结果示例
请求方法 request_method GET, POST
完整 URI request_full_uri https://example.com/api?x=1
URI 片段 request_uri /api?x=1
HTTP 版本 request_version / response_version HTTP/1.1
状态码 response_code 200
响应文本 response_phrase OK
内容类型 content_type application/json
Cookie cookie_pair / set_cookie sessionid=abc123; ...

在抓取 HTTP 流量时,需要注意 请求包响应包 的区别。PyShark 在读取 HTTP 包时,只是粗略地保留了一些属性,并没有为它们做出专门的区分。因此,如果你在遍历包时对一个请求包使用了仅存在于响应包中的属性(例如 response_coderesponse_phrase),就会导致报错。

解决办法很简单:

  • 请求包 具有 request_method 属性;
  • 响应包 具有 response_code 属性。

先根据这两个标识判断包的类型,再使用对应的属性进行处理,就能避免错误。

另一个常见需求是提取 HTTP 包中的主体数据:

  • 对于请求包,获取的是请求体(body);
  • 对于响应包,获取的是返回体(body)。

在处理时同样需要先区分包类型,然后再调用相应的属性或方法来读取主体内容。

常见的方法是对读取file_data 来进行处理,但是file_data默认是十六进制的数据需要对数据进行处理。但file_data 默认是16进制字符,对于pkt[‘DATA-TEXT-LINES’]的layer来获得body内容,而且代码只需要如下小部分,但是pkt[‘DATA-TEXT-LINES’]一班只在返回包里存在:

1
2
3
if hasattr(pkt, 'DATA-TEXT-LINES'):
body = str(pkt['DATA-TEXT-LINES'])
print('data:\n'+(body))

最后,为了方便理解我写了一个安顺序遍历http流量的样例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python3
import pyshark
import urllib.parse, binascii
# ---------- 配置 ----------
PCAP_FILE = r"C:/Users/LEXS/Desktop/att.pcapng" # 你的 pcap 路径


# ---------- 读取流量包 ----------
caps = pyshark.FileCapture(PCAP_FILE,display_filter='http')


for pkt in caps:
# 1️⃣ 判断是请求还是响应
if hasattr(pkt.http, 'request_method'):
print("\n--- HTTP REQUEST ---")
print(f"Method : {pkt.http.request_method}")
print(f"URI : {pkt.http.request_uri}")
print(f"Version: {pkt.http.request_version}")
print(f"Host : {getattr(pkt.http, 'host', '<none>')}")
print(f"User‑Agent: {getattr(pkt.http, 'user_agent', '')}")
print(f"cookie: {getattr(pkt.http, 'cookie', '')}")
if hasattr(pkt.http, 'file_data'):
body = urllib.parse.unquote_plus(binascii.unhexlify(pkt.http.file_data.replace(":", "")).decode('utf-8'))
print('data:\n'+(body))


elif hasattr(pkt.http, 'response_code'): # 响应包
print("\n--- HTTP RESPONSE ---")
print(f"Status : {pkt.http.response_code} {pkt.http.response_phrase}")
print(f"Version: {pkt.http.response_version}")
print(f"Server : {getattr(pkt.http, 'server', '<none>')}")
if hasattr(pkt.http, 'file_data'):
body = urllib.parse.unquote_plus(binascii.unhexlify(pkt.http.file_data.replace(":", "")).decode('utf-8'))
print('data:\n'+(body))
文章目录
  1. pyshark的基础使用
    1. 1. 安装
      1. 1‑1. 先确保你已安装 Wireshark / tshark
      2. 1‑2. 安装 PyShark
    2. 2. 基本概念
    3. 3.基本使用
      1. FileCapture与LiveCapture的读取方法
      2. Packet对象
      3. Layer对象
  2. pyshark分析http流量
|