我是靠谱客的博主 专一耳机,最近开发中收集的这篇文章主要介绍 PyShark入门(4):packet对象,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

原文链接:http://zodiacg.net/2016/07/in...

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

目前在这一系列文章中我们已经了解了如何捕获数据包和使用 capture 对象,我们终于到了有趣的部分,开始对数据包进行操作了!

当我们捕获了数据包后,它们以 packet 对象列表的形式存储在 capture 对象中。这些 packet 对象的方法和属性使我们能够访问数据包头以及包的负载信息。在之前的文章中提到过,我们可以使用 only_summaries 参数来控制每个数据包保存的信息量。

数据包摘要属性

在捕获时将 only_summaries 设置为 True 会使得不管捕获的数据包的内容是何种协议, packet 对象都具有固定的属性集。其中最有用的属性值有:

>>> cap = pyshark.FileCapture('test.pcap', only_summaries=True)
>>>
>>> dir(cap[0])
['delta', 'destination', 'info', 'ip id', 'length', 'no', 'protocol', 'source', 'stream', 'summary_line', 'time', 'window']
  • delta : 当前数据包和上一个数据包捕获时间的差值。

  • destination : IP层的目标地址。

  • info :应用层数据的简短摘要(比如"HTTP GET /resource_folder/page.html")。

  • ip id : IP标识符字段。

  • length : 以字节表示的数据包长度。

  • no : 数据包在列表中的索引值。

  • protocol : 数据包中识别出的最高层级的协议。(译注:HTTP数据包如果是JSON的数据,此处可能是JSON而非HTTP)

  • source : IP层的源地址。

  • stream : 索引值,标识出该数据包属于哪一个TCP流(仅用于TCP数据包)。

  • summary_line : 将所有的摘要属性输出在一个tab分隔的字符串中。

  • time : 当前数据包到达时间与第一个数据包的差值。

  • window : TCP的窗口大小(仅用于TCP数据包)。

利用这些内容可以做很多事情,打印出数据包摘要只是一个开始!利用这些数据可以做出很棒的可视化图表来展示IP会话、带宽使用、协议以及应用的性能指标(比如TCP数据流中的RTT值)。这都是很有用的分析,还有别的吗?

完整的数据包属性

如果你不仅想从捕获的数据包中获取摘要信息,那么好好看看这部分吧。使用Wireshark和tshark内建的解析器,PyShark可以将数据包的所有细节按层次分解。
比如我们先来深入研究一下DNS数据包,看一下数据包所具有的属性。

>>> cap = pyshark.LiveCapture(interface='en0', bpf_filter='udp port 53')
>>> cap.sniff(packet_count=50)
>>> dns_1 = cap[0]
>>> dns_2 = cap[1]
>>> dns_1.
#(tab auto-complete)
dns_1.captured_length
dns_1.highest_layer
dns_1.length
dns_1.transport_layer
dns_1.dns
dns_1.interface_captured
dns_1.pretty_print
dns_1.udp
dns_1.eth
dns_1.ip
dns_1.sniff_time
dns_1.frame_info
dns_1.layers
dns_1.sniff_timestamp

这其中有一些普通的数据包信息属性,比如lengthframe_info,以及time,还有pretty_print()方法用于以可读性较强的方式显示数据包(类似于Wireshark的详细信息视图)。
如果你仔细看的话能够发现直接制定层次名的属性(ethip),还有会根据数据包内的协议而变动的属性(transport_layerhighest_layer)。
如果你要寻找特定类型的数据流量,这些属性可以使得寻找感兴趣的信息变得很简单。
比如下面的脚本会打印出所有的DNS查询和响应:

import pyshark
cap = pyshark.LiveCapture(interface='en0', bpf_filter='udp port 53')
cap.sniff(packet_count=10)
def print_dns_info(pkt):
if pkt.dns.qry_name:
print 'DNS Request from %s: %s' % (pkt.ip.src, pkt.dns.qry_name)
elif pkt.dns.resp_name:
print 'DNS Response from %s: %s' % (pkt.ip.src, pkt.dns.resp_name)
cap.apply_on_packets(print_dns_info, timeout=100)

会给出如下的结果:

DNS Request from 10.10.10.40: apple.com
DNS Request from 10.10.10.1: apple.com
DNS Request from 10.10.10.40: ipv6.icanhazip.com
DNS Request from 10.10.10.1: ipv6.icanhazip.com
DNS Request from 10.10.10.40: ipv4.icanhazip.com
DNS Request from 10.10.10.1: ipv4.icanhazip.com

动态的层引用

使用上面提到的动态变化的层属性(比如transport_layerhighest_layer)让我们在分析数据包时更灵活。
如果你对每个数据包都试图访问pkt.dns.qry_resp属性,那么如果这个数据包不是DNS数据包就会返回AttributeError异常。传输层也有类似的问题,因为有TCP和UDP两种可能。我们可以使用动态引用的层属性来获取源地址和目的地址,然后使用try/except来处理既不是TCP也不是UDP数据包的情况。

import pyshark
cap = pyshark.FileCapture('test.pcap')
def print_conversation_header(pkt):
try:
protocol =
pkt.transport_layer
src_addr = pkt.ip.src
src_port = pkt[pkt.transport_layer].srcport
dst_addr = pkt.ip.dst
dst_port = pkt[pkt.transport_layer].dstport
print '%s
%s:%s --> %s:%s' % (protocol, src_addr, src_port, dst_addr, dst_port)
except AttributeError as e:
#ignore packets that aren't TCP/UDP or IPv4
pass
cap.apply_on_packets(print_conversation_header, timeout=100)

该脚本会输出:

UDP
10.10.10.12:51554 --> 239.255.255.250:1900
UDP
10.10.10.12:51554 --> 239.255.255.250:1900
UDP
10.10.10.15:58803 --> 8.8.8.8:53
UDP
8.8.8.8:53 --> 10.10.10.15:58803
TCP
10.10.10.15:58632 --> 192.168.20.197:80
TCP
192.168.20.197:80 --> 10.10.10.15:58632
TCP
10.10.10.15:58632 --> 192.168.20.197:80

无限的可能

从这几个简单的例子当中我们可以看出,PyShark使我们能够轻松的访问所有的数据包细节。
在分类和处理多种不同协议的时候,可以使用条件语句来创造动态的逻辑,你也可以寻找具有特定属性的数据包来筛选特定类型的数据流量(当然要注意处理AttributeError)。

希望你喜欢这一系列文章。如果你对PyShark的应用实例感兴趣,你可以看看我的Cloud-Pcap项目


上一篇:PyShark入门(3):capture对象

最后

以上就是专一耳机为你收集整理的 PyShark入门(4):packet对象的全部内容,希望文章能够帮你解决 PyShark入门(4):packet对象所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部