2013-04-29 131 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