python 批量探测服务端开放的TCP端口

个人博客地址

http://www.darkghost.life

现在大多服务器都有做icmp限制或直接禁掉,导致我们业务去连接服务器异常时无法判断是程序问题还是网络问题,所以写一个简单探测tcp端口脚本来探测服务器所开放的端口,再使用tcp测试双向时延来排掉网络问题

  1 #!/usr/bin env python
  2 #-*-coding:utf-8-*-
  3 import socket,time,threading
  4 import signal,os,argparse,re
  5 #---------------------------------------------信号侦听模块------------------------------------------
  6 def signal_handler(signal, frame):
  7     # print(success)
  8     if success:
  9         for ip in success:
 10             print()
 11             print('扫描结束,主机%s,开放的端口有%s'%(ip,success[ip]))
 12     os._exit(0)
 13 signal.signal(signal.SIGINT, signal_handler)
 14 #----------------------------------------------扫描函数-------------------------------------------------
 15 socket.setdefaulttimeout(0.1)
 16 success = {}
 17 port_li = []
 18 def scan(HOST,port,q):
 19     startport,endport = port
 20     for port in range (startport,endport):
 21         s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            s.settimeout(1)
 22         try:
 23             s.connect((HOST,port))
 24             print('%s-%d端口开启'%(HOST,port))
 25             port_li.append(port)
 26             success[HOST]=port_li 
 27         except:
 28             pass
            finally:
                s.close()
    
 29 def thread(ip,q,startport,maxport):
 30     li = []
 31     startport = 1
 32     endport = startport+200
 33     if endport > maxport:
 34         endport = maxport
 35     dup=[(startport,endport)]
 36     while endport < maxport:
 37         startport,endport=endport,endport+200
 38         if endport >= maxport:
 39             endport = maxport
 40         dup.append((startport,endport))
 41     for port in dup:
 42         t1 = threading.Thread(target=scan,args=(ip,port,q))
 43         t1.start()
 44         li.append(t1)
 45     for t in li:
 46         t.join()
 47     if success:
 48         q.put(success)
 49 
 50 
 51 if __name__=='__main__':
 52     from multiprocessing import Process,Queue
 53     #接收参数
 54     parser = argparse.ArgumentParser(description='ip_scan')
 55     parser.add_argument('-t',action = 'store',dest='tip')
 56     parser.add_argument('-p',action='store',dest='port')
 57     args= parser.parse_args()
 58     try:
 59         ip = args.tip
 60         port = args.port
 61         dip = re.findall('\d+',ip)
 62         startport,maxport = port.split('-')
 63     except:
 64         print('-----------------example--------------')
 65         print('tcpportstatus.py -t 10.0.0.0/24 -p 0-65535')
 66         exit(0)
 67     q = Queue()
 68     li = []
 69     ip_list = []
 70     if int(dip[4]) ==0 or int(dip[4])>32:
 71         print('----------------掩码错误----------------------')
 72         exit(0)
 73     #计算地址数量
 74     subnet = int(dip[4])%8
 75     if subnet !=0:
 76         subnet_count = 2**(8-subnet)
 77     else:
 78         subnet_count = 2**subnet
 79     #创建ip地址列表
 80     if 32 >= int(dip[4])>24:
 81         #验证子网划分是否错误
 82         if int(dip[3])%subnet_count != 0:
 83             print('-----------ip格式错误-----------')
 84             exit(0)
 85         startip = int(dip[3])
 86         endip = startip + subnet_count
 87         dip[3] = '%s'
 88         dip = '.'.join(dip[0:4])
 89         for d in range(startip,endip):
 90             ip_list.append(dip%d)
 91     elif int(dip[4])>16:
 92         if int(dip[2])%subnet_count != 0:
 93             print('-----------ip格式错误-----------')
 94             exit(0)
 95         startip = int(dip[2])
 96         endip = startip + subnet_count 
 97         dip[2] = '%s'
 98         dip[3] = '%s'
 99         dip = '.'.join(dip[0:4])
