4.2 实现高效的端口扫描器 python-nmap
如今互联网安全形势日趋严峻,给系统管理员带来很大的挑战,网络的开放性以及黑客的攻击是造成网络不安全的主因,稍有疏忽将给黑客带来可乘之机,给企业带来无法弥补的损失,比如由于系统管理员误操作,导致核心业务服务器的22,21,3389,3306等高危端口暴露在互联网上,大大提高了被入侵的风险,因此,定制一种规避此安全事故的机制已经迫在眉睫,本节主要讲述通过python的第三方模块python-nmap来实现高效的端口扫描,达到发现异常时可以再第一时间发现并处理,将安全风险降到最低的目的,python-nmap模块作为nmap命令的python封装,可以让Python很方便的操作nmap扫描器,他可以帮助管理员完成自动扫描任务和生成报告,
1.安装:
[root@mankel py] yum -y install nmap
[root@mankel py] pip3 install python-nmap
[root@mankel py] python3
>>> import nmap
4.2.1 模块常用方法说明
本节介绍python-nmap模块的两个常用类,一个为PortScanner()类,实现一个nmap工具的端口扫描功能封装;另一个为PortScannerHostDict()类,实现存储与访问主机的扫描结果,
下面介绍一些常用方法:
import nmap # 导入 nmap.py 模块
nm = nmap.PortScanner() # 获取 PortScanner 对象
nm.scan('127.0.0.1', '22-443') # 扫描主机 127.0.0.1 端口号 22-443
# nm.scan(self, hosts='127.0.0.1', ports=None, arguments='-sV')
# hosts字符串类型,格式:"scanme.nmap.org"、"192.116.0-255.1-127"、"216.163.128.20/20"
# ports字符串类型,格式:"22,53,110,143-4564"
# arguments: -sS -sU -sC等
nm.command_line() # 获取用于扫描的命令行:nmap -oX - -p 22-443 127.0.0.1
nm.scaninfo() # 获取本次扫描的信息 {'tcp': {'services': '22-443', 'method': 'connect'}}
nm.all_hosts() # 获取所有扫描到的主机
nm['127.0.0.1'].hostname() # 获取 127.0.0.1 的主机名
nm['127.0.0.1'].hostnames() # 获取list格式的主机名dict 127.0.0.1 # 如 [{'name':'hostname1', 'type':'PTR'}, {'name':'hostname2', 'type':'user'}]
nm['127.0.0.1'].state() # 获取主机 127.0.0.1 的状态 (up|down|unknown|skipped)
nm['127.0.0.1']['tcp'].keys() # 获取所有tcp端口
nm['127.0.0.1'].all_tcp() # 获取所有tcp端口 (已排序)
nm['127.0.0.1'].all_udp() # 获取所有udp端口 (已排序)
nm['127.0.0.1'].all_ip() # 获取所有ip端口 (已排序)
nm['127.0.0.1'].all_sctp() # 获取所有sctp端口 (已排序)
nm['127.0.0.1'].has_tcp(22) # 是否含有主机 127.0.0.1 的 22 端口的信息
nm['127.0.0.1']['tcp'][22] # 获取主机 127.0.0.1 22 端口(tcp)的所有信息
nm['127.0.0.1'].tcp(22) # 获取主机 127.0.0.1 22 端口的所有信息
nm['127.0.0.1'].all_protocols() #获取扫描的协议
4.2.2 实践: 实现高效的端口扫描
本次实践通过python-nmap实现一个高效的端口扫描工具,与定时作业crontab及邮件告警结合,可以很好的帮助我们及时发现异常开放的高危端口,当然,该工具也可以作为业务服务端口得可用性探测,例如扫描192.168.1.20-25网段Web服务端口80是否处于open状态,实践所采用的scan()方法的arguments参数指定为"-v -PE -p’+端口",-v表示启用细节模式,可以返回非Up状态主机清单;-PE表示采用TCP同步扫描(TCP,SYN)方式;-p指定扫描端口范围,程序输出部分采用了三个for循环体,第一层遍历扫描主机,第二层为遍历协议,第三层为遍历端口,最后输出主机状态,具体实现代码如下:
1.代码:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import nmap
scan_row = []
input_data = input('Please input hosts and port: ')
scan_row = input_data.split(" ")
if len(scan_row)!=2:
print("Input errors,example \"192.168.0.0 80,443,22\"")
sys.exit(0)
hosts = scan_row[0]
port = scan_row[1]
try:
nm = nmap.PortScanner()
except nmap.PortScannerError:
print('Nmap not found', sys.exc_info()[0])
sys.exit(0)
except:
print("Unexpected error:", sys.exc_info()[0])
sys.exit(0)
try:
nm.scan(hosts=hosts, arguments=' -v -sS -p '+port)
except Exception as e:
print("Scan erro:"+str(e))
for host in nm.all_hosts():
print("----------------------------------------------------------")
print('Host : %s (%s)' % (host, nm[host].hostname()))
print('State : %s' % nm[host].state())
for proto in nm[host].all_protocols():
print('-------------')
print('Protocol : %s' % proto)
lport = nm[host][proto].keys()
for port in lport:
print('port : %s\tstate : %s' % (port, nm[host][proto][port]['state']))
2.代码运行结果: