千家信息网

如何用python写个端口扫描器及各种并发尝试

发表于:2024-11-17 作者:千家信息网编辑
千家信息网最后更新 2024年11月17日,这期内容当中小编将会给大家带来有关如何用python写个端口扫描器及各种并发尝试,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。端口扫描器原理很简单,无非就是操作so
千家信息网最后更新 2024年11月17日如何用python写个端口扫描器及各种并发尝试

这期内容当中小编将会给大家带来有关如何用python写个端口扫描器及各种并发尝试,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

端口扫描器原理很简单,无非就是操作socket,能connect就认定这个端口开放着。

import socketdef 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))

这样一个最简单的端口扫描器出来了。

等等喂,半天都没反应,那是因为socket是阻塞的,每次连接要等很久才超时。

我们自己给它加上的超时。

s.settimeout(0.1)

再跑一遍,感觉快多了。

多线程版本

import socketimport threadingdef scan(port):    s = socket.socket()    s.settimeout(0.1)    if s.connect_ex(('localhost', port)) == 0:        print port, '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。

想一下,这个进程开启了65535个线程,有两种可能,一种是超过最大线程数了,一种是超过最大socket句柄数了。在linux可以通过ulimit来修改。

如果不修改最大限制,怎么用多线程不报错呢?

加个queue,变成生产者-消费者模式,开固定线程。

多线程+队列版本

import socketimport threadingfrom Queue import Queuedef scan(port):    s = socket.socket()    s.settimeout(0.1)    if s.connect_ex(('localhost', port)) == 0:        print port, '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+队列版本

总不能开65535个进程吧?还是用生产者消费者模式

import multiprocessingdef scan(port):    s = socket.socket()    s.settimeout(0.1)    if s.connect_ex(('localhost', port)) == 0:        print port, '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,xrange(1,65535))    jobs = [multiprocessing.Process(target=worker, args=(q,)) for i in xrange(100)]    map(lambda x:x.start(),jobs)

注意这里把队列作为一个参数传入到worker中去,因为是process safe的queue,不然会报错。

还有用的是JoinableQueue(),顾名思义就是可以join()的。

gevent的spawn版本

from gevent import monkey; monkey.patch_all();import geventimport 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 socketfrom gevent.pool import Pool...if __name__ == '__main__':    pool = Pool(500)    pool.map(scan,xrange(1,65536))    pool.join()

concurrent.futures版本

import socketfrom Queue import Queuefrom concurrent.futures import ThreadPoolExecutor...if __name__ == '__main__':    q = Queue()    map(q.put,xrange(1,65536))    with ThreadPoolExecutor(max_workers=500) as executor:        for i in range(500):            executor.submit(worker,q)

上述就是小编为大家分享的如何用python写个端口扫描器及各种并发尝试了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

0