前言
端口是设备与外界通信交流的接口。如果把服务器看作一栋房子,那么端口就是可以进出这栋房子的门。不同的端口可以指向不同的服务。所以入侵者想要获取到房子的控制权,势必要先从一个门进入一个房间,再通过这个房间控制整个房子。那么服务器开了几个端口,端口后面的服务是什么,这些都是十分重要的信息,可以为入侵者制定详细的入侵计划提供依据。因此端口扫描就显得十分重要。
代码演示
先导入相应的函数库
import sys
import socket
import optparse
import threading
import queue
编写一个端口扫描类,继承threading.Thread,这个在爬虫领域也叫多线程爬虫,只是应用领域不同而已。这个类需要传递3个参数,分别是目标IP,端口队列,超时时间,通过这样来加快扫描速度
#端口扫描类,继承threading.Thread
class PortScanner(threading.Thread):
#需要传入端口队列,目标IP,探测超时时间
def __init__(self,portqueue,ip,timeout=3):
threading.Thread.__init__(self)
self._portqueue = portqueue
self._ip = ip
self._timeout = timeout
def run(self):
while True:
#判断端口队列是否为空
if self._portqueue.empty():
#端口队列为空,说明已经扫描完毕,跳出循环
break
#从端口队列中取出端口,超时时间为3s
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,端口队列的生成以及线程的生成,支持大范围的扫描
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(PortScanner(portQueue,ip,timeout=3))
#启动线程
for thread in threads:
thread.start()
#阻塞线程
for thread in threads:
thread.join()
最后编写主函数入口
#主函数
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)
基于Nmap库的代码修改
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import nmap
import optparse
def NmapScan(targetIP, targetPort):
# 实例化PortScanner对象
nm = nmap.PortScanner()
try:
# hosts为目标IP地址,argusments为Nmap的扫描参数
# -p:对指定端口进行扫描
result = nm.scan(hosts=targetIP, arguments='-p'+str(targetPort))
# 对结果进行切片,提取端口信息
# 这里需要注意的是,提取信息时需要把端口转化为int型
port_infor = result['scan'][targetIP]['tcp'][int(targetPort)]
# 分别显示 端口号:端口状态
print("[{}] : [{}]".format(targetPort, port_infor['state'] ))
except Exception as e:
print(e)
if __name__ == '__main__':
parser = optparse.OptionParser('usage: python %prog -i ip -p port\n\n'
'Example: python %prog -i 192.168.1.1 -p 80,3306\n')
# 添加目标IP参数-i
parser.add_option('-i','--ip',dest='targetIP',default='192.168.1.1',type='string',help='target ip address')
# 添加扫描端口参数-p
parser.add_option('-p','--port',dest='targetPort',default='80',type='string',help='target port')
options,args = parser.parse_args()
for i in range(0,len(options.targetPort.split(','))):
NmapScan(options.targetIP, options.targetPort.split(',')[i])
运行效果如下图