2020-06-29 04:31 PM 2020-06-29 04:34 PM 更新
Scapy は Python で書かれたパケット操作ツールで、パケットの作成やキャプチャ・デコードをしたりすることができます。本記事では、モバイルパケットコアで使用されている GTP や PFCP への適用方法を見ていきたいと思います。Scapy を使用することにより大量のパケットデータを自動的に解析するといったことが可能になります。
インストールは簡単なので、詳細は以下のサイトを参照してください。
https://github.com/secdev/scapy
基本的なステップは以下のとおりです。
$ git clone https://github.com/secdev/scapy.git $ cd scapy $ sudo python setup.py install
GTP や PFCP の解析に必要なライブラリは scapy/contrib 配下にあります。
❯ ls scapy/contrib/ | grep -E "gtp|pfcp" gtp.py gtp_v2.py pfcp.py
まずは Python のインタラクティブシェルを使ってパケットをデコードしてみたいと思います。
❯ ./run_scapy INFO: Can't import matplotlib. Won't be able to plot. INFO: Can't import PyX. Won't be able to use psdump() or pdfdump(). INFO: Can't import python-cryptography v1.7+. Disabled WEP decryption/encryption. (Dot11) INFO: Can't import python-cryptography v1.7+. Disabled IPsec encryption/authentication. aSPY//YASa apyyyyCY//////////YCa | sY//////YSpcs scpCY//Pp | Welcome to Scapy ayp ayyyyyyySCP//Pp syY//C | Version 2.4.3.dev699 AYAsAYYYYYYYY///Ps cY//S | pCCCCY//p cSSps y//Y | https://github.com/secdev/scapy SPPPP///a pP///AC//Y | A//A cyP////C | Have fun! p///Ac sC///a | P////YCpc A//A | To craft a packet, you have to be a scccccp///pSP///p p//Y | packet, and learn how to swim in sY/////////y caa S//P | the wires and in the waves. cayCyayP//Ya pY/Ya | -- Jean-Claude Van Damme sY/PsY////YCc aC//Yp | sc sccaCY//PCypaapyCP//YSs spCPY//////YPSps ccaacs using IPython 7.9.0 >>> pkts = rdpcap("../s5.pcap") >>> pkts.summary() Ether / IP / UDP 192.168.3.1:30016 > 192.168.3.2:gtp_control / Raw Ether / IP / UDP 192.168.3.2:gtp_control > 192.168.3.1:30016 / Raw Ether / IP / UDP 192.168.3.1:30016 > 192.168.3.3:gtp_control / Raw Ether / IP / UDP 192.168.3.3:gtp_control > 192.168.3.1:30016 / Raw Ether / IP / UDP 192.168.3.3:gtp_control > 192.168.3.1:gtp_control / Raw Ether / IP / UDP 192.168.3.1:gtp_control > 192.168.3.3:gtp_control / Raw
s5.pcap は GTPv2 パケットを含む PCAP ファイルですが、デフォルトの状態では Raw を表示され正しくデコードされていません。GTP パケットをデコードするためには、scapy.contrib.gtp を import する必要があります。
>>> from scapy.contrib.gtp import * >>> pkts = rdpcap("../s5.pcap") >>> pkts.summary() Ether / IP / UDP 192.168.3.1:30016 > 192.168.3.2:gtp_control / GTPHeader / GTPV2CreateSessionRequest Ether / IP / UDP 192.168.3.2:gtp_control > 192.168.3.1:30016 / GTPHeader / GTPV2CreateSessionResponse Ether / IP / UDP 192.168.3.1:30016 > 192.168.3.3:gtp_control / GTPHeader / GTPV2CreateSessionRequest Ether / IP / UDP 192.168.3.3:gtp_control > 192.168.3.1:30016 / GTPHeader / GTPV2CreateSessionResponse Ether / IP / UDP 192.168.3.3:gtp_control > 192.168.3.1:gtp_control / GTPHeader / GTPV2CreateBearerRequest Ether / IP / UDP 192.168.3.1:gtp_control > 192.168.3.3:gtp_control / GTPHeader / GTPV2CreateBearerResponse
今度は GTP パケットの内容が正しくデコードされました。PFCP も同様に、scapy.contrib.pfcp を import するとデコードすることができます。
>>> from scapy.contrib.pfcp import * >>> pkts = rdpcap("../pfcp-sample.pcap") >>> pkts.summary() Ether / IPv6 / UDP 2001:10:1:200::1:8805 > 2001:10:1:200::101:8805 / PFCP / PFCPHeartbeatRequest Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:8805 / PFCP / PFCPHeartbeatResponse Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:8805 / PFCP / PFCPHeartbeatRequest Ether / IPv6 / UDP 2001:10:1:200::1:8805 > 2001:10:1:200::101:8805 / PFCP / PFCPHeartbeatResponse Ether / IPv6 / UDP 2001:10:1:200::1:50007 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionEstablishmentRequest Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50007 / PFCP / PFCPSessionEstablishmentResponse
これでデコードされたパケットの中身を見ることができます。pkts[17][PFCP] は、ファイル内の18番目のパケットの PFCP プロトコル・スタックにアクセスするということ意味しています。
>>> pkts[17].summary() 'Ether / IPv6 / UDP 2001:10:1:200::1:50007 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionEstablishmentRequest' >>> pkts[17][PFCP].show() ###[ PFCP (v1) Header ]### version= 1 spare_b2= 0x0 spare_b3= 0x0 spare_b4= 0x0 MP= 1 S= 1 message_type= session_establishment_request length= 887 seid= 0x0 seq= 1280 priority= 1 spare_p= 1 ###[ PFCP Session Establishment Request ]### \IE_list\ |###[ IE F-SEID ]### | ietype= F-SEID | length= 25 | spare= 0x0 | v4= 0 | v6= 1 | seid= 0x4000000000001 | ipv6= 2001:10:1:200::1 | extra_data= ''
--- 省略 ---
これでパケットに含まれる各データに簡単にアクセスできるようになりました。
>>> pkts[17][PFCP]["IE F-SEID"].seid 1125899906842625
一点注意事項として、PFCP 内の IE に一部 Cisco 独自の実装が使われているので、そのような IE は IE not implemented として表示されます。
| |###[ IE FAR ID ]### | | ietype= FAR ID | | length= 4 | | id= 32770 | | extra_data= '' | |###[ IE not implemented ]### | | ietype= 207 | | length= 9 | | data= 'internet\x00'
シンプルなものですが、PFCP パケットの summary と SEID を表示するコードを作成してみます。パケットが UDP かつ 8805 ポートを使用して、SEID を持っていれば summary と SEID を表示します。
#!/usr/bin/env python3 from scapy.all import * from scapy.contrib.pfcp import * import sys pcap_file = sys.argv[1] pkts= rdpcap(pcap_file) PFCP_PORT = 8805 for packet in pkts: if not packet.haslayer(UDP): continue if (packet[UDP].sport == PFCP_PORT) or (packet[UDP].dport == PFCP_PORT): if packet["PFCP (v1) Header"].seid != None: print(packet.summary() + " seid: %x" % packet[PFCP]["PFCP (v1) Header"].seid)実行結果
❯ ./show_pfcp.py ../pfcp-sample.pcap途中で新しいセッションになり SEID が変わった様子が確認できます。
Ether / IPv6 / UDP 2001:10:1:200::1:50007 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionEstablishmentRequest seid: 0
Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50007 / PFCP / PFCPSessionEstablishmentResponse seid: 4000000000001
Ether / IPv6 / UDP 2001:10:1:200::1:50007 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionModificationRequest seid: 14000000000001
Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50007 / PFCP / PFCPSessionModificationResponse seid: 4000000000001
Ether / IPv6 / UDP 2001:10:1:200::1:50007 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionModificationRequest seid: 14000000000001
Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50007 / PFCP / PFCPSessionModificationResponse seid: 4000000000001
Ether / IPv6 / UDP 2001:10:1:200::1:50007 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionModificationRequest seid: 14000000000001
Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50007 / PFCP / PFCPSessionModificationResponse seid: 4000000000001
Ether / IPv6 / UDP 2001:10:1:200::1:50007 > 2001:10:1:200::101:8805 / PFCP seid: 14000000000001
Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50007 / PFCP / PFCPSessionDeletionResponse seid: 4000000000001
Ether / IPv6 / UDP 2001:10:1:200::1:50014 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionEstablishmentRequest seid: 0
Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50014 / PFCP / PFCPSessionEstablishmentResponse seid: 8000000000003
Ether / IPv6 / UDP 2001:10:1:200::1:50014 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionModificationRequest seid: 10000000000000
Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50014 / PFCP / PFCPSessionModificationResponse seid: 8000000000003
Ether / IPv6 / UDP 2001:10:1:200::1:50014 > 2001:10:1:200::101:8805 / PFCP / PFCPSessionModificationRequest seid: 10000000000000
Ether / IPv6 / UDP 2001:10:1:200::101:8805 > 2001:10:1:200::1:50014 / PFCP / PFCPSessionModificationResponse seid: 8000000000003
検索バーにキーワード、フレーズ、または質問を入力し、お探しのものを見つけましょう
シスコ コミュニティをいち早く使いこなしていただけるよう役立つリンクをまとめました。みなさんのジャーニーがより良いものとなるようお手伝いします