注意:笔者使用的是python3,Windows10系统,华为USG6300防火墙
背景:当职网络有国内出口跟海外出口(访问google)时,偶尔会遇到部分网站打不开或加载速度慢,大概率是访问国内资源从海外出口走,访问海外资源亦是如此,由于路由不准确导致,笔者之前通过IANA获取的地址合集路由命中率不高(云厂商真会玩),经过多番查找,在github上找到了相对准确的国内地址合集,大概每月更新一次,为什么是获取国内的地址合集,国内地址合集目前大约6千多条,海外合集几万条。
此教程为两篇(上篇基础使用,下篇相对代码偏多)
上篇为如何获取IP地址合集,如何将地址下发给设备
本篇为自动同步地址合集(自动对地址合集做增删操作)
代码如下:
import requests
from netmiko import ConnectHandler
import time
time1 = time.time()
new_time = time.strftime("%Y-%m-%d", time.localtime())
new_ip_list = []
dev_ip_list_01 = []
dev_ip_list_02 = []
dev_ip_list_all = []
add_address = []
delete_address = []
add_address_comm_01 = ['ip address-set IP-CN01 type object']
add_address_comm_02 = ['ip address-set IP-CN02 type object']
delete_address_comm_01 = ['ip address-set IP-CN01 type object']
delete_address_comm_02 = ['ip address-set IP-CN02 type object']
def get_new_ip_list():
url = 'https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt'
try:
header = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,'
'*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/96.0.4664.110 Safari/537.36',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2',
'Connection': 'keep-alive',
'path': '/17mon/china_ip_list/master/china_ip_list.tx'
}
r = requests.get(url, headers=header, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
new_ip_list_01 = r.text
with open(f'D:\\Python\\network\\update_ip_china\\new_ip\\new_ip_{new_time}.txt', 'w') as new_ip:
new_ip.write(new_ip_list_01)
new_ip_list_02 = new_ip_list_01.strip().split('\n')
for new_ip_list_03 in new_ip_list_02:
new_ip_list.append(new_ip_list_03)
print(f'最新国内IP地址条目为: {len(new_ip_list)}\n')
except Exception as e:
print(e)
def get_dev_ip_list():
try:
device = {'device_type': 'huawei', 'host': '10.100.0.200', 'username': 'python', 'password': '123456.com'}
ssh_client = ConnectHandler(**device)
print('开始获取防火墙现有国内IP地址集合')
ger_dev_ip_list_01 = ssh_client.send_command('display ip address-set verbose IP-CN01 item')
with open('ip_01.txt', 'w+') as ip01:
ip01.write(ger_dev_ip_list_01)
ger_dev_ip_list_02 = ssh_client.send_command('display ip address-set verbose IP-CN02 item')
with open('ip_02.txt', 'w+') as ip02:
ip02.write(ger_dev_ip_list_02)
except Exception as e:
print(e)
def format_add():
with open('ip_01.txt') as ip01:
ip01_2 = ip01.read().strip().replace(' mask ', '/').replace(' address ', '')
ip01_3 = ip01_2.split('\n')
for ip01_4 in ip01_3[7:]:
ip01_5 = ip01_4.split(' ')[1]
dev_ip_list_01.append(ip01_5)
dev_ip_list_all.append(ip01_5)
with open('ip_02.txt') as ip02:
ip02_2 = ip02.read().strip().replace(' mask ', '/').replace(' address ', '')
ip02_3 = ip02_2.split('\n')
for ip02_4 in ip02_3[7:]:
ip02_5 = ip02_4.split(' ')[1]
dev_ip_list_02.append(ip02_5)
dev_ip_list_all.append(ip02_5)
print(f'设备现有IP地址数:{len(dev_ip_list_all)}\n')
def get_add_address():
for new_ip_list_1 in new_ip_list:
if new_ip_list_1 not in dev_ip_list_all:
add_address.append(new_ip_list_1)
print(f'----需要更新的IP地址数为{len(add_address)}----\n')
def get_delete_address():
for dev_ip_list_all_1 in dev_ip_list_all:
if dev_ip_list_all_1 not in new_ip_list:
delete_address.append(dev_ip_list_all_1)
print(f'----需要删除的IP地址数为{len(delete_address)}----\n')
def add_dev_ip_address():
if len(add_address) >= 1:
ip_cn_01 = 3999 - len(dev_ip_list_01)
if ip_cn_01 >= 1:
for add_dev_ip_address_1 in add_address[:ip_cn_01]:
add_dev_ip_address_1_1 = add_dev_ip_address_1.replace('/', ' mask ')
add_address_comm_01.append(f'address {add_dev_ip_address_1_1}')
print(f'---------------需要更新IP-CN01的地址数为{len(add_address_comm_01) - 1}------------------\n')
if len(add_address) - ip_cn_01 >= 1:
for add_dev_ip_address_2 in add_address[ip_cn_01:]:
add_dev_ip_address_2_1 = add_dev_ip_address_2.replace('/', ' mask ')
add_address_comm_02.append(f'address {add_dev_ip_address_2_1}')
print(f'---------------需要更新IP-CN02的地址数为{len(add_address_comm_02) -1}------------------\n')
try:
device = {'device_type': 'huawei', 'host': '10.100.0.200', 'username': 'python', 'password': '123456.com'}
ssh_client = ConnectHandler(**device)
print('开始更新防火墙现有国内IP地址集合')
if len(add_address_comm_01) >= 2:
add_address_comm_01_log = ssh_client.send_config_set(add_address_comm_01)
print(f'------------下面是新增ip_cn_01命令日志------------------------\n{add_address_comm_01_log}')
if len(add_address_comm_02) >= 2:
add_address_comm_02_log = ssh_client.send_config_set(add_address_comm_02)
print(f'------------下面是新增ip_cn_02命令日志------------------------\n{add_address_comm_02_log}')
except Exception as e:
print(e)
def delete_dev_ip_address():
if len(delete_address) >= 1:
with open('ip_01.txt') as ip01:
ip01_2 = ip01.read().replace(' mask ', '/').replace(' address ', '')
ip01_3 = ip01_2.strip().split('\n')
for ip01_4 in ip01_3[7:]:
ip01_5 = ip01_4.split(' ')[1]
ip01_6 = ip01_4.split(' ')[0]
if ip01_5 in delete_address:
delete_address_comm_01.append(f'undo address {ip01_6}')
print(f'----ip_cn_01删除的地址数为{len(delete_address_comm_01[1:])}-----\n{delete_address_comm_01}\n')
with open('ip_02.txt') as ip02:
ip02_2 = ip02.read().replace(' mask ', '/').replace(' address ', '')
ip02_3 = ip02_2.strip().split('\n')
for ip02_4 in ip02_3[7:]:
ip02_5 = ip02_4.split(' ')[1]
ip02_6 = ip02_4.split(' ')[0]
if ip02_5 in delete_address:
delete_address_comm_02.append(f'undo address {ip02_6}')
print(f'-----ip_cn_02删除的地址数为{len(delete_address_comm_02[1:])}----\n{delete_address_comm_02}\n')
try:
device = {'device_type': 'huawei', 'host': '10.100.0.200', 'username': 'python', 'password': '123456.com'}
ssh_client = ConnectHandler(**device)
print('开始删除防火墙现有国内IP地址集合')
if len(delete_address_comm_01) >= 2:
delete_address_comm_01_log = ssh_client.send_config_set(delete_address_comm_01)
print(f'------------下面是删除ip_cn_01命令日志------------------------\n{delete_address_comm_01_log}')
if len(delete_address_comm_02) >= 2:
delete_address_comm_02_log = ssh_client.send_config_set(delete_address_comm_02)
print(f'------------下面是删除ip_cn_02命令日志------------------------\n{delete_address_comm_02_log}')
except Exception as e:
print(e)
if __name__ == '__main__':
get_new_ip_list()
get_dev_ip_list()
format_add()
get_add_address()
get_delete_address()
add_dev_ip_address()
delete_dev_ip_address()
print(time.time() - time1)
在防火墙上配置地址合集及选路策略
创建一个名为IP-CN 的地址组将IP-CN01 和 IP-CN02 添加到地址组中
创建策略路由
代码讲解:
在上篇中描述过的部分本文不在叙述。
import time
time1 = time.time()
new_time = time.strftime("%Y-%m-%d", time.localtime())
import time 导入时间模块,已经集成无需额外安装;
time1 = time.time() 记录脚本开始运行时间节点;
new_time = time.strftime("%Y-%m-%d", time.localtime()) 格式化当前时间(例:2021-12-12),创建日志文件会用到。
dev_ip_list_01 = []
dev_ip_list_02 = []
dev_ip_list_all = []
dev_ip_list_01 = [] dev_ip_list_02 = [] 分别记录设备上现有IP-CN01 和 IP-CN02的地址合集
dev_ip_list_all = [] 记录设备上现有的IP地址合集
add_address = []
add_address_comm_01 = ['ip address-set IP-CN01 type object']
add_address_comm_02 = ['ip address-set IP-CN02 type object']
add_address 记录设备需要新增的地址合集
add_address_comm_01 记录IP-CN01需要新增到的地址,ip address-set IP-CN01 type objec 进入配试图
add_address_comm_02 记录IP-CN02需要新增到的地址
delete_address = []
delete_address_comm_01 = ['ip address-set IP-CN01 type object']
delete_address_comm_02 = ['ip address-set IP-CN02 type object']
delete_address 记录设备需要删除的地址合集
delete_address_comm_01 记录IP-CN01需要删除的地址
delete_address_comm_02 记录IP-CN02需要删除的地址
def get_new_ip_list():
with open(f'D:\\Python\\network\\update_ip_china\\new_ip\\new_ip_{new_time}.txt', 'w') as new_ip:
new_ip.write(new_ip_list_01)
创建一个名为new_ip_{new_time}.txt 将获取的信息保存至指定路径方便日后查看,w 为覆盖写入。在python中 \ 为原字符,需要使用 \\ 为路径分隔符。
def get_dev_ip_list():
try:
device = {'device_type': 'huawei', 'host': '10.100.0.200', 'username': 'python', 'password': '123456.com'}
ssh_client = ConnectHandler(**device)
print('开始获取防火墙现有国内IP地址集合')
ger_dev_ip_list_01 = ssh_client.send_command('display ip address-set verbose IP-CN01 item')
with open('ip_01.txt', 'w+') as ip01:
ip01.write(ger_dev_ip_list_01)
ger_dev_ip_list_02 = ssh_client.send_command('display ip address-set verbose IP-CN02 item')
with open('ip_02.txt', 'w+') as ip02:
ip02.write(ger_dev_ip_list_02)
except Exception as e:
print(e)
登录设备查询 IP-CN01 和 IP-CN02 现有的地址,并在当前目录创建两个文件分别存储IP-CN01 和 IP-CN02 的内容,方便后期做计算。
def format_add():
with open('ip_01.txt') as ip01:
ip01_2 = ip01.read().strip().replace(' mask ', '/').replace(' address ', '')
ip01_3 = ip01_2.split('\n')
for ip01_4 in ip01_3[7:]:
ip01_5 = ip01_4.split(' ')[1]
dev_ip_list_01.append(ip01_5)
dev_ip_list_all.append(ip01_5)
with open('ip_02.txt') as ip02:
ip02_2 = ip02.read().strip().replace(' mask ', '/').replace(' address ', '')
ip02_3 = ip02_2.split('\n')
for ip02_4 in ip02_3[7:]:
ip02_5 = ip02_4.split(' ')[1]
dev_ip_list_02.append(ip02_5)
dev_ip_list_all.append(ip02_5)
print(f'设备现有IP地址数:{len(dev_ip_list_all)}\n')
将设备获取的地址格式化为 1.0.2.0/23 这种格式存入相应列表中,方便后期做计算
for ip01_4 in ip01_3[7:]: 从第七行开始截取,前7行为相关提示,如下图
def get_add_address():
for new_ip_list_1 in new_ip_list:
if new_ip_list_1 not in dev_ip_list_all:
add_address.append(new_ip_list_1)
print(f'----需要更新的IP地址数为{len(add_address)}----\n')
计算设备需要新增的地址合集,并存入 add_address 列表中
def get_delete_address():
for dev_ip_list_all_1 in dev_ip_list_all:
if dev_ip_list_all_1 not in new_ip_list:
delete_address.append(dev_ip_list_all_1)
print(f'----需要删除的IP地址数为{len(delete_address)}----\n')
计算设备需要删除的地址合集,并存入 delete_address 列表中
def add_dev_ip_address():
if len(add_address) >= 1:
ip_cn_01 = 3999 - len(dev_ip_list_01)
if ip_cn_01 >= 1:
for add_dev_ip_address_1 in add_address[:ip_cn_01]:
add_dev_ip_address_1_1 = add_dev_ip_address_1.replace('/', ' mask ')
add_address_comm_01.append(f'address {add_dev_ip_address_1_1}')
print(f'---------------需要更新IP-CN01的地址数为{len(add_address_comm_01) - 1}------------------\n')
if len(add_address) - ip_cn_01 >= 1:
for add_dev_ip_address_2 in add_address[ip_cn_01:]:
add_dev_ip_address_2_1 = add_dev_ip_address_2.replace('/', ' mask ')
add_address_comm_02.append(f'address {add_dev_ip_address_2_1}')
print(f'---------------需要更新IP-CN02的地址数为{len(add_address_comm_02) -1}------------------\n')
if len(add_address) >= 1: 当 add_address 中的地址个数大于1才对设备进行操作
ip_cn_01 = 3999 - len(dev_ip_list_01) 由于每个地址合集最大数量为3999,首先查看IP-CN01中地址数是不是3999个,如果个数小于 3999 才向IP-CN01 下发新增地址
for add_dev_ip_address_1 in add_address[:ip_cn_01]: 从列表中截取指定的值,假如 IP-CN01个位为3990,(3999 - 3990 = 9 )此时从 add_address 取前9个地址集。
add_dev_ip_address_1_1 = add_dev_ip_address_1.replace(’/’, ’ mask ‘) add_address_comm_01.append(f’address {add_dev_ip_address_1_1}’)
上述两行代码,将的到的地址,格式为设备能接受的格式类型 例如:address 1.0.2.0 mask 23
if len(add_address) - ip_cn_01 >= 1: 向 IP-CN01 中添加完成后还有剩余的地址合集才下发至IP-CN02
for add_dev_ip_address_2 in add_address[ip_cn_01:]: 从列表中截取指定的值,IP-CN01截取完成后还有剩余地址,剩余地址会下发至IP-CN02 中
try:
device = {'device_type': 'huawei', 'host': '10.100.0.200', 'username': 'python', 'password': '123456.com'}
ssh_client = ConnectHandler(**device)
print('开始更新防火墙现有国内IP地址集合')
if len(add_address_comm_01) >= 2:
add_address_comm_01_log = ssh_client.send_config_set(add_address_comm_01)
print(f'------------下面是新增ip_cn_01命令日志------------------------\n{add_address_comm_01_log}')
if len(add_address_comm_02) >= 2:
add_address_comm_02_log = ssh_client.send_config_set(add_address_comm_02)
print(f'------------下面是新增ip_cn_02命令日志------------------------\n{add_address_comm_02_log}')
except Exception as e:
print(e)
开始对设备设备下发新增地址合集
if len(add_address_comm_01) >= 2: 为什么是2了,列表中第一条命令为 ip address-set IP-CN01 type object 进入地址集配置视图,长度需要大于或等于2才会对 IP-CN01 地址集操作。
def delete_dev_ip_address():
if len(delete_address) >= 1:
with open('ip_01.txt') as ip01:
ip01_2 = ip01.read().replace(' mask ', '/').replace(' address ', '')
ip01_3 = ip01_2.strip().split('\n')
for ip01_4 in ip01_3[7:]:
ip01_5 = ip01_4.split(' ')[1]
ip01_6 = ip01_4.split(' ')[0]
if ip01_5 in delete_address:
delete_address_comm_01.append(f'undo address {ip01_6}')
print(f'----ip_cn_01删除的地址数为{len(delete_address_comm_01[1:])}-----\n{delete_address_comm_01}\n')
with open('ip_02.txt') as ip02:
ip02_2 = ip02.read().replace(' mask ', '/').replace(' address ', '')
ip02_3 = ip02_2.strip().split('\n')
for ip02_4 in ip02_3[7:]:
ip02_5 = ip02_4.split(' ')[1]
ip02_6 = ip02_4.split(' ')[0]
if ip02_5 in delete_address:
delete_address_comm_02.append(f'undo address {ip02_6}')
print(f'-----ip_cn_02删除的地址数为{len(delete_address_comm_02[1:])}----\n{delete_address_comm_02}\n')
华为删除地址集中的命令为地址集的编号 例:undo address 100
将地址格式化 例: 100 1.0.2.0/23 第一段为地址集编号,第二段为IP地址段
ip01_5 = ip01_4.split(’ ')[1] 截取第二段 1.0.2.0/23
ip01_6 = ip01_4.split(’ ')[0] 截取第一段 100
if ip01_5 in delete_address: 如果该地址在合集 IP-CN01 将生成对应的删除命令,添加至列表delete_address_comm_01中
剩余余代码功能一致不做解释了。