端口是设备与外界通信交流的接口,如果把服务器看作一栋房子,那么端口就是可以进出这栋房子的门。真正的房子只有一个或者几个门,但是服务器至多可以有 65536 个门。不同的端口指向不同的服务,就像不同的门对应不同的房间
这里使用 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))