端口是设备与外界通信交流的接口,如果把服务器看作一栋房子,那么端口就是可以进出这栋房子的门。真正的房子只有一个或者几个门,但是服务器至多可以有 65536 个门。不同的端口指向不同的服务,就像不同的门对应不同的房间 最常见的三个服务端口就是 80、21、3389,分别对应的是浏览网页时涉及的 www 服务,上传和下载文件的服务,远程桌面的服务。如果入侵者想要控制这个服务器,那么肯定得先通过一个端口进入该服务,就如同控制房子首先得通过门进入房间一样,因此,在信息的收集阶段,端口的扫描就尤为重要
这里使用 python 的 socket 模块来进行端口扫描的编写,先导入需要用到的模块
1 2 3 4 5 import sys import socket import optparse import threading import queque
接着编写一个端口扫描类,继承 threading.Thread。这个类需要传递 3 个参数,分别是目标 IP、端口队列、超时时间,通过这个类来创造多个子线程来加快扫描速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # 端口扫描类,继承threading.Thread class PortScaner(threading.Thread): def __init__(self, portqueue, ip, timeout=3): threading.Thread.__init__(self) self._potqueue = portqueue self._ip = ip self._timeout = timeout def run(self): while True: # 判断端口队列是否为空 if self._portqueue.empty(): # 端口队列为空,说明已经扫描完毕,跳出循环 break # 从端口队列中取出端口,超时时间为1s port = self._portqueue.get(timeout=0.5) try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(self._timeout) result_code = s.connect_ex((self._ip, port)) # sys.stdout.write("[%d]Scan\n"%port) # 若端口开放,则会返回0 if result_code == 0: sys.stdout.write("[%d] OPEN\n" % port) except Exception as e: print(e) finally: s.close()
编写一个函数,根据用户的参数来指定目标 IP、端口队列的生成以及子线程的生成,同时能支持单个端口的扫描和范围端口的扫描
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def StartScan(targetip, port, threadNum): # 端口列表 portList = [] portNumb = port # 判断是单个端口还是范围端口 if '-' in port: for i in range(int(port.split('-')[0]), int(port.split('-')[1]) + 1): portList.append(i) else: portList.append(int(port)) # 目标IP地址 ip = targetip # 线程列表 threads = [] # 线程数量 threadNumber = threadNum # 端口队列 portQueue = queue.Queue() # 生成端口,加入端口队列 for port in portList: portQueue.put(port) for t in range(threadNumber): threads.append(PortScaner(portQueue, ip, timeout=3)) # 启动线程 for thread in threads: thread.start() # 阻塞线程 for thread in threads: thread.join()
编写主函数来指定参数的规则
1 2 3 4 5 6 7 8 9 10 if __name__ == '__main__': parser = optparse.OptionParser('Example:python %prog -i 127.0.0.1 -p 80 \n python %prog -i 127.0.0.1 -p 1-100\n') # 目标IP参数-i parser.add_option('-i', '--ip', dest='targetIP', default='127.0.0.1', type='string', help='target IP') # 添加端口参数-p parser.add_option('-p', '--port', dest='port', default='80', type='string', help='scann port') # 线程数量参数-t parser.add_option('-t', '--thread', dest='threadNum', default=100, type='int', help='scann thread number') (options, args) = parser.parse_args() StartScan(options.targetIP, options.port, options.threadNum)
接下来用自己的服务器测试一下开放端口
1 python3 ./ce.py -i ip -p 端口
这是测试单个端口的开放,也同时可以设置多线程跑范围端口
1 python3 ./ce.py -i ip -p 1-3500 -t 100
同时也可以使用 nmap 库来修改工具进行端口扫描,所需修改的部分代码:
1 result = nm.scan(hosts=targetIP,arguments='-p'+str(targetPort))