运维python进行(一) nmap扫描

  • 2020 年 1 月 13 日
  • 笔记

介绍

python-nmap是基于系统nmap命令的一个端口扫描工具,使用简单方便。

最近为了加强服务器安全性和监管,需要每天把公司服务器开放端口扫描记录,一旦出现增加减少能发现。

最近打算完善一下我们的运维平台,重新编写了脚本,方便平台的调用。

In [17]: import nmap  把nmap模块的端口扫描方法进行实例化  In [18]: s=nmap.PortScanner()  使用scan('192.168.0.0/16',port='0-65536','sV')方法,里面分别是网段,端口范围,nmap的参数  In [19]: result = s.scan('192.168.199.211', '20-443','')  这里result是执行的输出  In [20]: print result  {'nmap': {'scanstats': {'uphosts': '1', 'timestr': 'Sat Dec 17 16:24:11 2016', 'downhosts': '0', 'totalhosts': '1', 'elapsed': '0.11'}, 'scaninfo': {'tcp': {'services': '20-443', 'method': 'syn'}}, 'command_line': 'nmap -oX - -p 20-443 192.168.199.211'}, 'scan': {'192.168.199.211': {'status': {'state': 'up', 'reason': 'localhost-response'}, 'hostnames': [{'type': 'PTR', 'name': 'salt'}], 'vendor': {}, 'addresses': {'ipv4': '192.168.199.211'}, 'tcp': {80: {'product': '', 'state': 'open', 'version': '', 'name': 'http', 'conf': '3', 'extrainfo': '', 'reason': 'syn-ack', 'cpe': ''}, 443: {'product': '', 'state': 'open', 'version': '', 'name': 'https', 'conf': '3', 'extrainfo': '', 'reason': 'syn-ack', 'cpe': ''}, 22: {'product': '', 'state': 'open', 'version': '', 'name': 'ssh', 'conf': '3', 'extrainfo': '', 'reason': 'syn-ack', 'cpe': ''}}}}}  初始化的实例如下方法  In [21]: s.              s.all_hosts             s.csv                   s.listscan              s.scaninfo                            s.analyse_nmap_xml_scan s.get_nmap_last_output  s.nmap_version          s.scanstats                           s.command_line          s.has_host              s.scan                 扫描的所有主机  In [21]: s.all_hosts()  Out[21]: ['192.168.199.211']    主机下的信息列表     In [23]: s['192.168.199.211'].keys()  Out[23]: ['status', 'hostnames', 'vendor', 'addresses', 'tcp']    主机下的tcp端口列表     In [26]: s['192.168.199.211']['tcp'].keys()  Out[26]: [80, 443, 22]  查看22端口的详细信息  In [30]: s['192.168.199.211']['tcp'][22]  Out[30]:   {'conf': '3',   'cpe': '',   'extrainfo': '',   'name': 'ssh',   'product': '',   'reason': 'syn-ack',   'state': 'open',   'version': ''}

通过上面大家可以看到 s=nmap.PortScanner()实例化以后,会把信息存储到“s”里面,“s”可以像从json里面取数据一样超级方便。

下面是脚本原理,欢迎大家拍砖,提更好意见:

  1. 依赖python-nmap模块扫扫面网段或者指定ip端口
  2. 对比redis内昨日此ip的端口集合,获取相互差集记录到文本
  3. 删除昨日的端口扫面记录,把今日信息ip为KEY 端口为集合记录到redis
#!/bin/bash  '''  	author: baishaohua  	date: 20161215  '''  host='192.168.1.224'  port='6379'  import nmap  import redis  import time  ctime = time.strftime('%Y_%m_%d')  r = redis.StrictRedis(host,port=port,db=12)    def get_info(ip):          '''获取集合,并把集合元素转换为整数'''  	a=[]  	for i in r.smembers(ip):  		a.append(int(i))  	return a    def set_info(ip, port_list):  	r.delete(ip)#删除昨日的端口记录,下面遍历写入今日的端口  	try:  		for port in port_list:  			r.sadd(ip, port)  	except:  		print "set redis err"    def r_log(msg):  	f_path = "/tmp/report_%s.txt" % ctime  	f = open(f_path, 'a+')  	f.write(msg)  	f.close()    def scan_port(my_ip,port_range):  	'''  	tow parameter: ip,port. will return a port list   	'''  	s = nmap.PortScanner()  	result = s.scan(my_ip,port_range,'')  	return s[my_ip]['tcp'].keys()    def scan_ips(ip_range,port_range):          '''          tow parameter: ip,port. will return a port list           '''          s = nmap.PortScanner()          result = s.scan(ip_range,port_range,'')  	report_key = "report_%s" % ctime  	a  = {}  	b  = {}  	for i in s.all_hosts():  		a[i] = set(get_info(i))  		b[i] = set(s[i]['tcp'].keys())  		if r.exists(i):  			less_port = a[i].difference(b[i])  			add_port = b[i].difference(a[i])  			if len(add_port)>0 and len(less_port)>0:  				msg = "%s port %s new open t   %s have closen" % (i, add_port, less_port)  				print msg  				r_log(msg)  			elif len(add_port)>0:  				msg = "%s port %s new open n" % (i, add_port)  				print msg  				r_log(msg)  			elif len(less_port)>0:  				msg = "%s port %s close n" % (i, less_port)  				print msg  				r_log(msg)  			else:  				print "%s port no change: %s , %s" % (i, a[i], b[i])  			set_info(i, s[i]['tcp'].keys())  		else:  			msg = "new host: %s port %s  openn" % (i, s[i]['tcp'].keys())  			print msg  			r_log(msg)  			set_info(i,s[i]['tcp'].keys())    def __main__():      scan_ips('192.168.1.211/28','20-8080')
Exit mobile version