python使用原始套接字 解析原始ip頭資料

2021-09-07 09:32:42 字數 3853 閱讀 7852

使用底層套接字解碼底層流量,是這次做的重點工作。

首先來捕獲第乙個包

1

#coding:utf-8import socket23

#監聽的主機ip

4 host = "

192.168.1.100"5

6 socket_protocol =socket.ipproto_icmp

78 sniffer =socket.socket(socket.af_inet, socket.sock_raw, socket_protocol)

9sniffer.bind((host, 0))

10 sniffer.setsockopt(socket.ipproto_ip, socket.ip_hdrincl, 1)

1112 raw_buffer = sniffer.recvfrom(65535)

13print 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

2import

struct

3from ctypes import *45

#監聽的主機iphost = "192.168.1.100"67

#ip頭定義

8class

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]

2223

def__new__(self, socket_buffer=none):

24return

self.from_buffer_copy(socket_buffer)

2526

def__init__(self, socket_buffer=none):

27 self.protocol_map =

2829

#readable ip address

30 self.src_address = socket.inet_ntoa(struct.pack("

", self.src))

31 self.dst_address = socket.inet_ntoa(struct.pack("

", self.dst))

3233

#type of protocol

34try

:35 self.protocol =self.protocol_map[self.protocol_num]

36except

:37 self.protocol =str(self.protocol_num)

3839 socket_protocol =socket.ipproto_icmp

4041 sniffer =socket.socket(socket.af_inet, socket.sock_raw, socket_protocol)

42sniffer.bind((host, 0))

43 sniffer.setsockopt(socket.ipproto_ip, socket.ip_hdrincl, 1)

4445

try:

46while

true:

47 raw_buffer = sniffer.recvfrom(65535)[0]

4849 ip_header = ip(raw_buffer[:20])

5051

print

"protocol: %s %s -> %s

" %(ip_header.protocol, ip_header.src_address, ip_header.dst_address)

5253

except

keyboardinterrupt:

54pass

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 address

self.src_address = socket.inet_ntoa(struct.pack("7. 乙個接收icmp包的伺服器,沒什麼說的。

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

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

10. 然後列印。

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

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

python使用原始套接字 解析原始ip頭資料

使用底層套接字解碼底層流量,是這次做的重點工作。首先來捕獲第乙個包 coding utf 8 import socket 監聽的主機ip host 192.168.1.100 socket protocol socket.ipproto icmp sniffer socket.socket sock...

python使用原始套接字 解析原始ip頭資料

使用底層套接字解碼底層流量,是這次做的重點工作。首先來捕獲第乙個包 coding utf 8 import socket 監聽的主機ip host 192.168.1.100 socket protocol socket.ipproto icmp sniffer socket.socket sock...

原始套接字

資料出處 實際上,我們常用的網路程式設計都是在應用層的報文的收發操作,也就是大多數程式設計師接觸到的流式套接字 sock stream 和資料報式套接字 sock dgram 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需...