scapython脚本在嗅探时消耗太多cpu

scapython脚本在嗅探时消耗太多cpu,python,wireless,scapy,Python,Wireless,Scapy,我使用python+scapy编写了一个无线探测器嗅探器。我想在openwrt路由器中使用此脚本 每次它捕获来自附近设备的探测请求时,信息都会发送到Web服务。(mac、电源和探头) 我的问题是CPU的高消耗。这个脚本在我的笔记本电脑上运行得很好(它占用了50-70%的cpu),但是当我在openwrt路由器(400mhz cpu,16RAM)上运行它时,它占用了99%。 这是一个众所周知的错误,即高负载数据包丢失(我同时测试了笔记本电脑和路由器中的脚本,路由器没有捕获空中所有可用的数据包) 我

我使用python+scapy编写了一个无线探测器嗅探器。我想在openwrt路由器中使用此脚本

每次它捕获来自附近设备的探测请求时,信息都会发送到Web服务。(mac、电源和探头)

我的问题是CPU的高消耗。这个脚本在我的笔记本电脑上运行得很好(它占用了50-70%的cpu),但是当我在openwrt路由器(400mhz cpu,16RAM)上运行它时,它占用了99%。 这是一个众所周知的错误,即高负载数据包丢失(我同时测试了笔记本电脑和路由器中的脚本,路由器没有捕获空中所有可用的数据包)

我已经对代码进行了一些优化,但我认为还有更多的改进空间

这是剧本

#!/usr/bin/python
from scapy.all import *
import time
import thread
import requests
from datetime import datetime

PROBE_REQUEST_TYPE=0
PROBE_REQUEST_SUBTYPE=4
buf={'arrival':0,'source':0,'dest':0,'pwr':0,'probe':0}
uuid='1A2B3'

def PacketHandler(pkt):
    global buf
    if pkt.haslayer(Dot11):
        if pkt.type==PROBE_REQUEST_TYPE and pkt.subtype == PROBE_REQUEST_SUBTYPE:
            arrival= int(time.mktime(time.localtime()))
            try:
                extra = pkt.notdecoded
            except:
                extra=None

            if extra!=None:
                signal_strength = -(256-ord(extra[-4:-3]))
            else:
                signal_strength = -100

            source = pkt.addr2
            dest= pkt.addr3
            pwr=signal_strength
            probe=pkt.getlayer(Dot11).info

            if buf['source']!=source and buf['probe']!=probe:
                print 'launch %r %r %r' % (source,dest,probe)
                buf={'arrival':arrival,'source':source,'dest':dest,'pwr':pwr,'probe':probe}

                try:
                    thread.start_new_thread(exporter,(arrival,source,dest,pwr,probe))
                except:
                    print 'Error launching the thread %r' % source

def exporter (arrival,source,dest,pwr,probe):
    global uuid
    urlg='http://webservice.com/?arrival='+str(arrival)+'&source='+str(source)+'&dest='+str(dest)+'&pwr='+str(pwr)+'&probe='+str(probe)+'&uuid='+uuid
    try:
        r=requests.get(urlg)
        print r.status_code
        print r.content
    except:
        print 'ERROR in Thread:::::: %r' % source







def main():
    print "[%s] Starting scan"%datetime.now()
    sniff(iface=sys.argv[1],prn=PacketHandler,store=0)

if __name__=="__main__":
    main()
[更新]

经过大量阅读和深入研究(似乎没有多少人找到同一问题或类似问题的完整解决方案)。 我发现您可以直接从sniff函数进行过滤,因此我添加了一个过滤器来捕获探测请求

def main():
    print "[%s] Starting scan"%datetime.now()
    sniff(iface=sys.argv[1],prn=PacketHandler, filter='link[26] = 0x40',store=0)
在我的笔记本电脑中,运行非常平稳,使用了1%-3%的cpu,并捕获了大部分空中可用的数据包

但是当我在路由器上运行这个时,脚本抛出一个错误并崩溃

Traceback (most recent call last):
  File "snrV2.py", line 66, in <module>
    main()
  File "snrV2.py", line 63, in main
    sniff(iface=sys.argv[1],prn=PacketHandler, filter='link[26] = 0x40',store=0)
  File "/usr/lib/python2.7/site-packages/scapy/sendrecv.py", line 550, in sniff
    s = L2socket(type=ETH_P_ALL, *arg, **karg)
  File "/usr/lib/python2.7/site-packages/scapy/arch/linux.py", line 460, in __init__
    attach_filter(self.ins, filter)
  File "/usr/lib/python2.7/site-packages/scapy/arch/linux.py", line 132, in attach_filter
    s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 99] Protocol not available
