实现高效的端口扫描器
如今互联网安全形势日趋严峻,给系统管理员带来很大的挑战,网络的开放性以及黑客的攻击是造成网络不安全的主因。稍有疏忽将给黑客带来可乘之机,给企业带来无法弥补的损失。比如由于系统管理员误操作,导致核心业务服务器的 22、21、3389、3306 等高危端口暴露在互联网上,大大提高了被入侵的风险。因此,定制一种规避此安全事故的机制已经迫在眉睫。本节主要讲述通过 Python 的第三方模块 python-nmap 来实现高效的端口扫描,达到发现异常时可以在第一时间发现并处理,将安全风险降到最低的目的。python-nmap 模块作为 nmap 命令的 Python 封装,可以让 Python 很方便地操作 nmap 扫描器,它可以帮助管理员完成自动扫描任务和生成报告。
python-nmap 模块的安装方法如下:
# yum -y install nmap #安装nmap工具
# 模块源码安装
# wget http://xael.org/norman/python/python-nmap/python-nmap-0.1.4.tar.gz
# tar -zxvf python-nmap-0.1.4.tar.gz
# cd python-nmap-0.1.4
# python setup.py install
模块常用方法说明
本节介绍 python-nmap 模块的两个常用类,一个为 PortScanner() 类,实现一个 nmap 工具的端口扫描功能封装;另一个为 PortScannerHostDict() 类,实现存储与访问主机的扫描结果,下面介绍 PortScanner() 类的一些常用方法。
-
scan(self, hosts='127.0.0.1', ports=None,arguments='-sV') 方法,实现指定主机、端口、nmap 命令行参数的扫描。参数 hosts 为字符串类型,表示扫描的主机地址,格式可以用"scanme.nmap.org"、"198.116.0-255.1-127"、"216.163.128.20/20" 表示;参数 ports 为字符串类型,表示扫描的端口,可以用"22,53,110,143-4564" 来表示;参数 arguments 为字符串类型,表示 nmap 命令行参数,格式为 "-sU -sX -sC",例如:
nm = nmap.PortScanner() nm.scan('192.168.1.21-22','22,80') # command_line(self)方法,返回的扫描方法映射到具体nmap命令行,如: >>> nm.command_line() u'nmap -oX - -p 22,80-sV 192.168.1.21-22' # scaninfo(self)方法,返回nmap扫描信息,格式为字典类型,如: >>> nm.scaninfo() {u'tcp': {'services': u'22,80', 'method': u'syn'}} -
all_hosts(self) 方法,返回 nmap 扫描的主机清单,格式为列表类型,如:
[u'192.168.1.21', u'192.168.1.22']
以下介绍 PortScannerHostDict() 类的一些常用方法。
-
hostname(self) 方法,返回扫描对象的主机名,如:
>>> nm['192.168.1.22'].hostname() u'SN2013-08-022' -
state(self) 方法,返回扫描对象的状态,包括 4 种状态(up、down、unknown、skipped),如:
>>> nm['192.168.1.22'].state() u'up' -
all_protocols (self) 方法,返回扫描的协议,如:
>>> nm['192.168.1.22'].all_protocols() [u'tcp'] -
all_tcp() (self) 方法,返回 TCP 协议扫描的端口,如:
>>> nm['192.168.1.22'].all_tcp() [22, 80] -
tcp(self, port) 方法,返回扫描 TCP 协议 port(端口)的信息,如:
>>> nm['192.168.1.22'].tcp(22) {'state': u'open', 'reason': u'syn-ack', 'name': u'ssh'}
实践:实现高效的端口扫描
本次实践通过 python-nmap 实现一个高效的端口扫描工具,与定时作业 crontab 及邮件告警结合,可以很好地帮助我们及时发现异常开放的高危端口。当然,该工具也可以作为业务服务端口的可用性探测,例如扫描 192.168.1.20-25 网段 Web 服务端口 80 是否处于 open 状态。实践所采用的 scan() 方法的 arguments 参数指定为 "-v -PE -p '+端口",-v 表示启用细节模式,可以返回非 up 状态主机清单;-PE 表示采用TCP 同步扫描(TCP SYN)方式;-p 指定扫描端口范围。程序输出部分采用了三个 for 循环体,第一层遍历扫描主机,第二层为遍历协议,第三层为遍历端口,最后输出主机状态。具体实现代码如下:
Unresolved include directive in modules/ROOT/pages/section01/ch04/ch4-02.adoc - include::example$/第四章/python-nmap/simple1.py[]
其中主机输入支持所有表达方式,如 www.qq.com、192.168.1.*、192.168.1.1-20、192.168.1.0/24 等,端口输入格式也非常灵活,如80,443,22、80,22-443。代码运行结果如图4-3所示。
参考提示
-
Python-nmap 模块方法与参数说明参考 http://xael.org/norman/python/python-nmap/ 。示例源码参考官方源码包中的 example.py 。