原文連接: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項目