Изменена структура списка выгрузки, добавлено конфигурирование community. Проверка коректности через временный файл на пустоту. Выгрузка всей маршрутизации в единый файл, подключение в bird2 через m4.

This commit is contained in:
2025-11-19 11:40:37 +10:00
parent d83e04af9d
commit 38633c9146
2 changed files with 96 additions and 49 deletions

View File

@@ -8,7 +8,19 @@ import net_tree
import requests
# компилируем регулярку поиска ipv4 адреса
ipv4_find_str=re.compile(r"[^0-9.]?(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]|[0-9])\.(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]|[0-9])\.(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]|[0-9])(/([0-9]{1}[0-9]*))?[^0-9.]?")
ipv4_find_str=re.compile(r"[^0-9.]?(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]|[0-9])\.(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]|[0-9])\.(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]|[0-9])\.(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]|[0-9])(/([0-9]{1}[0-9]*))?[^0-9.]?")
# заголовок HTTP запроса
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
}
# метод сбора словаря ip адресов ipv4 из текста
def ipv4_find(strip:str, size:int):
@@ -65,7 +77,7 @@ def list_ip(c_dict: dict = []):
# бежим весь список ссылок пока не код 200
for c_url in c_list['url']:
try:
if (result:=requests.get(c_url)) and result.status_code == 200 and result.text:
if (result:=requests.get(c_url, headers=headers)) and result.status_code == 200 and result.text:
print(f"URL: {c_url}")
# пополняем словарь ipv4_list
if ipv4: ipv4_list.update(ipv4_find(result.text,ipv4))
@@ -99,7 +111,7 @@ def list_ip(c_dict: dict = []):
# более мягкое сжатие
Root.collapse(1,Root.real_ip_records_count)
# возвращаем результат
ipv4_list:str=Root.returnCollapsedTree('route {addr}/{masklen} blackhole;')
ipv4_list:str=Root.returnCollapsedTree(' route {addr}/{masklen} blackhole;')
else:
ipv4_list:bool=False
@@ -129,7 +141,7 @@ if __name__ == "__main__":
try:
# если файл list ссылка, загружаем и парсим его
with open(list_file, "r") as file:
if (result:=requests.get(url_list_file:=file.readline().strip())) and result.status_code == 200 and result.text:
if (result:=requests.get(url_list_file:=file.readline().strip(), headers=headers)) and result.status_code == 200 and result.text:
ip_list = ast.literal_eval(result.text)
print(f"Список выгрузки по url: {url_list_file}")
except requests.exceptions.MissingSchema:
@@ -162,27 +174,44 @@ if __name__ == "__main__":
outdir=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'unloading')
if not os.path.exists(outdir):
os.makedirs(outdir,exist_ok=True)
# создаём временный файл, перед выгрузкой
open(ipv4_out_file := f"{outdir}/bird2_v4.m4.tmp", "w").close()
open(ipv6_out_file := f"{outdir}/bird2_v6.m4.tmp", "w").close()
# обходим массив списков для выкрузки
for clist in ip_list:
# имена выходых файлов
ipv4_out_file=f"{outdir}/{clist.lower()}_v4.txt"
ipv6_out_file=f"{outdir}/{clist.lower()}_v6.txt"
# вычисляем кол-во записей прошлой выгрузки
ipv4_count_old = sum(1 for line in open(ipv4_out_file)) if os.path.isfile(ipv4_out_file) else 0
ipv6_count_old = sum(1 for line in open(ipv6_out_file)) if os.path.isfile(ipv6_out_file) else 0
# выполняем выгрузку
print(f"Выгружаю список IP: {clist}")
ipv4_list, ipv6_list=list_ip(ip_list[clist])
ipv4_list, ipv6_list=list_ip(ip_list[clist]['list'])
# сохраняем ipv4
if ipv4_list and len(ipv4_list.splitlines()) >= ipv4_count_old * 0.5:
if ipv4_list:
# собираем комьюнити маршрутов
bgp_community=str()
for c in str(ip_list[clist]['community']).split(","):
bgp_community+=f"bgp_community.add(({str(c).replace(":",",")})); "
# сохраняем в файл
with open(ipv4_out_file, "w") as file:
file.write(ipv4_list)
print(f"Файл {ipv4_out_file} сохранён")
with open(ipv4_out_file, "a") as file:
file.write(f"protocol static static_{clist.lower()} {{\n ipv4 {{ import filter {{ {bgp_community}accept; }}; }};\n{ipv4_list}}}\n")
print(f"Временный файл {ipv4_out_file} создан")
# проверяем, что файл не пустой, сохраняем в постоянный
if os.path.exists(ipv4_out_file) and os.path.getsize(ipv4_out_file) != 0:
print(f"Новый файл выгрузки ipv4 премененён")
os.replace(ipv4_out_file, ipv4_out_file.removesuffix(".tmp"))
# bird2 reload
os.system("systemctl reload bird.service")
# сохраняем ipv6
if ipv6_list and len(ipv6_list.splitlines()) >= ipv6_count_old * 0.5:
if ipv6_list:
# собираем комьюнити маршрутов
bgp_community=str()
for c in str(ip_list[clist]['community']).split(","):
bgp_community+=f"bgp_community.add(({str(c).replace(":",",")})); "
# сохраняем в файл
with open(ipv6_out_file, "w") as file:
file.write(ipv6_list)
print(f"Файл {ipv6_out_file} сохранён")
with open(ipv6_out_file, "a") as file:
file.write(f"protocol static static_{clist.lower()} {{\n ipv6 {{ import filter {{ {bgp_community}accept; }}; }};\n{ipv6_list}}}\n")
print(f"Временный файл {ipv6_out_file} создан")
# проверяем, что файл не пустой, сохраняем в постоянный
if os.path.exists(ipv6_out_file) and os.path.getsize(ipv6_out_file) != 0:
print(f"Новый файл выгрузки ipv6 премененён")
os.replace(ipv6_out_file, ipv6_out_file.removesuffix(".tmp"))
# bird2 reload
os.system("systemctl reload bird.service")
print("")

