本文,介绍一种。通过Django框架,搭建API服务器,并通过此API服务器管理华为防火墙。并以此衍生出,通过Django+Python+ssh的方式管理网络设备的方法。
关于Django环境的搭建,请参照逗老师之前的一篇文章。
搭建完环境之后,设计以下Python脚本,并import到Django的views中。
我们通过下面这个脚本举例,,主要说明一下如何通过Python脚本远程ssh登录网络设备,并进行配置。
下面这个脚本实现的功能是对指定的address-set对象组添加IP地址,实现防火墙策略的自动化管理。
例如某台服务器默认不允许所有流量访问,但是通过OA系统审批后,可以指定添加某个IP访问此服务器。通过此Python脚本可以实现自动对防火墙进行配置的目的。
目录
- 一、防火墙域间策略和address-set对象组
- 二、H3C、HUAWEI 设备开启ssh登录功能
- 三、python paramiko模块ssh登录网络设备
- 四、python paramiko模块回显抓取
- 五、最终效果
一、防火墙域间策略和address-set对象组
对于防火墙的域间策略,通常会引用地址组
作为策略生效对象。华为叫做address-set,华三叫做object-group,都是一个意思。
例如下面这个策略,表示源地址在NAT_Internet
地址组内IP,可以出网访问Internet。
#
security-policy
rule name trust_出网NAT访问Internet
source-zone trust
destination-zone untrust
source-address address-set NAT_Internet
action permit
#
ip address-set NAT_Internet type group
description NAT访问Internet允许源主机组
address 0 172.16.64.69 mask 32
因此,我们在自动化运维之前,配置好域间策略和address-set地址组。后续只需要对address-set地址组追加地址即可。
二、H3C、HUAWEI 设备开启ssh登录功能
H3C配置举例
#
ssh server enable
#
local-user admin class manage
password hash $h$6$f+j7WzEYItlWRcVKQ==
service-type ssh terminal https
authorization-attribute user-role level-3
authorization-attribute user-role network-admin
authorization-attribute user-role network-operator
#
line vty 0 63
authentication-mode scheme
user-role network-admin
#
HUAWEI配置举例
#
stelnet ipv4 server enable
#
aaa
local-user admin password irreversible-cipher $1a$\V >WBN:~2SM3gq!y6$
local-user admin privilege level 15
local-user admin service-type terminal ssh http
#
user-interface vty 0 4
authentication-mode aaa
protocol inbound ssh(all)
#注意,华为的user-interface接口下需要绑定入站协议,可以选择all,也可以只选ssh或者telnet
user-interface vty 16 20
#
验证ssh登录
三、python paramiko模块ssh登录网络设备
下面代码片段举例介绍,如何通过paramiko模块ssh登录网络设备。
paramiko模块需要单独安装,安装命令
pip install paramiko
如果想通过Python登录设备执行一些命令(比如 reboot),以下代码片段就够了。
import paramiko
import time
import re
import sys
client = paramiko.SSHClient()
client.load_system_host_keys()
know_host = paramiko.AutoAddPolicy()
client.set_missing_host_key_policy(know_host)
client.connect('192.168.0.1',22,'admin','password',allow_agent=False,look_for_keys=False)
#这里改成你设备的IP地址和用户名密码
# get shell
ssh_shell = client.invoke_shell()
# ready when line endswith '>' or other character
while True:
line = ssh_shell.recv(1024)
if line and str(line).endswith(">'"):#登录后等待设备出现>标识,稳定后输入命令
break;
# 发送命令
ssh_shell.sendall( 'ping 127.0.0.1' + '\n')
四、python paramiko模块回显抓取
如果对执行的命令还需要抓取回显,则需要要追加几行简单的代码。
paramiko的回显抓取深究起来可以专门出一篇文章,涉及ssh管道、字符编码,tcp传输期间的占位符等等。我们这里不深究,直接上一个例子大家拿去用就好了。
# send command
ssh_shell.sendall( 'ping 127.0.0.1' + '\n')
# get result lines
lines = []
while True:
line = ssh_shell.recv(1024)
if line and str(line).endswith(">'"):
break;
lines.append(line.decode(encoding='utf-8', errors='strict'))
result = ''.join(lines).replace('\r\r','').split('\n')
for i in result:
print(i)
如此,我们得到了一个list类型的返回值,其中存放着ssh命令回显的每一行,每行占一个元素。
中间插个print,检验一下结果:
上面两行代码,拼在一起,找个python环境直接运行就行,人品好的大概率不报错。
五、最终效果
以下代码,主要逻辑是:
1、传入一个或多个IP地址组,中间用分号分割,例如192.168.1.1;192.168.1.2;192.168.1.3。之后用分号作为切片关键字。
2、传入申请人名字,作为description添加到防火墙的命令里
3、传入防火墙设备IP,也可以支持多台设备一起配置。
4、ssh登录设备,等待指定字符串出现后,输入命令
5、通过传入的参数,构建出address x.x.x.x mask 32 description xxxx
的命令行,向address-set中添加记录
6、对所有传入的IP地址,逐个IP通过dis ip address-set address x.x.x.x
命令检查是否添加成功。找到该IP地址认为添加成功。
7、返回值,0成功。任何一个IP地址没找到,返回值>0,表示不成功。
具体的解释,看注释
# encoding=utf-8
import datetime
import re
import sys
import time
import requests
import paramiko
import time
client = paramiko.SSHClient()
client.load_system_host_keys()
know_host = paramiko.AutoAddPolicy()
client.set_missing_host_key_policy(know_host)
#等待指定字符串
#对于网络设备,等待>出现的时候,表示命令行定位到了可以输入命令的状态
def check_CLI_str(ssh_shell,str):
while True:
line = ssh_shell.recv(1024)
#print line
if line and line.decode(encoding='utf-8', errors='strict').endswith(str):
break;
def add_Internet_IP(deviceip,ip_list,username):
# connect to client
client.connect(deviceip,1500,'admin','passwordn',allow_agent=False,look_for_keys=False)
# get shell
ssh_shell = client.invoke_shell()
# 需要等待">"字符出现
check_CLI_str(ssh_shell,'>')
#开始输入命令,进行设备配置
ssh_shell.sendall( 'system' + '\n')
#进入system视图后,需要等待"]"字符出现
check_CLI_str(ssh_shell,']')
# 进入address-set视图
ssh_shell.sendall( 'ip address-set NAT_Internet type group' + '\n')
# 添加所有的IP地址,掩码长度/32
for ip in ip_list:
ssh_shell.sendall( 'address %s mask 32 description %s'%(ip,username) + '\n')
check_CLI_str(ssh_shell,']')
ssh_shell.sendall( 'quit' + '\n')
ssh_shell.sendall( 'quit' + '\n')
check_CLI_str(ssh_shell,'>')
result_int=0
# 检查所有的IP地址是否添加成功
for ip in ip_list:
ssh_shell.sendall( 'dis ip address-set address %s'%ip + '\n')
lines = []
while True:
line = ssh_shell.recv(1024)
if line and line.decode(encoding='utf-8', errors='strict').endswith('>'):
break;
lines.append(line.decode(encoding='utf-8', errors='strict'))
result = ''.join(lines)
if 'NAT_Internet' in result:
#成功,result_int不变
result_int=result_int
else:
#成功,result_int+1
result_int=result_int+1
return result_int
def Firewall_Add_Internet_IP(ip_list_str,username):
try:
ip_list=ip_list_str.split(';')
#多台设备依次执行
run_result_1=add_Internet_IP('10.168.254.130',ip_list,username)
run_result_2=add_Internet_IP('10.168.255.130',ip_list,username)
#统计多台设备的添加结果
run_result=run_result_1+run_result_2
except Exception as err:
raise err
else:
return run_result
if __name__ == '__main__':
#运行脚本的时候传入两个系统变量
Firewall_Add_Internet_IP(sys.argv[1],sys.argv[2])
好啦,搞定。希望能帮到大家