python自动更新国内IP地址合集

注意:笔者使用的是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中

剩余余代码功能一致不做解释了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值