This commit is contained in:
a.kazantsev 2026-07-03 17:33:29 +03:00
parent baa3474d0f
commit 70d5b4f73b
5 changed files with 79 additions and 193 deletions

109
README.md
View file

@ -1,15 +1,15 @@
# Domain-based Routing для BIRD BGP # Domain-based Routing для BIRD BGP
Этот проект содержит скрипт для автоматической генерации BGP-конфигурации на основе списка доменов для BIRD BGP маршрутизатора. Этот проект содержит скрипт для автоматической генерации BGP-маршрутов на основе списка доменов для BIRD BGP маршрутизатора.
## Возможности ## Возможности
- Читает список доменов из текстового файла (по одному домену на строку) - Читает список доменов из текстового файла (по одному домену на строку)
- Разрешает домены в IPv4-адреса через DNS - Разрешает домены в IPv4-адреса через DNS
- Генерирует файл с IP-адресами в формате `route 185.76.151.0/24 reject;` - Генерирует файл с маршрутами в формате `route 185.76.151.0/24 reject;`
- Генерирует конфигурацию для BIRD BGP с загруженными маршрутами - Поддерживает настраиваемый файл с маршрутами
- Поддерживает настраиваемые параметры BGP
- Логирование процессов с различными уровнями детализации - Логирование процессов с различными уровнями детализации
- НЕ изменяет основной конфигурационный файл `/etc/bird/bird.conf`
## Требования ## Требования
@ -62,9 +62,6 @@ python3 domain_routing.py --help
# Путь к файлу со списком доменов (текстовый файл, по одному домену на строку) # Путь к файлу со списком доменов (текстовый файл, по одному домену на строку)
domains_file: domains.txt domains_file: domains.txt
# Путь к выходному конфигурационному файлу BIRD
output_file: /etc/bird/bird.conf
# Путь к файлу с маршрутами (выходной файл с route statements) # Путь к файлу с маршрутами (выходной файл с route statements)
routes_file: routes.conf routes_file: routes.conf
@ -73,18 +70,13 @@ routes_file: routes.conf
# Уровень логирования: DEBUG, INFO, WARNING, ERROR # Уровень логирования: DEBUG, INFO, WARNING, ERROR
log_level: INFO log_level: INFO
# Параметры BGP (опционально)
# neighbor_ip: 192.168.1.1
# neighbor_as: 65000
# protocol_name: domain_routing
``` ```
### Список доменов (domains.txt) ### Список доменов (domains.txt)
``` ```
# Список доменов для domain-based routing # Список доменов для domain-based routing
# Каждый домен будет разрешен в IPv4-адреса и добавлен в BGP-конфигурацию # Каждый домен будет разрешен в IPv4-адреса и добавлен в файл с маршрутами
# Основные домены # Основные домены
example.com example.com
@ -109,30 +101,27 @@ route 185.76.151.0/24 reject;
route 192.168.1.0/24 reject; route 192.168.1.0/24 reject;
``` ```
### Конфигурация BIRD (bird.conf)
Объединяет основную конфигурацию BIRD с загруженными маршрутами:
```
# Generated by domain-routing-bird
# Generated at: 2026-07-03T12:00:00.000000
protocol bgp domain_routing {
import all;
export all;
neighbor 192.168.1.1 as 65000;
route 185.76.151.0/24 reject;
route 192.168.1.0/24 reject;
}
```
## Интеграция с BIRD BGP ## Интеграция с BIRD BGP
После генерации конфигурации: ### Настройка BIRD
1. Проверьте сгенерированные файлы (`routes.conf` и `/etc/bird/bird.conf`) 1. Убедитесь, что у вас есть основной конфигурационный файл BIRD (`/etc/bird/bird.conf`)
2. Для применения изменений выполните:
2. Добавьте `include`-директиву для подключения сгенерированных маршрутов:
```bash
# В /etc/bird/bird.conf добавьте строку:
include "routes.conf";
```
3. Создайте файл `routes.conf` (или укажите другой путь в config.yaml)
4. Запустите скрипт для генерации маршрутов:
```bash
python3 domain_routing.py
```
5. Примените изменения в BIRD:
```bash ```bash
sudo birdc configure sudo birdc configure
``` ```
@ -147,15 +136,15 @@ sudo systemctl restart bird
### Пример 1: Базовая настройка ### Пример 1: Базовая настройка
1. Создайте `config.yaml` и `domains.txt` из примеров 1. Создайте `config.yaml` и `domains.txt` из примеров
2. Запустите скрипт: 2. Добавьте в `/etc/bird/bird.conf` строку:
```
include "routes.conf";
```
3. Запустите скрипт:
```bash ```bash
python3 domain_routing.py python3 domain_routing.py
``` ```
3. Проверьте сгенерированные файлы:
- `routes.conf` - файл с маршрутами
- `/etc/bird/bird.conf` - конфигурация BIRD
4. Примените изменения: 4. Примените изменения:
```bash ```bash
sudo birdc configure sudo birdc configure
@ -166,56 +155,60 @@ sudo birdc configure
1. Отредактируйте `config.yaml`: 1. Отредактируйте `config.yaml`:
```yaml ```yaml
domains_file: my_domains.txt domains_file: my_domains.txt
output_file: /etc/bird/bird.conf routes_file: /etc/bird/routes.conf
routes_file: my_routes.conf
neighbor_ip: 10.0.0.1
neighbor_as: 65100
protocol_name: custom_routing
``` ```
2. Создайте `my_domains.txt` со своими доменами 2. Создайте `my_domains.txt` со своими доменами
3. Запустите скрипт: 3. Добавьте в `/etc/bird/bird.conf`:
```
include "/etc/bird/routes.conf";
```
4. Запустите скрипт:
```bash ```bash
python3 domain_routing.py -c config.yaml python3 domain_routing.py -c config.yaml
``` ```
### Пример 3: Кастомный файл с маршрутами ### Пример 3: Интеграция с существующей конфигурацией
1. Отредактируйте `config.yaml`: 1. Отредактируйте `config.yaml`:
```yaml ```yaml
routes_file: /etc/bird/routes.conf routes_file: /etc/bird/domain-routes.conf
``` ```
2. Запустите скрипт: 2. Добавьте в `/etc/bird/bird.conf` (в нужное место):
```
include "/etc/bird/domain-routes.conf";
```
3. Запустите скрипт:
```bash ```bash
python3 domain_routing.py python3 domain_routing.py
``` ```
Скрипт создаст файл `/etc/bird/routes.conf` с маршрутами и обновит основную конфигурацию BIRD.
## Troubleshooting ## Troubleshooting
### Проблема: "Файл не найден" ### Проблема: \"Файл не найден\"
**Решение**: Убедитесь, что пути к конфигурационным файлам указаны правильно **Решение**: Убедитесь, что пути к конфигурационным файлам указаны правильно
### Проблема: "Не удалось разрешить домен" ### Проблема: \"Не удалось разрешить домен\"
**Решение**: Проверьте сетевое соединение и DNS-серверы **Решение**: Проверьте сетевое соединение и DNS-серверы
### Проблема: "Ошибка записи файла" ### Проблема: \"Ошибка записи файла\"
**Решение**: Убедитесь, что у пользователя есть права на запись в целевой файл **Решение**: Убедитесь, что у пользователя есть права на запись в целевой файл
### Проблема: "Конфигурация не применяется" ### Проблема: \"Конфигурация не применяется\"
**Решение**: **Решение**:
- Проверьте синтаксис сгенерированной конфигурации - Проверьте синтаксис сгенерированного файла с маршрутами
- Убедитесь, что `include`-директива добавлена в `/etc/bird/bird.conf`
- Убедитесь, что BIRD запущен - Убедитесь, что BIRD запущен
- Проверьте права доступа к `/etc/bird/` - Проверьте права доступа к файлам конфигурации
## Безопасность ## Безопасность
- Убедитесь, что список доменов содержит только доверенные домены - Убедитесь, что список доменов содержит только доверенные домены
- Рассмотрите использование DNSSEC для защиты от DNS spoofing - Рассмотрите использование DNSSEC для защиты от DNS spoofing
- Ограничьте права доступа к конфигурационным файлам - Ограничьте права доступа к конфигурационным файлам
- Используйте не-стандартные BGP-параметры в продакшене - Используйте не-стандартные пути к файлам в продакшене
## Лицензия ## Лицензия
@ -223,4 +216,4 @@ python3 domain_routing.py
## Автор ## Автор
GigaCode - Sber AI Assistant GigaCode - Sber AI Assistant

