python 批量探测服务端开放的TCP端口
个人博客地址
现在大多服务器都有做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系列)就行了
以驱魔为理想,为生计而奔波

浙公网安备 33010602011771号