错误:

Traceback (most recent call last):
  File "snrV2.py", line 66, in <module>
    main()
  File "snrV2.py", line 63, in main
    sniff(iface=sys.argv[1],prn=PacketHandler, filter='type mgt subtype probe-req', store=0)
  File "/usr/lib/python2.7/site-packages/scapy/sendrecv.py", line 550, in sniff
    s = L2socket(type=ETH_P_ALL, *arg, **karg)
  File "/usr/lib/python2.7/site-packages/scapy/arch/linux.py", line 460, in __init__
    attach_filter(self.ins, filter)
  File "/usr/lib/python2.7/site-packages/scapy/arch/linux.py", line 120, in attach_filter
    raise Scapy_Exception("Filter parse error")
NameError: global name 'Scapy_Exception' is not defined
回溯(最近一次呼叫最后一次):
文件“snrV2.py”,第66行,在
main()
文件“snrV2.py”,第63行,在main中
嗅探(iface=sys.argv[1],prn=PacketHandler,filter='type mgt subtype probe req',store=0)
文件“/usr/lib/python2.7/site packages/scapy/sendrecv.py”,第550行,在sniff中
s=L2socket(类型=ETH_P_ALL,*arg,**karg)
文件“/usr/lib/python2.7/site packages/scapy/arch/linux.py”,第460行,在__
附加过滤器(self.ins,过滤器)
文件“/usr/lib/python2.7/site packages/scapy/arch/linux.py”,第120行,在附件过滤器中
引发Scapy_异常(“筛选器分析错误”)
NameError:未定义全局名称“Scapy_异常”
在路由器中,我安装了最新版本的scapy和tcpdump。
现在我真的不知道该怎么办。

我在NETGEAR WNDR4300上尝试使用带有过滤器的
sniff()
时遇到了类似的错误(socket.error:[Errno 99]协议不可用)

在Google上搜索了很多次之后,我发现原因是我路由器的Linux内核没有启用CONFIG_数据包。其中提到,如下所示:

  • 确保您的内核已选择数据包套接字(CONFIG_数据包)
  • 如果内核<2.6,请确保已选择套接字筛选(配置过滤器)

如果您在编译内核时设置了
CONFIG\u PACKET=y
,那么它将为底层套接字启用BPF。

1:捕获数据包是一件非常困难的事情2:400mhz没有您想象的那么强大,它肯定会轻松地利用所有这些功能来捕获Python下的流量。如果你的电脑使用70%的CPU,这应该是捕获所有数据包所需的电量的一个很好的指标,因为我假设你的电脑中有超过2Ghz的数据包,这告诉我你大约使用1400Mhz来捕获所有数据包,现在将其与400Mhz进行比较。(这不是一个精确的计算,但能让你知道你在做什么)@Torxed:停止试图把问题硬塞进CR。如果这个问题在这里是离题的,那么投票结束它,并列出适当的理由。您可以建议,一个问题可能非常适合,但投票结束一篇文章的第一条规则是,它实际上必须脱离主题。@Torxed:例如,这个问题可能太广泛了。此时,您投票决定将其关闭,建议OP可能更适合CR(首先查看他们的主题帮助信息),并标记帖子,要求版主将其迁移。但不要为此滥用自定义的“结束投票”消息。@Torxed:请注意,代码有效也不是将某些内容标记为非主题的原因。我们有很多问题,其中代码已经“起作用”,只是对于特定的指标来说不够好。@Torxed:其中哪一部分必须脱离主题,并标记文章以询问主持人,你错过了吗?迁移到选项为。
Traceback (most recent call last):
  File "snrV2.py", line 66, in <module>
    main()
  File "snrV2.py", line 63, in main
    sniff(iface=sys.argv[1],prn=PacketHandler, filter='type mgt subtype probe-req', store=0)
  File "/usr/lib/python2.7/site-packages/scapy/sendrecv.py", line 550, in sniff
    s = L2socket(type=ETH_P_ALL, *arg, **karg)
  File "/usr/lib/python2.7/site-packages/scapy/arch/linux.py", line 460, in __init__
    attach_filter(self.ins, filter)
  File "/usr/lib/python2.7/site-packages/scapy/arch/linux.py", line 120, in attach_filter
    raise Scapy_Exception("Filter parse error")
NameError: global name 'Scapy_Exception' is not defined