View file

@ -3,9 +3,6 @@
# Путь к файлу со списком доменов (текстовый файл, по одному домену на строку) # Путь к файлу со списком доменов (текстовый файл, по одному домену на строку)
domains_file: domains.txt domains_file: domains.txt
# Путь к выходному конфигурационному файлу BIRD
output_file: /etc/bird/bird.conf
# Путь к файлу с маршрутами (выходной файл с route statements) # Путь к файлу с маршрутами (выходной файл с route statements)
routes_file: routes.conf routes_file: routes.conf
@ -14,8 +11,3 @@ routes_file: routes.conf
# Уровень логирования: DEBUG, INFO, WARNING, ERROR # Уровень логирования: DEBUG, INFO, WARNING, ERROR
log_level: INFO log_level: INFO
# Параметры BGP (опционально)
# neighbor_ip: 192.168.1.1
# neighbor_as: 65000
# protocol_name: domain_routing

View file

@ -3,9 +3,6 @@
# Путь к файлу со списком доменов (текстовый файл, по одному домену на строку) # Путь к файлу со списком доменов (текстовый файл, по одному домену на строку)
domains_file: domains.txt domains_file: domains.txt
# Путь к выходному конфигурационному файлу BIRD
output_file: /etc/bird/bird.conf
# Путь к файлу с маршрутами (выходной файл с route statements) # Путь к файлу с маршрутами (выходной файл с route statements)
routes_file: routes.conf routes_file: routes.conf
@ -14,8 +11,3 @@ routes_file: routes.conf
# Уровень логирования: DEBUG, INFO, WARNING, ERROR # Уровень логирования: DEBUG, INFO, WARNING, ERROR
log_level: INFO log_level: INFO
# Параметры BGP (опционально)
# neighbor_ip: 192.168.1.1
# neighbor_as: 65000
# protocol_name: domain_routing

