实例探究Python以并发方式编写高性能端口扫描器的方法
关于端口扫描器 端口扫描定义是客户端向一定范围的服务器端口发送对应请求,以此确认可使用的端口。虽然其本身并不是恶意的网络活动,但也是网络攻击者探测目标主机服务,以利用该服务的已知漏洞的重要手段。端口扫描的主要用途仍然只是确认远程机器某个服务的可用性。 扫描多个主机以获取特定的某个端口被称为端口清扫(Portsweep),以此获取特定的服务。例如,基于SQL服务的计算机蠕虫就会清扫大量主机的同一端口以在 1433 端口上建立TCP连接。 Python实现 端口扫描器原理很简单,无非就是操作socket,能connect就认定这个端口开放着。 import socket def scan(port): s = socket.socket() if s.connect_ex(('localhost',port)) == 0: print port,'open' s.close() if __name__ == '__main__': map(scan,range(1,65536)) 这样一个最简单的端口扫描器出来了。 s.settimeout(0.1) 再跑一遍,感觉快多了。 多线程版本 import socket import threading def scan(port): s = socket.socket() s.settimeout(0.1) if s.connect_ex(('localhost','open' s.close() if __name__ == '__main__': threads = [threading.Thread(target=scan,args=(i,)) for i in xrange(1,65536)] map(lambda x:x.start(),threads) 运行一下,哇,好快,快到抛出错误了。thread.error: can't start new thread。 多线程+队列版本 import socket import threading from Queue import Queue def scan(port): s = socket.socket() s.settimeout(0.1) if s.connect_ex(('localhost','open' s.close() def worker(): while not q.empty(): port = q.get() try: scan(port) finally: q.task_done() if __name__ == '__main__': q = Queue() map(q.put,xrange(1,65535)) threads = [threading.Thread(target=worker) for i in xrange(500)] map(lambda x:x.start(),threads) q.join() 这里开500个线程,不停的从队列取任务来做。 multiprocessing+队列版本 import multiprocessing def scan(port): s = socket.socket() s.settimeout(0.1) if s.connect_ex(('localhost','open' s.close() def worker(q): while not q.empty(): port = q.get() try: scan(port) finally: q.task_done() if __name__ == '__main__': q = multiprocessing.JoinableQueue() map(q.put,65535)) jobs = [multiprocessing.Process(target=worker,args=(q,)) for i in xrange(100)] map(lambda x:x.start(),jobs) 注意这里把队列作为一个参数传入到worker中去,因为是process safe的queue,不然会报错。 gevent的spawn版本 from gevent import monkey; monkey.patch_all(); import gevent import socket ... if __name__ == '__main__': threads = [gevent.spawn(scan,i) for i in xrange(1,65536)] gevent.joinall(threads) 注意monkey patch必须在被patch的东西之前import,不然会Exception KeyError.比如不能先import threading,再monkey patch. gevent的Pool版本 from gevent import monkey; monkey.patch_all(); import socket from gevent.pool import Pool ... if __name__ == '__main__': pool = Pool(500) pool.map(scan,65536)) pool.join() concurrent.futures版本 import socket from Queue import Queue from concurrent.futures import ThreadPoolExecutor ... if __name__ == '__main__': q = Queue() map(q.put,65536)) with ThreadPoolExecutor(max_workers=500) as executor: for i in range(500): executor.submit(worker,q) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |