python使用原始通訊端 解析原始ip頭資料

來源:互聯網
上載者:User

標籤:while   一點   net   port   並且   version   try   pass   read   

使用底層通訊端解碼底層流量,是這次做的重點工作。

 

首先來捕獲第一個包

 1 # coding:utf-8import socket 2  3 # 監聽的主機IP 4 host = "192.168.1.100" 5  6 socket_protocol = socket.IPPROTO_ICMP 7  8 sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 9 sniffer.bind((host, 0))10 sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)11 12 raw_buffer = sniffer.recvfrom(65535)13 print raw_buffer

下面一行一行解釋上面代碼的意思。

1. 匯入socket包

2. 需要監聽的本機ip地址

3. 給socket_protocol變數賦值icmp變數

4. 為sniffer變數建立一個soket對象,該對象為ipv4 原始通訊端並指定其協議為icmp

5. 綁定到指定地址和連接埠進行監聽

6. 為sniffer通訊端設定選項參數,使其攜帶ip頭

7. 將監聽連接埠的通訊端收到的未經處理資料賦值給raw_buffer

8. 列印raw_buffer的值

這個時候,我們使用root許可權運行這個指令碼,並且開啟另外一個terminal對任意一個地址發送icmp包,我們監聽的介面的recvfrom 會收到回監聽回包到指定地址。recvfrom與recv不同的是 recvfrom會同時接收回包地址。(string, address)的格式

 

這個時候我們可以看到列印出來的值,是一堆完全看不懂的東西,因為是沒有解碼的狀態,下面我們將對ip頭進行解碼。

使用python的struct和ctypes兩個庫實現這一點。

 

 1 # coding:utf-8import socket 2 import struct 3 from ctypes import * 4  5 # 監聽的主機IPhost = "192.168.1.100" 6  7 # IP頭定義 8 class IP(Structure): 9     _fields_ = [10         ("ihl",             c_ubyte, 4),11         ("version",         c_ubyte, 4),12         ("tos",             c_ubyte),13         ("len",             c_ushort),14         ("id",              c_ushort),15         ("offset",          c_ushort),16         ("ttl",             c_ubyte),17         ("protocol_num",    c_ubyte),18         ("sum",             c_ushort),19         ("src",             c_uint),20         ("dst",             c_uint),21     ]22 23     def __new__(self, socket_buffer=None):24         return self.from_buffer_copy(socket_buffer)25 26     def __init__(self, socket_buffer=None):27         self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}28 29         # readable ip address30         self.src_address = socket.inet_ntoa(struct.pack("<I", self.src))31         self.dst_address = socket.inet_ntoa(struct.pack("<I", self.dst))32 33         # type of protocol34         try:35             self.protocol = self.protocol_map[self.protocol_num]36         except:37             self.protocol = str(self.protocol_num)38 39 socket_protocol = socket.IPPROTO_ICMP40 41 sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)42 sniffer.bind((host, 0))43 sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)44 45 try:46     while True:47         raw_buffer = sniffer.recvfrom(65535)[0]48 49         ip_header = IP(raw_buffer[:20])50 51         print "Protocol: %s %s -> %s " % (ip_header.protocol, ip_header.src_address, ip_header.dst_address)52 53 except KeyboardInterrupt:54     pass

 

1. 匯入各模組

2. 監聽的本機ip地址

3. 使用ctypes 構造一個解析ip頭的結構體(structure) IP

4. 使用from_buffer_copy方法在__new__方法將收到的資料產生一個IP class的執行個體

5. __init__方法初始化一部分資料儲存到對應的執行個體屬性值中。

6. 特別說明下面代碼, 使用了python struct庫的pack方法 用指定的格式化參數將src 和dst的long型數值轉換為字串,然後使用socket.inet_ntoa方法將字串的一串數字轉換為對應的ip格式。最後賦值給對應的src或者dst變數

# readable ip addressself.src_address = socket.inet_ntoa(struct.pack("<I", self.src))self.dst_address = socket.inet_ntoa(struct.pack("<I", self.dst))

7. 一個接收icmp包的伺服器,沒什麼說的。

8. 無限迴圈監聽指定連接埠,將recvfrom收到的資料的第一部分 也就是不要ip地址的部分傳遞給raw_buffer

9. ip頭raw_buffer的前20個位元組傳遞給結構體進行解碼。

10. 然後列印。

 

可以看到大致思路就是,將原型socket資料拿過來,然後通過類比c語言的結構體,使用python的庫對這個格式的包進行一一對應的解碼,將解碼之後的資料列印出來。

到此為止可以看到,在ip層已經可以解析出資料包從哪兒去哪兒的資訊。

python使用原始通訊端 解析原始ip頭資料

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.