我使用python + scapy编写了一个无线探针嗅探器。我想在openwrt路由器中使用这个脚本。
每次从附近的设备捕获探测请求时,信息都会发送到Web服务。 (mac,power and probe)。
我的问题是CPU的消耗很高。这个脚本在我的笔记本电脑上运行得非常好(需要50-70%的cpu),但是当我在一个openwrt路由器(400mhz cpu,16 ram)中运行它需要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()
[UPDATE]
经过大量的阅读和深度搜索(似乎没有多少人找到完全解决同一问题或类似的问题)。 我发现你可以直接从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
我尝试过使用bpf过滤器语法(在tcpdump http://biot.com/capstats/bpf.html中使用的相同),并且假设你也可以在scapy中使用它,但我得到了一个过滤器语法错误。
嗤之以鼻:
def main():
print "[%s] Starting scan"%datetime.now()
sniff(iface=sys.argv[1],prn=PacketHandler, filter='type mgt subtype probe-req', store=0)
错误:
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
在路由器中,我安装了最新版本的scapy和tcpdump。 现在我真的不知道该怎么做。
答案 0 :(得分:1)
当我尝试在NETGEAR WNDR4300上使用带有过滤器的sniff()
时,我遇到了类似的错误(socket.error:[Errno 99]协议不可用)。
经过大量搜索,我发现原因是我的路由器的Linux内核没有启用CONFIG_PACKET。 the Scapy installation guide中提到了如下:
- 确保您的内核已选择数据包套接字(CONFIG_PACKET)
- 如果您的内核是&lt; 2.6,确保选择Socket过滤CONFIG_FILTER)
如果在编译内核时设置CONFIG_PACKET=y
,那么它将为底层套接字启用BPF。