一、基于python的防火墙自动化验证小工具
#!/usr/bin/env python
#coding:utf-8
import paramiko
import sys
import getpass
username=raw_input("Please give a usrname:")
password=getpass.getpass("Please input puhuiop's password:")
def ssh(sys_ip,username,password,cmds):
try:
#创建ssh客户端
client = paramiko.SSHClient()
#第一次ssh远程时会提示输入yes或者no
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#密码方式远程连接
client.connect(sys_ip, 22, username=username, password=password, timeout=2000)
#执行命令,远程命令的执行其实是stderr,所以这里取stderr的值,这里还有待学习
stdin, stdout,stderr = client.exec_command(cmds)
print(stderr.read().strip())
except Exception, e:
print e
finally:
client.close()
if __name__=="__main__":
sys_ip='XX.XX.XX.XX'
sip=sys.argv[1]
port=sys.argv[2]
cmds = "echo '\n'|telnet %s %s |grep 'connected' |tail -n 1 1>&1" %(sip,port)
ssh(sys_ip,username,password,cmds)
运行命令:python 脚本名 目标IP 目标端口
再输入用户名和密码,回车会输出运行结果,closed表示通的。
远程登录主机部分小结:
1、使用python的getpass模块,可以在输入密码不将密码显示在屏幕上,即不回显;
2、这里使用sys模块实现传参,但这种时候,IP和端口分别只能传单个值,我们验墙时通常都是批量的,需要考虑如何批量传参
二、使用argparse位置参数进行批量传参
1、期望输入多个源IP、多个目标、多个端口
2、脚本目前放置于堡垒机,期望源端也可以是系统名,使用squery命令来获取系统对应部署单元的IP;
import argparse
parser = argparse.ArgumentParser()
#源端IP
parser.add_argument('-s','--sip',help="Source ip", nargs = '+')
#目标IP
parser.add_argument('-d','--dip',help="Target IP", nargs = '+')
#目标端口
parser.add_argument('-p','--port',help="Target PORT", nargs = '+')
#系统名(下划线形式)
parser.add_argument('--sys',help="System NAME(eg:ph_yxd_pms)" )
args = parser.parse_args()
##取值实例
print (arfs.sip,args.dip,args.port)
脚本运行命令:
python ver4.py -s 源ip1 源ip2 .. .. -d 目标ip1 目标ip2 .. .. -p 端口1 端口2 .. ..
或:
python ver4.py --sip 源ip1 源ip2 .. .. --dip 目标ip1 目标ip2 .. .. --port 端口1 端口2 .. ..
三、利用itertools模块得到列表之间的笛卡尔积:源地址、目标地址、端口分别有多个时,如何不遗漏地测试每个源地址到每个目标地址、每个端口的防火墙(笛卡尔积)。
def cartesian(sips,dips,ports):
for x in itertools.product(sips,dips,ports):
if __name__=="__main__":
##itertools生成的每行数据其实是元组形式(源IP,目标IP,端口IP)
sys_ip=x[0]
sys2_ip= x[1]
sys2_port= x[2]
cmds = "echo '\n'|telnet %s %s |grep 'connected' |tail -n 1 1>&1" % (sys2_ip,sys2_port)
ssh(sys_ip,username,password,cmds,sys2_ip,sys2_port)
笛卡尔积结果示例:
四、传参优化及参数判断
1、有时候我们源端地址可能不局限与一个系统,源端IP非常多时,期望可以将这些IP以文件形式进行传参,所以利用python的open内置函数来读取文件,再将内容以列表形式传给上述生成笛卡尔积的方法;需要新增一个位置参数来接收文件。
2、参数判断
上述可以发现,源端地址的传参类型有IP(列表)、系统名(字符串)、文件名(文件),根据类型来确定该如何处理传入的源端地址:
列表:直接调用生成笛卡尔积的方法cartesian
系统名:先使用squery命令获取系统实例,生成列表,再调用cartesian方法
文件名:先读文件内容,生成列表,再调用cartesian方法
五、全量代码及传参说明
#!/usr/bin/env pythons
#coding:utf-8
import sys
import os
import paramiko
import argparse
import itertools
import getpass
username=raw_input("Please input a username: ")
password=getpass.getpass("Please input password: ")
'''
对远程执行命令的结果进行处理
'''
def result(sentence,sys_ip,sys2_ip,sys2_port):
if 'closed' in sentence:
print(sys_ip+' connected to '+sys2_ip +' '+ sys2_port+' is True')
elif 'timed' in sentence:
print(sys_ip+' connected to '+sys2_ip +' '+sys2_port +' is timed out')
elif 'refused' in sentence:
print(sys_ip+' connected to '+sys2_ip +' ' +sys2_port +' is refused')
else:
print('False')
'''
远程登录验证防火墙实现方法
'''
def ssh(sys_ip,username,password,cmds,sys2_ip,sys2_port):
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(sys_ip, 22, username=username, password=password, timeout=2000)
stdin, stdout,stderr = client.exec_command(cmds)
#print(stderr.read().strip())
sentence=stderr.read().strip()
result(sentence,sys_ip,sys2_ip,sys2_port)
except Exception, e:
print e
finally:
client.close()
'''
进行笛卡尔积计算(元组类型)
'''
def cartesian(sips,dips,ports):
for x in itertools.product(sips,dips,ports):
if __name__=="__main__":
sys_ip=x[0]
sys2_ip= x[1]
sys2_port= x[2]
cmds = "echo '\n'|telnet %s %s |grep 'connected' |tail -n 1 1>&1" % (sys2_ip,sys2_port)
ssh(sys_ip,username,password,cmds,sys2_ip,sys2_port)
'''
处理传参,调用防火墙方法
'''
parser = argparse.ArgumentParser()
parser.add_argument('-s','--sip',help="Source ip", nargs = '+')
parser.add_argument('--sys',help="System NAME(eg:ph_yxd_pms)" )
parser.add_argument('-f','--files',help="Source ip's File")
parser.add_argument('-d','--dip',help="Target IP", nargs = '+')
parser.add_argument('-p','--port',help="Target PORT", nargs = '+')
args = parser.parse_args()
if isinstance(args.sys,str):
cmds="~/bin/servicetool squery -l |grep %s |grep -v -i 'PADIS' |grep -v -i 'docker'|grep -v -i 'openresty' |awk -F '.' '{print $1}'" %args.sys
units=os.popen(cmds).read().split()
for i in range(len(units)):
print(units[i])
cmd="~/bin/servicetool squery -s %s 2>/dev/null |grep [0-9]|awk -F ':' '{print $1}'" %units[i]
val=os.popen(cmd).read().splitlines()
cartesian(val,args.dip,args.port)
elif isinstance(args.sip,list):
cartesian(args.sip,args.dip,args.port)
elif os.path.exists(args.files):
f = open(args.files, 'r')
val=f.read().decode('utf-8').splitlines()
f.close()
cartesian(filter(None,val),args.dip,args.port)
传参方式:
python ver4.py --sys 系统名(下划线)-d 目标IP –p目标端口
python ver4.py --sys 系统名(下划线)--dip 目标IP --port目标端口
python ver4.py -s 源ip1 源ip2 .. -d 目ip1 目ip1 .. -p 端口1 端口2 ..
python ver4.py -f 文件名(绝对路径或者相对路径)-d 目ip1 目ip1 .. -p 端口1 端口2 ..
说明:
以上目标IP,既可以是IP地址,也可以是F5域名。
网友评论