View file

@ -3,11 +3,14 @@
Domain-based Routing Script for BIRD BGP Domain-based Routing Script for BIRD BGP
Этот скрипт читает список доменов из текстового файла, разрешает их в IPv4-адреса, Этот скрипт читает список доменов из текстового файла, разрешает их в IPv4-адреса,
создает файл с IP-адресами и генерирует BGP-конфигурацию для BIRD. и создает файл с маршрутами в формате BIRD.
Использует формат: Использует формат:
route 185.76.151.0/24 reject; route 185.76.151.0/24 reject;
Пользователь должен подключить сгенерированный файл через include-директиву
в конфигурации BIRD (например: include "/path/to/routes.conf";).
Автор: GigaCode Автор: GigaCode
""" """
@ -15,6 +18,7 @@ import argparse
import logging import logging
import socket import socket
import sys import sys
from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import List, Optional from typing import List, Optional
@ -145,7 +149,7 @@ def generate_routes_file(resolved_domains: dict, routes_file: str) -> str:
""" """
lines = [ lines = [
"# Generated by domain-routing-bird", "# Generated by domain-routing-bird",
f"# Generated at: {__import__('datetime').datetime.now().isoformat()}", f"# Generated at: {datetime.now().isoformat()}",
"" ""
] ]
@ -175,88 +179,6 @@ def generate_routes_file(resolved_domains: dict, routes_file: str) -> str:
return routes_content return routes_content
def load_routes(routes_file: str) -> str:
"""
Загрузка существующего файла с маршрутами.
Args:
routes_file: Путь к файлу с маршрутами
Returns:
str: Содержимое файла с маршрутами
"""
try:
with open(routes_file, 'r') as f:
content = f.read()
logger.info(f"Загружен файл с маршрутами из {routes_file}")
return content
except FileNotFoundError:
logger.warning(f"Файл с маршрутами не найден: {routes_file}")
return ""
except IOError as e:
logger.error(f"Ошибка чтения файла {routes_file}: {e}")
raise
def generate_bird_config(
routes_file: str,
output_file: str,
neighbor_ip: str = "192.168.1.1",
neighbor_as: int = 65000,
protocol_name: str = "domain_routing"
) -> str:
"""
Генерация конфигурационного файла для BIRD BGP.
Args:
routes_file: Путь к файлу с маршрутами
output_file: Путь к выходному файлу
neighbor_ip: IP-адрес BGP-Neighbor
neighbor_as: AS номер соседа
protocol_name: Имя BGP-протокола
Returns:
str: Сгенерированная конфигурация
"""
lines = [
"# Generated by domain-routing-bird",
f"# Generated at: {__import__('datetime').datetime.now().isoformat()}",
"",
f"protocol bgp {protocol_name} {{",
" import all;",
" export all;",
f" neighbor {neighbor_ip} as {neighbor_as};",
""
]
# Загрузка маршрутов из файла
try:
with open(routes_file, 'r') as f:
routes_content = f.read()
# Извлечение строк с route statements
for line in routes_content.split('\n'):
if line.strip().startswith('route '):
lines.append(f" {line.strip()}")
except FileNotFoundError:
logger.warning(f"Файл с маршрутами не найден: {routes_file}")
lines.append("")
lines.append("}")
config = "\n".join(lines)
# Сохранение в файл
try:
with open(output_file, 'w') as f:
f.write(config)
logger.info(f"Конфигурация BIRD сохранена в {output_file}")
except IOError as e:
logger.error(f"Ошибка записи файла {output_file}: {e}")
raise
return config
def parse_arguments() -> argparse.Namespace: def parse_arguments() -> argparse.Namespace:
""" """
Парсинг аргументов командной строки. Парсинг аргументов командной строки.
@ -271,6 +193,12 @@ def parse_arguments() -> argparse.Namespace:
Пример usage: Пример usage:
%(prog)s -c config.yaml %(prog)s -c config.yaml
%(prog)s --config config.yaml --domains domains.txt %(prog)s --config config.yaml --domains domains.txt
Скрипт генерирует файл с маршрутами (routes.conf), который должен быть
подключен к BIRD через include-директиву в конфигурации BIRD.
Пример добавления в /etc/bird/bird.conf:
include "/path/to/routes.conf";
""" """
) )
@ -285,11 +213,6 @@ def parse_arguments() -> argparse.Namespace:
help='Путь к файлу со списком доменов (переопределяет настройку из config)' help='Путь к файлу со списком доменов (переопределяет настройку из config)'
) )
parser.add_argument(
'-o', '--output',
help='Путь к выходному файлу BIRD (переопределяет настройку из config)'
)
parser.add_argument( parser.add_argument(
'-r', '--routes', '-r', '--routes',
help='Путь к файлу с маршрутами (переопределяет настройку из config)' help='Путь к файлу с маршрутами (переопределяет настройку из config)'
@ -324,9 +247,6 @@ def main() -> int:
# Определение пути к файлу доменов # Определение пути к файлу доменов
domains_file = args.domains or config.get('domains_file', 'domains.txt') domains_file = args.domains or config.get('domains_file', 'domains.txt')
# Определение пути к выходному файлу
output_file = args.output or config.get('output_file', '/etc/bird/bird.conf')
# Определение пути к файлу с маршрутами # Определение пути к файлу с маршрутами
routes_file = args.routes or config.get('routes_file', 'routes.conf') routes_file = args.routes or config.get('routes_file', 'routes.conf')
@ -352,23 +272,12 @@ def main() -> int:
logger.info("Генерация файла с маршрутами...") logger.info("Генерация файла с маршрутами...")
generate_routes_file(resolved_domains, routes_file) generate_routes_file(resolved_domains, routes_file)
# Генерация BIRD конфигурации logger.info("Генерация файла с маршрутами завершена")
neighbor_ip = config.get('neighbor_ip', '192.168.1.1')
neighbor_as = int(config.get('neighbor_as', '65000'))
protocol_name = config.get('protocol_name', 'domain_routing')
config_content = generate_bird_config(
routes_file,
output_file,
neighbor_ip,
neighbor_as,
protocol_name
)
logger.info("Генерация BIRD конфигурации завершена")
logger.info(f"Конфигурация BIRD сохранена в {output_file}")
logger.info(f"Файл с маршрутами сохранен в {routes_file}") logger.info(f"Файл с маршрутами сохранен в {routes_file}")
logger.info("Для применения изменений выполните: sudo birdc configure") logger.info("")
logger.info("Для применения изменений:")
logger.info(f"1. Добавьте 'include \"{routes_file}\";' в вашу конфигурацию BIRD")
logger.info("2. Выполните: sudo birdc configure")
return 0 return 0

View file

@ -1,28 +1,28 @@
# Generated by domain-routing-bird # Generated by domain-routing-bird
# Generated at: 2026-07-03T17:05:18.067428 # Generated at: 2026-07-03T17:26:26.179016
route 216.239.36.0/24 reject;
route 216.239.38.0/24 reject;
route 216.239.32.0/24 reject; route 216.239.32.0/24 reject;
route 216.239.34.0/24 reject; route 216.239.34.0/24 reject;
route 216.239.38.0/24 reject;
route 216.239.36.0/24 reject;
route 173.194.220.0/24 reject; route 173.194.220.0/24 reject;
route 74.125.131.0/24 reject;
route 64.233.162.0/24 reject; route 64.233.162.0/24 reject;
route 74.125.205.0/24 reject;
route 173.194.221.0/24 reject; route 173.194.221.0/24 reject;
route 209.85.233.0/24 reject; route 209.85.233.0/24 reject;
route 64.233.161.0/24 reject; route 74.125.205.0/24 reject;
route 108.177.14.0/24 reject;
route 64.233.164.0/24 reject; route 64.233.164.0/24 reject;
route 142.251.1.0/24 reject;
route 173.194.222.0/24 reject;
route 74.125.131.0/24 reject;
route 172.253.152.0/24 reject;
route 64.233.163.0/24 reject; route 64.233.163.0/24 reject;
route 173.194.73.0/24 reject; route 173.194.73.0/24 reject;
route 172.253.152.0/24 reject;
route 173.194.222.0/24 reject;
route 108.177.14.0/24 reject;
route 142.251.1.0/24 reject;
route 64.233.161.0/24 reject;
route 64.233.165.0/24 reject; route 64.233.165.0/24 reject;
route 172.253.130.0/24 reject;
route 142.250.150.0/24 reject; route 142.250.150.0/24 reject;
route 34.126.226.0/24 reject; route 34.126.226.0/24 reject;
route 172.253.130.0/24 reject;
route 172.217.132.0/24 reject; route 172.217.132.0/24 reject;
route 74.125.109.0/24 reject; route 74.125.109.0/24 reject;
route 74.125.3.0/24 reject; route 74.125.3.0/24 reject;