前言

端口是设备与外界通信交流的接口。如果把服务器看作一栋房子,那么端口就是可以进出这栋房子的门。不同的端口可以指向不同的服务。所以入侵者想要获取到房子的控制权,势必要先从一个门进入一个房间,再通过这个房间控制整个房子。那么服务器开了几个端口,端口后面的服务是什么,这些都是十分重要的信息,可以为入侵者制定详细的入侵计划提供依据。因此端口扫描就显得十分重要。

代码演示

先导入相应的函数库

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])

运行效果如下图

端口探测java_IP


端口探测java_python_02