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