pcap

最近花了點時間研究 PCAP 的檔案格式,試著把 PCAP 的 Parser 用 Python 寫出來,本來就只是單純練習而躍躍欲試後結果。

最終 lib 寫出來後就把這個 patch 送給 Ryu team 高興的是對方很快地就接受,並且跟我說這是個好東西。

為什麼 patch 到 Ryu Controller?

原因是後來想到有時候在 SDN Controller 上要開發 SDN Apps 因為某些原因需要把 Packet-In 的封包輸出來看,但是在 Controller 上直接把封包的內容直接輸出,顯示就只會看到一堆16進位的數值,還需要再透過各種方法把每種封包格式還原,實在是太傷神了。

或許你可能會嘗試用 Wireshark 去抓封包來看,這是一個不錯的方法,但是我接下來想跟大家分享的是直接在 application 上直接呼叫 ryu.lib.pcaplib 來用可以更快的方法直接的把封包儲存下來看!

怎麼使用?

  • 把 pcaplib import 近來
  • 利用 pcaplib.Writer() 生一個物件,並餵入寫檔物件 open('mypcap.pcap', 'wb')
  • 在有封包經過的 Handler 使用物件的 write_pkt method 並給予參數 msg.data

That’s it. 只需要上面三個步驟,就可以把封包存下來。唯一需要注意的是,通常會把它放在有封包經過的 Handler 可以參考以下的範例

pcapsave.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from ryu.lib import pcaplib

class SimpleSwitch13(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

def __init__(self, *args, **kwargs):
super(SimpleSwitch13, self).__init__(*args, **kwargs)
self.mac_to_port = {}
self.pcap_pen = pcaplib.Writer(open('mypcap.pcap', 'wb'))
# Creating an instance with a PCAP filename
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
msg = ev.msg
self.pcap_pen.write_pkt(msg.data)
# Dump the data packet into PCAP file

另外還有提供讀取 PCAP 的 Class 如果需要的話可以參考以下的範例

pcapread.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from ryu.lib import pcaplib
from ryu.lib.packet import packet

frame_count = 0
for ts, buf in pcaplib.Reader(open('test.pcap', 'rb')):
# Using the Reader iterator that yields packets in PCAP file
frame_count += 1
pkt = packet.Packet(buf)

eth = pkt.get_protocols(ethernet.ethernet)[0]

dst = eth.dst
src = eth.src

print frame_count, ts, dst, src, pkt
# print frames count, timestamp, ethernet src, ethernet dst and raw packet.

Python 目前在第三方套件支援 PCAP 的 Parser 算是少的,只有一個還不錯用的 dpkt 函式庫,但是看上去好像沒在維護了?