原文连接:http://zodiacg.net/2016/07/in...html
本系列文章译自thePacketGeek的系列文章。原创翻译,转载请注明出处。python
目前在这一系列文章中咱们已经了解了如何捕获数据包和使用 capture 对象,咱们终于到了有趣的部分,开始对数据包进行操做了!git
当咱们捕获了数据包后,它们以 packet 对象列表的形式存储在 capture 对象中。这些 packet 对象的方法和属性使咱们可以访问数据包头以及包的负载信息。在以前的文章中提到过,咱们能够使用 only_summaries 参数来控制每一个数据包保存的信息量。github
在捕获时将 only_summaries 设置为 True 会使得无论捕获的数据包的内容是何种协议, packet 对象都具备固定的属性集。其中最有用的属性值有:app
>>> 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层的目标地址。.net
info :应用层数据的简短摘要(好比"HTTP GET /resource_folder/page.html")。翻译
ip id : IP标识符字段。code
length : 以字节表示的数据包长度。htm
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
这其中有一些普通的数据包信息属性,好比length
,frame_info
,以及time
,还有pretty_print()
方法用于以可读性较强的方式显示数据包(相似于Wireshark的详细信息视图)。
若是你仔细看的话可以发现直接制定层次名的属性(eth
和ip
),还有会根据数据包内的协议而变更的属性(transport_layer
和highest_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_layer
和highest_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项目