2013-04-29 79 views
6

我會嘗試用簡單示例演示我的問題。Scapy無法在使用多線程時嗅探數據包

以下是一個非常簡單的(單線程)數據包嗅探器(ICMP):

from scapy.all import * 

m_iface = "wlan0" 
m_dst = "192.168.0.1" 

def print_summary(pkt): 
    print pkt.summary() 

def plain_sniff(): 
    sniff(iface = m_iface, count = 10, filter = "icmp and src {0}".format(m_dst), prn = print_summary) 

這種嗅探器工作得很好,我得到的輸出:

WARNING: No route found for IPv6 destination :: (no default route?) 
Ether/IP/ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0/Raw 
Ether/IP/ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0/Raw 
Ether/IP/ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0/Raw 
... 

接下來,我創建一個單獨的線程用於嗅探數據包並使用隊列在嗅探器線程和主線程之間傳送捕獲的數據包:

from threading import Thread 
from Queue import Queue, Empty 
from scapy.all import * 

m_iface = "wlan0" 
m_finished = False 
m_dst = "192.168.0.1" 

def print_summary(pkt): 
    print pkt.summary() 

def threaded_sniff_target(q): 
    global m_finished 
    sniff(iface = m_iface, count = 10, filter = "icmp and src {0}".format(m_dst), prn = lambda x : q.put(x)) 
    m_finished = True 

def threaded_sniff(): 
    q = Queue() 
    sniffer = Thread(target = threaded_sniff_target, args = (q,)) 
    sniffer.daemon = True 
    sniffer.start() 
    while (not m_finished): 
    try: 
     pkt = q.get(timeout = 1) 
     print_summary(pkt) 
    except Empty: 
     pass 

這個嗅探器也工作正常,我得到了與上面相同的輸出。然而,當我修改主線程只是一點點,以便它使用的send()功能從下面的數據包隊列中讀取之間:我下面的離奇輸出(過濾器似乎

def threaded_sniff_with_send(): 
    q = Queue() 
    sniffer = Thread(target = threaded_sniff_target, args = (q,)) 
    sniffer.daemon = True 
    sniffer.start() 
    while (not m_finished): 
    send(IP(dst = m_dst)/ICMP()) # Here 
    try: 
     pkt = q.get(timeout = 1) 
     print_summary(pkt) 
    except Empty: 
     pass 

然後拿到並不工作):

WARNING: No route found for IPv6 destination :: (no default route?) 
Sent 1 packets. 
Ether/ARP who has 192.168.0.1 says 192.168.0.9 
Sent 1 packets. 
Ether/ARP is at a0:21:b7:1a:7a:db says 192.168.0.1 
Sent 1 packets. 
Ether/IP/ICMP 192.168.0.9 > 192.168.0.1 echo-request 0 
Sent 1 packets. 
Ether/IP/ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0 
... 

三個嗅探器的腳本可以從here下載。

我的當前系統配置如下:

Python: 2.7.3 
Scapy: 2.2.0 
OS: Fedora 18 

有趣的是,所有三個監聽器正常工作我的舊計算機上:

Python: 2.6.4 
Scapy: 2.0.0.10 (beta) 
OS: Fedora 13 

首先,我想這可能是Scapy的/ Python版本。但即使在我的新電腦上安裝完全相同的版本,行爲仍然存在。

我不完全確定這是否是適合SO的問題(可能是Scapy的錯誤報告?)。在這種情況下請原諒我。

+0

看起來像一個已知的bug:http://trac.secdev.org/scapy/ticket/747 – 2013-05-01 04:03:24

+0

@ChathurangaChandrasekara:我面臨的問題與多線程有關。該代碼工作正常,無需線程。 – 2013-05-01 07:21:27

+0

@AsiriRathnayake這不會發生與網絡接口最終處於「Premiscious模式」並且只有一個源可以綁定到該接口的事實有關?如果沒有,你是否嘗試過使用python'threading'庫而不是隊列?我並不完全確定隊列系統是如何工作的,但是通過'線程',你至少可以控制什麼時候發生什麼,你可以稍微鼓掌一下。 – Torxed 2013-05-06 13:33:36

回答

6

這樣做的主要原因很可能是因爲資源鎖定。 Scapy的sniff()函數可能必須鎖定到低級網絡資源才能夠嗅探數據包。

延遲這兩個線程(在啓動嗅探器線程後),您將確保Scapy得到所需的時間。

要了解我們如何得出這一結論,請參閱上面的評論部分中的討論。 Gl Asiri Rathnayake :)

+0

謝謝你關注此事。這也解決了我原來的問題(這是一個更復雜的通信方案)。 Scapy的內部可能存在線程安全問題,希望Scapy的某個人能夠遇到這篇文章:) – 2013-05-07 08:13:48

+1

Yw。如果我得到它的時間,我會發送一個筆記到一個郵件列表,有人會希望注意到這一點:) – Torxed 2013-05-07 08:53:02