對線上服務器進行端口掃描是一件很有用的事,可以驗證你的防火牆規則,避免暴漏不需要的服務。也可以知道你機器上開了哪些服務,不用等烏雲爆出來了才知道,有人黑進內網玩了好幾個月。哈哈,真事,服務器被通過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 + "<h2>ip地址:%s 主機名:[%s] ...... %s</h2><hr>" %(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 = '<strong><font color=red>Alert:非預期端口</font><strong> '
else:
info = '<strong><font color=green>Info:正常開放端口</font><strong> '
portinfo = "%s <strong>port</strong> : %s <strong>state</strong> : %s <strong>product<strong/> : %s <br>" %(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 = 'linuxidc163'
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 + "<h2>ip地址:%s 主機名:[%s] ...... %s</h2><hr>" %(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 = '<strong><font color=red>Alert:非預期端口</font><strong> '
else:
info = '<strong><font color=green>Info:正常開放端口</font><strong> '
portinfo = "%s <strong>port</strong> : %s <strong>state</strong> : %s <strong>product<strong/> : %s <br>" %(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 = 'linuxidc163'
mailcontent = '<br>'.join(results)
tool.sendemail(sender,receiver,subject,mailcontent,smtpserver,smtpuser,smtppass)
掃描結果:馬賽克阻礙了人類文明的進步,尤其是在欣賞島國動作片的時候,但是,親,我不能把俺們的服務器給你看的,你懂的!
--------------------------------------分割線 --------------------------------------
Python 用socket模塊實現檢測端口和檢測web服務 http://www.linuxidc.com/Linux/2013-06/86449.htm
CentOS上源碼安裝Python3.4 http://www.linuxidc.com/Linux/2015-01/111870.htm
《Python核心編程 第二版》.(Wesley J. Chun ).[高清PDF中文版] http://www.linuxidc.com/Linux/2013-06/85425.htm
《Python開發技術詳解》.( 周偉,宗傑).[高清PDF掃描版+隨書視頻+代碼] http://www.linuxidc.com/Linux/2013-11/92693.htm
Python腳本獲取Linux系統信息 http://www.linuxidc.com/Linux/2013-08/88531.htm
在Ubuntu下用Python搭建桌面算法交易研究環境 http://www.linuxidc.com/Linux/2013-11/92534.htm
Python 語言的發展簡史 http://www.linuxidc.com/Linux/2014-09/107206.htm
Python 的詳細介紹:請點這裡
Python 的下載地址:請點這裡