34
list
View File

@@ -1,5 +1,13 @@
{
'RU': [
'DEFAULT': {
'community': '65432:LOCATION,65432:1000',
'list': [
{ 'static4': '0.0.0.0/0,0.0.0.0/0', 'ipv4': True, 'ipv6': False },
]
},
'RU': {
'community': '65432:LOCATION,65432:200',
'list': [
# Большая часть RU сегмента
{ 'url': ['https://stat.ripe.net/data/country-resource-list/data.json?resource=RU'], 'ipv4': True, 'ipv6': False },
{ 'url': ['https://ipv4.fetus.jp/ru.txt'], 'ipv4': True, 'ipv6': False },
@@ -8,25 +16,35 @@
{ 'url': ['https://bgp.he.net/AS51115#_prefixes', 'https://ipinfo.io/widget/demo/AS51115?dataset=asn', 'https://api.hackertarget.com/aslookup/?q=AS51115'], 'ipv4': True, 'ipv6': False },
# STATIC
{ 'static4': '188.130.255.0/24', 'ipv4': True, 'ipv6': False },
],
'CHINA': [
]
},
'CHINA': {
'community': '65432:LOCATION,65432:201',
'list': [
# Большая часть CH сегмента
{ 'url': ['https://stat.ripe.net/data/country-resource-list/data.json?resource=CN'], 'ipv4': True, 'ipv6': False },
{ 'url': ['https://ipv4.fetus.jp/cn.txt'], 'ipv4': True, 'ipv6': False },
{ 'url': ['https://github.com/ipverse/rir-ip/blob/master/country/cn/aggregated.json'], 'ipv4': True, 'ipv6': False },
],
'JAPAN': [
]
},
'JAPAN': {
'community': '65432:LOCATION,65432:202',
'list': [
# Большая часть KR сегмента
{ 'url': ['https://stat.ripe.net/data/country-resource-list/data.json?resource=JP'], 'ipv4': True, 'ipv6': False },
{ 'url': ['https://ipv4.fetus.jp/jp.txt'], 'ipv4': True, 'ipv6': False },
{ 'url': ['https://github.com/ipverse/rir-ip/blob/master/country/jp/aggregated.json'], 'ipv4': True, 'ipv6': False },
],
'KOREA': [
]
},
'KOREA': {
'community': '65432:LOCATION,65432:203',
'list': [
# Большая часть KR сегмента
{ 'url': ['https://stat.ripe.net/data/country-resource-list/data.json?resource=KR'], 'ipv4': True, 'ipv6': False },
{ 'url': ['https://ipv4.fetus.jp/kr.txt'], 'ipv4': True, 'ipv6': False },
{ 'url': ['https://github.com/ipverse/rir-ip/blob/master/country/kr/aggregated.json'], 'ipv4': True, 'ipv6': False },
# LG DACOM Corporation
{ 'url': ['https://bgp.he.net/AS3786#_prefixes', 'https://ipinfo.io/widget/demo/AS3786?dataset=asn', 'https://api.hackertarget.com/aslookup/?q=AS3786'], 'ipv4': True, 'ipv6': False },
],
]
},
}