本文,介绍一种。通过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开启防火墙端口 python 防火墙_IP

三、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环境直接运行就行,人品好的大概率不报错。

Python开启防火墙端口 python 防火墙_Python开启防火墙端口_02

五、最终效果

以下代码,主要逻辑是:
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])

好啦,搞定。希望能帮到大家