100         for c in range(startip,endip):
101             dip_c = dip%(c,'%s')
102             for d in range(1,256):
103                 dip_d = dip_c%d
104                 ip_list.append(dip_d)
105     elif int(dip[4])>8:
106         if int(dip[1])%subnet_count != 0:
107             print('-----------ip格式错误-----------')
108             exit(0)
109         startip = int(dip[1])
110         endip = startip + subnet_count 
111         dip[1] = '%s'
112         dip[2] = '%s'
113         dip[3] = '%s'
114         dip = '.'.join(dip[0:4])
115         for b in range(startip,endip):
116             dip_b = dip%(b,'%s','%s')
117             for c in range(0,256):
118                 dip_c = dip_b%(c,'%s')
119                 for d in range(1,256):
120                     dip_d = dip_c%d
121                     ip_list.append(dip_d)
122     elif int(dip[4])>0:
123         if int(dip[1])%subnet_count != 0:
124             print('-----------ip格式错误-----------')
125             exit(0)
126         startip = int(dip[0])
127         endip = startip + subnet_count
128         dip[0] = '%s'
129         dip[1] = '%s'
130         dip[2] = '%s'
131         dip[3] = '%s'
132         dip = '.'.join(dip[0:4])
133         for a in range(startip,endip):
134             dip_a = dip%(a,'%s','%s','%s')
135             for b in range(0,256):
136                 dip_b = dip_a%(b,'%s','%s')
137                 for c in range(0,256):
138                     dip_c = dip_b%(c,'%s')
139                     for d in range(0,256):
140                         dip_d = dip_c%d
141                         ip_list.append(dip_d)
142     print('-----------------------------------开始扫描------------------------------------')
143     starttime = time.time()
144     print('扫描地址数量%s,端口%s-%s'%(len(ip_list),int(startport),int(maxport)))
145 
146     for address in ip_list:
147         t1 = Process(target=thread,args=(address,q,int(startport),int(maxport)))
148         t1.start()
149         li.append(t1)
150     for t in li:
151         t.join()
152     usetime = time.time()-starttime
153     print('--------------------------扫描结束用时%s秒----------------------'%int(usetime))
154     if not q.empty():
155         while not q.empty():
156             q_dic = q.get()
157             for ip in q_dic:
158                 print('扫描结束,此次扫描的主机%s,开放的端口有%s'%(ip,q_dic[ip]))
159     else:
160         print()
161         print('扫描结束,此次扫描的主机,没有开放的TCP端口')
旧版做记录

 

 

 -------------------------------------------2023.1.17更新-------------------------------------------------------------------------

#!/usr/bin env python
#-*-coding:utf-8-*-
import socket,time
from concurrent import futures
import signal,os,argparse
import ipaddress as dst
from sys import exit

#---------------------------------------------信号侦听模块------------------------------------------
def signal_handler(signal, frame):
    show()
    os._exit(0)
signal.signal(signal.SIGINT, signal_handler)
#----------------------------------------------扫描函数-------------------------------------------------
socket.setdefaulttimeout(0.1)
def show():
    time.sleep(0.1)
    if not q.empty():
        while not q.empty():
            q_dic = q.get()
            for ip in q_dic:
                print('扫描结束,此次扫描的主机%s,开放的端口有%s'%(ip,q_dic[ip]))
    else:
        print()
        print('扫描结束,此次扫描的主机,没有开放的TCP端口')
class Scan:
    def __init__(self,ip):
        self.port_li=[]
        self.success = {}
        self.port,self.host = ip
        self.host = str(self.host)
        global q
        self.q = q
        self.start()
    def portrange(self):
        startport,maxport = self.port.split('-')
        startport,maxport= int(startport),int(maxport)
        endport = maxport+1 if maxport< startport + 200 else startport +200
        portrange_list=[(startport,endport)]
        while endport < maxport:
            startport,endport=endport,endport+200
            if endport >= maxport:
                endport = maxport+1
            portrange_list.append((startport,endport))
        return portrange_list
    def scan(self,portrange):
        startport,endport = portrange
        for port in range (startport,endport):
            s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            s.settimeout(0.2)
            s.bind((sip,0))
            try:
                s.connect((self.host,port))
                try:
                    port_type = s.recv(1024).decode().strip()
                    print('%s-%d端口开启,%s'%(self.host,port,port_type))
                except:
                    print('%s-%d端口开启'%(self.host,port))
                self.port_li.append(port)
            except:
                pass
            s.close()    
    def start(self):
        portrange_list = self.portrange()
        with futures.ThreadPoolExecutor(100) as executor:
            res = executor.map(self.scan, [portrange for portrange in portrange_list])
        if self.port_li:
            self.success[self.host]=self.port_li
            self.q.put(self.success)
if __name__=='__main__':
    from multiprocessing import Process,Queue
    #接收参数
    parser = argparse.ArgumentParser(description='ip_scan')
    parser.add_argument('-s',action = 'store',dest='sip')
    parser.add_argument('-t',action = 'store',dest='tip')
    parser.add_argument('-p',action='store',dest='port')
    args= parser.parse_args()
    try:
        sip = args.sip
        dip = dst.ip_network(args.tip)
        port = args.port
    except ValueError as format_error:
        print(format_error)
        print('-----------------example--------------')
        print('tcpportstatus.py -s 127.0.0.1 -t 10.0.0.0/24 -p 0-65535')
        exit(0)
    q = Queue()
    print('-----------------------------------开始扫描------------------------------------')
    starttime = time.time()
    print('扫描地址数量%s,端口%s'%(dip.num_addresses,port))
    
    with futures.ThreadPoolExecutor(100) as executor:
        res = executor.map(Scan, [(port,host) for host in dip])
    usetime = time.time()-starttime+1
    print('--------------------------扫描结束用时%s秒----------------------'%int(usetime))
    show()

 

 

 

 

多进程多线程扫描,一个ip一个进程,根据扫描机器cpu性能可以调整startport和endport的参数来跑更多线程,以我的设备为例,Intel(R) Xeon(R) CPU E3-1220 V2 @ 3.10GHz ,扫描50个ip地址65535以下端口用时71秒

 

 

探测到端口后剩下的测试使用tcping.py(见zabbix系列)就行了

posted @ 2021-05-22 16:17  无限's-blog  阅读(658)  评论(0编辑  收藏  举报