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

2022-02-01 12:14:08 字數 3601 閱讀 8393

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

首先來捕獲第乙個包

#

coding:utf-8

import

socket

#監聽的主機ip

host = "

192.168.1.100

"socket_protocol =socket.ipproto_icmp

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

sniffer.bind((host, 0))

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

raw_buffer = sniffer.recvfrom(65535)

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兩個庫實現這一點。

#

coding:utf-8

import

socket

import

struct

from ctypes import *

#監聽的主機ip

host = "192.168.1.100"

#ip頭定義

class

ip(structure):

_fields_ =[

("ihl

", c_ubyte, 4),

("version

", c_ubyte, 4),

("tos

", c_ubyte),

("len

", c_ushort),

("id

", c_ushort),

("offset

", c_ushort),

("ttl

", c_ubyte),

("protocol_num

", c_ubyte),

("sum

", c_ushort),

("src

", c_uint),

("dst

", c_uint),

]def__new__(self, socket_buffer=none):

return

self.from_buffer_copy(socket_buffer)

def__init__(self, socket_buffer=none):

self.protocol_map =

#readable ip address

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

", self.src))

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

", self.dst))

#type of protocol

try:

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

except

: self.protocol =str(self.protocol_num)

socket_protocol =socket.ipproto_icmp

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

sniffer.bind((host, 0))

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

try:

while

true:

raw_buffer = sniffer.recvfrom(65535)[0]

ip_header = ip(raw_buffer[:20])

print

"protocol: %s %s -> %s

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

except

keyboardinterrupt:

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 address

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

", self.src))

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

", self.dst))

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

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

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

10. 然後列印。

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

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

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

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

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 而這些資料報都是由系統提供的協議棧實現,使用者只需要填充應用層報文即可,由系統完成底層報文頭的填充並傳送。然而在某些情況下需...