本系列文章译自thePacketGeek的系列文章。原创翻译,转载请注明出处。

PyShark中进行数据包分析的两个典型方法是使用 FileCaptureLiveCapture 模块。
前者从一个存储的捕获文件中导入u数据包,后者将使用本机的网络接口进行嗅探。
使用这两个模块都会返回一个 capture 对象。之后的文章中会详细介绍。
我们首先来了解一下这两个模块如何使用。

两个模块提供相似的参数来控制 capture 对象中返回的数据包。下面的定义直接从模块的docstring中获取:

  • interface: [仅用于LiveCapture] 进行嗅探的网络接口。如果没有给出,使用可用的第一个接口。
  • bpf_filter: [仅用于LiveCapture] 在嗅探时使用的BPF(tcpdump)过滤条件。
  • input_file: [仅用于FileCapture] 保存的捕获文件的路径(PCAP, PCAPNG格式)。
  • keep_packets: 设定在调用next()函数之后是否保留之前读取的数据包。用于在读取较大的捕获时节省内存。
  • display_filter: 设定在读取捕获时使用的display过滤条件(即Wireshark过滤器)。
  • only_summaries: 仅产生数据包摘要,比正常读取速度快的多,但包含信息很少。
  • decryption_key: 可选的用于加密解密捕获的流量的密钥。
  • encryption_type: 捕获的数据流量所使用的加密标准(必须是WEP,WPA-PWD或WPA-PWK中之一,默认是WPA-PWK)。

only_summaries选项

使用 only_summaries 后,返回的 capture 对象中的数据包将只包含摘要信息,类似于tshark的默认输出:

1
2
3
>>> cap = pyshark.FileCapture('test.pcap', only_summaries=True)
>>> print cap[0]
2 0.512323 0.512323 fe80::f141:48a9:9a2c:73e5 ff02::c SSDP 208 M-SEARCH * HTTP/

使用这个选项,读取捕获文件将变得很快,但每个数据包将只包含下面的这些属性。如果你想获取嗅探中的IP地址来构建会话列表,或者使用时间和包长度来计算带宽的统计数据,那么这些信息也足够了。

1
2
3
4
>>> pkt.     #(tab auto-complete)
pkt.delta pkt.info pkt.no pkt.stream pkt.window
pkt.destination pkt.ip id pkt.protocol pkt.summary_line
pkt.host pkt.length pkt.source pkt.time

keep_packets选项

PyShark只会在要对数据包进行处理的时候才会将其读入内存。在你处理数据包的过程中,PyShark会将每个数据包添加到 capture 对象中叫 _packet 的列表属性的末尾。当处理大量的数据包时,这个列表将占用大量的内存,因此PyShark提供了这个选项使得内存中一次仅保留一个数据包。如果 keep_packets 设置为False(默认为True),PyShark在读取新数据包时会将上一个从内存中清除。我发现这样能提升一点数据包遍历处理的速度,提升一点也是好的!

display_filter和bpf_filter

这些过滤器有助于使你的应用集中精力于你想要分析的内容上。类似于使用Wireshark或者tshark进行嗅探,BPF过滤器可以用于确定进入到返回的 capture 对象中的流量。
BPF过滤器的灵活性不如Wireshark的display过滤器,但是你仍可以创造性的使用这些有限的关键字和偏移过滤器。
如果需要对使用BPF过滤器更详细的说明,参考Wireshark的官方文档
下面是一个使用BPF过滤器嗅探目标HTTP流量的例子:

1
2
3
4
5
6
>>> cap = pyshark.LiveCapture(interface='en0', bpf_filter='ip and tcp port 80')
>>> cap.sniff(timeout=5)
>>> cap
<LiveCapture (21 packets)>
>>> print cap[5].highest_layer
HTTP

在读取保存的捕获文件时,你可以通过设置 display_filter 选项,利用Wireshark强大的解析器来限制返回的数据包。
下面是没有使用过滤器的情况下,我的test.pcap文件中的前几个数据包:

1
2
3
4
5
6
7
8
9
10
>>> cap = pyshark.FileCapture('test.pcap')
>>> for pkt in cap:
...: print pkt.highest_layer
...:
HTTP
HTTP
HTTP
TCP
HTTP
... (truncated)

使用了display过滤器来限制只显示DNS数据流量:

1
2
3
4
5
6
7
8
9
10
>>> cap = pyshark.FileCapture('test.pcap', display_filter="dns")
>>> for pkt in cap:
...: print pkt.highest_layer
...:
DNS
DNS
DNS
DNS
DNS
... (truncated)

针对LiveCapture的附加说明

在遍历 LiveCapture 返回的 capture 对象时我发现了一个奇怪的现象。似乎当你试图遍历数据包列表时,它会从头开始进行嗅探,然后实时的进行遍历(来一个数据包就进行一次遍历)。我目前没有发现能够存储下数据包的方法,LiveCapture 仅能用于实时处理数据包。


上一篇:PyShark入门(1):简介
下一篇:PyShark入门(3):capture对象