简体   繁体   English

Scapy python脚本在嗅探时消耗了太多的CPU

[英]Scapy python script consuming too much cpu while sniffing

I have coded a wireless probe sniffer using python + scapy. 我用python + scapy编写了一个无线探针嗅探器。 I'm want to use this script in openwrt routers. 我想在openwrt路由器中使用这个脚本。

Everytime it captures a probe request from nearby devices, the information is send to a webservice. 每次它从附近的设备捕获探测请求时,信息都会发送到Web服务。 (mac, power and probe). (mac,power和probe)。

My problem is the high consumption of CPU. 我的问题是CPU的高消耗。 The script runs quite good in my laptop (it takes between 50-70% of cpu), but when I run it in an openwrt router (400mhz cpu,16 ram) it takes 99%. 这个脚本在我的笔记本电脑上运行得非常好(需要50-70%的cpu),但是当我在一个openwrt路由器(400mhz cpu,16 ram)中运行它需要99%。 It's a well known bug in scapy the lost of packets with high loads (I have tested at the same time the script in my laptop and in the router and the router do not catched all the available packets in the air) 这是一个众所周知的错误,因为丢失了高负载的数据包(我同时测试了我的笔记本电脑和路由器中的脚本以及路由器没有捕获空中的所有可用数据包)

I already made some optimizations to the code, but I think there's more room for improvement. 我已经对代码做了一些优化,但我认为还有更多的改进空间。

This is the script. 这是脚本。

#!/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()

[UPDATE] [UPDATE]

After a lot of reading and deep searching (it seems not many people have found full solution to the same issue or something similar). 经过大量的阅读和深度搜索(似乎没有多少人找到完全解决同一问题或类似的东西)。 I have found you can filter directly from the sniff function, so I've added a filter to just catch probe requests. 我发现你可以直接从sniff函数中过滤,所以我添加了一个过滤器来捕获探测请求。

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

In my laptop runs really smooth, using between 1%-3% of cpu and catching most of the available packets in the air. 在我的笔记本电脑运行非常顺利,使用1%-3%的CPU和捕获大部分空闲的可用数据包。

but when I run this on the router, the script throws an error and crash. 但是当我在路由器上运行它时,脚本会抛出错误并崩溃。

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

I have tried using bpf filter syntax (the same used in tcpdump http://biot.com/capstats/bpf.html ) and it is supposed you can also use it in scapy but I get a filter syntax error. 我已经尝试使用bpf过滤器语法(在tcpdump http://biot.com/capstats/bpf.html中使用相同)并且它应该也可以在scapy中使用它,但是我得到了一个过滤器语法错误。

Sniff fucntion: 嗅觉功能:

def main():                                                                                                                                           
    print "[%s] Starting scan"%datetime.now()                                                                                                         
    sniff(iface=sys.argv[1],prn=PacketHandler, filter='type mgt subtype probe-req', store=0) 

error: 错误:

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

In the router I have installed the last version of scapy and tcpdump. 在路由器中我安装了最新版本的scapy和tcpdump。 Now I really don't know what to do. 现在我真的不知道该怎么做。

I encountered a similar error (socket.error: [Errno 99] Protocol not available) when I tried to use sniff() with a filter on my NETGEAR WNDR4300. 当我尝试在我的NETGEAR WNDR4300上使用带过滤器的sniff() ,我遇到了类似的错误(socket.error:[Errno 99]协议不可用)。

After a lot of searching on Google, I found that the reason is that the Linux kernel of my router does not enable CONFIG_PACKET. 经过大量的Google搜索,我发现原因是我的路由器的Linux内核没有启用CONFIG_PACKET。 It is mentioned in the Scapy installation guide , as follows: Scapy安装指南中提到如下:

  • Make sure your kernel has Packet sockets selected (CONFIG_PACKET) 确保您的内核已选择数据包套接字(CONFIG_PACKET)
  • If your kernel is < 2.6, make sure that Socket filtering is selected CONFIG_FILTER) 如果你的内核<2.6,请确保选择Socket过滤CONFIG_FILTER)

If you set CONFIG_PACKET=y when you compile the kernel, then it will enable the BPF for underlying socket. 如果在编译内核时设置CONFIG_PACKET=y ,那么它将为底层套接字启用BPF。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM