对线上服务器进行端口扫描是一件很有用的事,可以验证你的防火墙规则,避免暴漏不需要的服务。也可以知道你机器上开了哪些服务,不用等乌云爆出来了才知道,有人黑进内网玩了好几个月。哈哈,真事,服务器被通过zabbix黑进来,开了一个socket5的进程,自由进出。反正,这玩意很有用,本着奉献精神,把代码放出来,共同学习。


        功能很简单,对服务器进行扫描,生成html格式的扫描结果,对扫描结果发邮件。格式方面做了点处理,定义端口白名单,正常端口显示绿色,异常端口显示红色。算是一种告警。对服务器进行全端口扫描是很耗时的一件事,每台6万多个端口,而且还取决于扫描机器到目标机的网络连接情况。受不了这个蜗牛速度,开发了第一版的单线程版本后,又实现了一个多进程的版本,果然爽了好多。整个人都好了……


mytools.py 这是定义的一个函数库,截取了用到的一个函数,这个sendemail的发邮件的函数,当然当前场景可以定义的一个文件中,不过,对程序按模块拆分是个好的习惯。哈哈,我有点pythonic了。

#-*- coding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.header import Header
def sendemail(sender,receiver,subject,content,smtpserver,smtpuser,smtppass):
    msg = MIMEText(content,'html','utf-8')#中文需参数‘utf-8',单字节字符不需要
    msg['Subject'] = Header(subject, 'utf-8')
    msg['From'] = '<%s>' % sender
    msg['To'] = ";".join(receiver)
    try:
        smtp = smtplib.SMTP()
        smtp.connect(smtpserver)
        smtp.login(smtpuser, smtppass)
        smtp.sendmail(sender, receiver, msg.as_string())
        smtp.quit()
    except Exception,e:
        print e


nmscan.py 实现端口扫描的程序,单线程版本,代码有点长,慎入

#!/usr/bin/python
#-*- coding:utf-8 -*-

import nmap
import re
import mytools as tool
import sys  

reload(sys)  
sys.setdefaultencoding('utf8')

def nmScan(hostlist,portrange,whitelist):
        p = re.compile("^(\d*)\-(\d*)$")
	if type(hostlist) != list:
            help()
        portmatch = re.match(p,portrange)
	if not portmatch:
            help()
        l = []
        for host in hostlist:
            result = ''
	    nm = nmap.PortScanner()
            tmp = nm.scan(host,portrange)
            result = result + "

ip地址:%s 主机名:[%s]  ......  %s


" %(host,tmp['scan'][host]['hostname'],tmp['scan'][host]['status']['state'])             try:                 ports = tmp['scan'][host]['tcp'].keys()             except KeyError,e:                 if whitelist:                     whitestr = ','.join(whitelist)                     result = result + "未扫到开放端口!请检查%s端口对应的服务状态" %whitestr                  else:                     result = result + "扫描结果正常,无暴漏端口"                     continue             for port in ports:                info = ''                if port not in whitelist:                    info = 'Alert:非预期端口  '                 else:                    info = 'Info:正常开放端口  '                portinfo = "%s port : %s   state : %s   product : %s 
" %(info,port,tmp['scan'][host]['tcp'][port]['state'],                                                                         tmp['scan'][host]['tcp'][port]['product'])                result = result + portinfo             l.append([host,str(result)]) return l def help(): print "Usage: nmScan(['127.0.0.1',],'0-65535')"  if __name__ == "__main__":      hostlist = ['10.10.10.10','10.10.10.11']     portrange = '0-65535'     whitelist = [80,443]     l = nmScan(hostlist,portrange,whitelist)     sender = '[email protected]'     receiver = ['[email protected]','[email protected]']     subject = '服务器端口扫描'     smtpserver = 'smtp.exmail.qq.com'     smtpuser = '[email protected]'     smtppass = 'gccmx163'     mailcontent = ''     for i in range(len(l)):         mailcontent = mailcontent + l[i][1]     tool.sendemail(sender,receiver,subject,mailcontent,smtpserver,smtpuser,smtppass)


mutinmscan.py 端口扫描的多进程版本,比照单线程版本最大的一个变化是nmscan函数的实现上,单线程传递一个服务器列表,在函数内部循环该列表,读取扫描结果,生成报告邮件。mutinmscan版的函数是接受一个ip地址,循环这一部分使用了mutiprocess库的Pool,并使用其map函数实现对服务器ip列表的迭代。多线程,一节更比五节强……

#!/usr/bin/python
#-*- coding:utf-8 -*-

import nmap
import re
import mytools as tool
import sys
from multiprocessing import Pool
from functools import partial

reload(sys)
sys.setdefaultencoding('utf8')

def nmScan(host,portrange,whitelist):
        p = re.compile("^(\d*)\-(\d*)$")
        # if type(hostlist) != list:
        #     help()
        portmatch = re.match(p,portrange)
        if not portmatch:
            help()

        if host == '121.42.32.172':
            whitelist = [25,]
        result = ''
        nm = nmap.PortScanner()
        tmp = nm.scan(host,portrange)
        result = result + "

ip地址:%s 主机名:[%s]  ......  %s


" %(host,tmp['scan'][host]['hostname'],tmp['scan'][host]['status']['state'])         try:             ports = tmp['scan'][host]['tcp'].keys()             for port in ports:                 info = ''                 if port not in whitelist:                    info = 'Alert:非预期端口  '                 else:                    info = 'Info:正常开放端口  '                 portinfo = "%s port : %s   state : %s   product : %s 
" %(info,port,tmp['scan'][host]['tcp'][port]['state'],                                                                       tmp['scan'][host]['tcp'][port]['product'])                 result = result + portinfo         except KeyError,e:             if whitelist:                 whitestr = ','.join(whitelist)                 result = result + "未扫到开放端口!请检查%s端口对应的服务状态" %whitestr                             else:                 result = result + "扫描结果正常,无暴漏端口"                    return result def help():         print "Usage: nmScan(['127.0.0.1',],'0-65535')"         return None if __name__ == "__main__":        hostlist = ['10.10.10.1','10.10.10.2']     pool = Pool(5)     nmargu = partial(nmScan,portrange='0-65535',whitelist=[])     results = pool.map(nmargu,hostlist)     #send email     sender = '[email protected]'     receiver = ['[email protected]',]     subject = '服务器端口扫描'     smtpserver = 'smtp.exmail.qq.com'     smtpuser = '[email protected]'     smtppass = 'gccmx163'     mailcontent = '
'.join(results)     tool.sendemail(sender,receiver,subject,mailcontent,smtpserver,smtpuser,smtppass)


扫描结果:马赛克阻碍了人类文明的进步,尤其是在欣赏岛国动作片的时候,但是,亲,我不能把俺们的服务器给你看的,你懂的!

Python 使用python-nmap模块实现端口扫描器_第1张图片