构建一个快速的扫描器
2015-08-14 21:35
330 查看
0x00 前言
最近工作需要做大规模的扫描,需要自己根据指纹写一个扫描引擎,其中碰到了无数的坑,最后勉强算的过去,特地写写博客总结一下各种坑和思路。0x01 任务队列+多线程模型
一开始自然而然想到的就是这个扫描模型,利用Python中的同步队列结合多线程发包、收包、写操作。大致模型如下:class Worker(Thread): def __init__(self, queue): self.queue = queue def run(self): while True: ip = self.queue.get() sock.send() recv = sock.recv(buf_size) .... do sth.... .... self.queue.task_done() def main(): ... worker = Worker(queue) work.deamon = True work.start() queue.join() # 队列同步 ...
然而事实证明效率真的很低,只能发出可怜的几百pps,
4M带宽都占不满。各位如果想做大规模扫描,我说的大规模扫描是指上亿的IP扫描,就别考虑这种方法了。
总结一下原因,主要是线程太多,切换时间非常耗费CPU,并且由于
GIL的存在,效率可想而知。其次就是由于IP太多,不能全部放入队列中,必须在main函数中做个缓冲区,然后放入同步队列,频繁
queue.join()的结果是状态为done的线程在等待慢线程的情景增多,效率自然就不高了,由于以上原因导致的效率低下,网络的IO延迟根本不算什么。
后来又想用celery做异步的任务,分离网络IO和本地IO,把线程中本地耗时长的IO操作分离出来,放到celery当中异步执行,这样可以加快发包收包线程的速度。结果发现更慢,建议不要用celery处理非常耗时的后台任务,感觉好坑….
0x01 基于无状态扫描模型
简单来说,就是不关心数据包的交互状态,这里不存在同步队列的情况。而是开辟两个线程即可,一个线程负责send,另一个线程负责
recv,由于我业务上需要发送UDP协议为基础探测包。
这样做的好处是不同在一个线程中同时发送和接收报文,由于不关心网络通信的交互过程,因此,可以让发包线程和收包线程分别满负荷工作,不存在线程相互等待的情况,也基本不存在同步的情况,因此效率大大提高。模型大致如下:
class Sender(Thread): def __init__(self, sock): self.sock = sock def run(self): for ip in list: pack = package_create() self.sock.sendto(pack, server) .... do sth ... .... class Receiver(Thread): def __init__(self, sock): self.sock = sock def run(self): while True: recv = self.sock.recvfrom(buf_size) handle_recv_package(recv) .... do sth ... .... def main(): sender = Sender(sock) recver = Receiver(sock) .... do sth ... .... sock.close()
比较麻烦的是,这种模式需要自己对报文进行组装、发送、解析接收的报文等工作。回报是,效率大大提高,轻松3k~4kpps(4M/1 CPU/2G mem),带宽基本占满。
0x03 性能提升
主要提升的空间在以下方面:加快报文组装的速度
加快接收报文的组装速度
利用缓冲区进行批量IO,一定程度减少IO操作
处理好socket error,建议使用事件模型,设置任务回滚功能,遇到socket error就结束线程,然后在主线程中再新建socket并启动线程开工
优化做好了,现有的带宽占满了,这时候,瓶颈就是带宽,就要换个更好的带宽,增加速度。
另外,在测试的过程中,鄙人发现网卡发送UDP包的速度比TCP慢多了,用了两台机器测试,结论一致。
相关文章推荐
- OpenCV 下载驿站(百度云盘下载,同步更新)
- HDU 1069 Monkey and Banana
- Visual Studio 2015 C++跨平台移动开发(二) -浅谈Windows Bridge for iOS
- openstack某节点空间不足
- list
- s3c2440开发板如何与pc直连
- noip2013转圈游戏
- java杨氏矩阵查找算法
- 【源代码】LinkedList源代码分析
- HDU 2602
- 编译spock proxy
- 代理模式
- 小白书之移动小球哈希表的链式结构
- Spring---IOC原理浅析
- HDU4324 Triangle Love【拓扑排序】
- dash
- 编写高质量代码改善C#程序的157个建议——建议25:谨慎集合属性的可写操作
- C# SqlHelper (一)
- block没那么难(三)
- block没那么难(二)