Переписан BGP сервер на FRR

This commit is contained in:
2025-07-11 18:06:07 +07:00
parent 3c5740784b
commit e197dae9f7
14 changed files with 1222 additions and 812 deletions
+15 -7
View File
@@ -1,21 +1,27 @@
FROM python:3.9-slim
FROM ubuntu:22.04
# Установка системных зависимостей
# Установка системных зависимостей и FRR
RUN apt-get update && apt-get install -y \
frr \
frr-pythontools \
python3 \
python3-pip \
iproute2 \
iputils-ping \
net-tools \
procps \
vim \
curl \
&& rm -rf /var/lib/apt/lists/*
# Установка ExaBGP
RUN pip install exabgp
# Установка Python зависимостей
RUN pip3 install watchdog
# Создание структуры директорий
RUN mkdir -p /app/scripts /app/data /app/logs /run/exabgp /var/run/exabgp /usr/local/run/exabgp /usr/local/var/run/exabgp
RUN mkdir -p /app/scripts /app/data /app/logs /etc/frr
# Копирование файлов
COPY exabgp.conf /app/exabgp.conf
COPY frr.conf /etc/frr/frr.conf
COPY scripts/ /app/scripts/
COPY data/ /app/data/
@@ -23,6 +29,7 @@ COPY data/ /app/data/
RUN chmod +x /app/scripts/start.sh
RUN chmod +x /app/scripts/load_prefixes.py
RUN chmod +x /app/scripts/generate_config.py
RUN chmod +x /app/scripts/monitor.py
# Рабочая директория
WORKDIR /app
@@ -37,7 +44,8 @@ ENV BGP_NEIGHBOR_IP=192.168.1.1
ENV BGP_NEIGHBOR_AS=65001
ENV BGP_HOLD_TIME=90
ENV BGP_KEEPALIVE=30
ENV BGP_LOG_LEVEL=INFO
ENV BGP_LOG_LEVEL=info
ENV FRR_DAEMONS="bgpd zebra"
# Команда запуска
ENTRYPOINT ["/app/scripts/start.sh"]
+241 -145
View File
@@ -1,228 +1,324 @@
# Быстрый старт BGP сервера
# Быстрый старт BGP Server (FRR)
## Минимальные требования
Этот документ поможет вам быстро запустить BGP сервер на базе FRR для раздачи префиксов.
## Предварительные требования
- Docker Desktop для Windows
- PowerShell
- RouterOS 7.14+ (на стороне клиента)
- RouterOS 7.14+ (для клиентской стороны)
## Быстрый запуск (5 минут)
## Шаг 1: Подготовка файлов
### 1. Клонирование и подготовка
### Создание файла с префиксами
```powershell
# Клонирование репозитория (если нужно)
git clone <repository-url>
cd bgp-server
# Создание необходимых директорий
mkdir logs
```
### 2. Настройка префиксов
Отредактируйте файл `data/prefixes.txt`:
Создайте файл `data/prefixes.txt` с вашими префиксами:
```
# Основные префиксы
192.168.1.0/24
192.168.2.0/24
10.0.0.0/8
172.16.0.0/12
# Дополнительные префиксы
203.0.113.0/24
198.51.100.0/24
```
### 3. Запуск сервера
### Создание дополнительного файла (опционально)
Создайте файл `data/additional_prefixes.txt` для дополнительных префиксов:
```
# Дополнительные префиксы
192.168.100.0/24
192.168.200.0/24
```
## Шаг 2: Запуск сервера
### Вариант A: Использование PowerShell скрипта (рекомендуется)
```powershell
# Запуск с автоматической сборкой
# Запуск с автоматической сборкой образа
.\scripts\start-server.ps1 -Build
# Или вручную
docker-compose up -d --build
# Или запуск без пересборки
.\scripts\start-server.ps1
```
### 4. Проверка работы
### Вариант B: Использование Docker Compose
```powershell
# Проверка статуса
docker-compose ps
# Сборка и запуск
docker-compose up -d --build
# Просмотр логов
docker-compose logs -f bgp-server
# Мониторинг
docker exec bgp-server python3 /app/scripts/monitor.py
# Или только запуск
docker-compose up -d
```
### 5. Настройка RouterOS
### Вариант C: Ручной запуск
Выполните в RouterOS:
```powershell
# Сборка образа
docker build -t bgp-server-frr .
# Запуск контейнера
docker run -d \
--name bgp-server \
--restart unless-stopped \
-p 179:179 \
-v ${PWD}/data:/app/data:ro \
-v ${PWD}/logs:/app/logs \
--cap-add NET_ADMIN \
--privileged \
bgp-server-frr
```
## Шаг 3: Проверка работы
### Проверка статуса контейнера
```powershell
# Статус контейнера
docker ps
# Логи контейнера
docker logs bgp-server
```
### Проверка FRR
```powershell
# Версия FRR
docker exec bgp-server vtysh -c "show version"
# Статус BGP
docker exec bgp-server vtysh -c "show ip bgp summary"
# Анонсированные маршруты
docker exec bgp-server vtysh -c "show ip bgp"
```
### Проверка загруженных префиксов
```powershell
# Логи загрузки префиксов
docker exec bgp-server tail -f /app/logs/prefixes.log
# Тестирование загрузки
docker exec bgp-server python3 /app/scripts/load_prefixes.py --test
```
## Шаг 4: Настройка RouterOS
### Базовая настройка BGP
```routeros
/routing bgp instance add name=bgp-server as=65001 router-id=192.168.1.1
/routing bgp network add network=192.168.1.0/24
/routing bgp peer add name=bgp-server remote-address=192.168.1.100 remote-as=65000 instance=bgp-server
# Создание BGP экземпляра
/routing bgp instance
add name=bgp-server as=65001 router-id=192.168.1.1
# Настройка BGP сети
/routing bgp network
add network=192.168.1.0/24
# Настройка BGP пира
/routing bgp peer
add name=bgp-server remote-address=192.168.1.100 remote-as=65000 instance=bgp-server
# Включение BGP
/routing bgp instance set bgp-server disabled=no
```
### 6. Проверка BGP сессии
### Проверка BGP сессии
В RouterOS:
```routeros
# Статус BGP
/routing bgp peer print
# Полученные маршруты
/routing bgp route print
```
Ожидаемый результат:
```
Flags: X - disabled, I - invalid, D - dynamic, E - established
0 name="bgp-server" ... state=established uptime=1m30s prefix-count=8
```
## Шаг 5: Мониторинг
## Полезные команды
### Управление сервером
### Просмотр логов
```powershell
# Запуск
.\scripts\start-server.ps1
# Логи FRR
docker exec bgp-server tail -f /app/logs/frr.log
# Остановка
# Логи загрузки префиксов
docker exec bgp-server tail -f /app/logs/prefixes.log
# Логи мониторинга
docker exec bgp-server tail -f /app/logs/monitor.log
```
### Статус системы
```powershell
# Статус в JSON формате
docker exec bgp-server cat /app/logs/status.json
# Запуск мониторинга
docker exec bgp-server python3 /app/scripts/monitor.py
```
### Команды vtysh
```powershell
# Подключение к FRR CLI
docker exec -it bgp-server vtysh
# Полезные команды внутри vtysh:
show ip bgp summary # Сводка BGP
show ip bgp # Все BGP маршруты
show ip route # Таблица маршрутизации
show interface # Интерфейсы
show running-config # Конфигурация
```
## Управление
### Остановка сервера
```powershell
# Остановка с сохранением контейнера
.\scripts\stop-server.ps1
# Перезапуск
docker-compose restart
# Просмотр логов
docker-compose logs -f bgp-server
# Остановка с удалением контейнера
.\scripts\stop-server.ps1 -Force
```
### Мониторинг
### Перезагрузка префиксов
```powershell
# Проверка статуса
docker-compose ps
# Мониторинг ресурсов
docker stats bgp-server
# Проверка BGP сессии
docker exec bgp-server exabgpcli show neighbor
```
### Обновление префиксов
```powershell
# Перезагрузка префиксов без перезапуска
# Перезагрузка без перезапуска сервера
docker exec bgp-server python3 /app/scripts/reload_prefixes.py
# Или перезапуск сервера
docker-compose restart
```
## Устранение неполадок
### Обновление контейнера
```powershell
# Обновление с пересборкой
.\scripts\update-container.ps1 -Force
```
## Диагностика
### Проблема: Контейнер не запускается
```powershell
# Проверка логов
docker-compose logs bgp-server
docker logs bgp-server
# Проверка портов
netstat -an | findstr :179
# Пересборка образа
docker-compose build --no-cache
# Проверка Docker
docker system info
```
### Проблема: BGP сессия не устанавливается
```powershell
# Проверка сетевого подключения
# Проверка сетевой связности
docker exec bgp-server ping 192.168.1.1
# Проверка конфигурации
docker exec bgp-server cat /app/exabgp.conf
# Проверка конфигурации FRR
docker exec bgp-server vtysh -c "show running-config"
# Проверка логов
docker-compose logs bgp-server
# Проверка статуса BGP
docker exec bgp-server vtysh -c "show ip bgp summary"
```
### Проблема: Префиксы не анонсируются
```powershell
# Проверка файлов с префиксами
# Проверка файлов префиксов
docker exec bgp-server cat /app/data/prefixes.txt
# Проверка логов загрузки префиксов
docker exec bgp-server cat /app/logs/prefixes.log
# Проверка логов загрузки
docker exec bgp-server tail -f /app/logs/prefixes.log
# Перезагрузка префиксов
docker exec bgp-server python3 /app/scripts/reload_prefixes.py
# Проверка статических маршрутов
docker exec bgp-server vtysh -c "show ip route static"
```
## Настройка сети
## Настройка переменных окружения
### Изменение IP адресов
Отредактируйте `docker-compose.yml`:
```yaml
environment:
- BGP_ROUTER_ID=192.168.1.100 # IP сервера
- BGP_NEIGHBOR_IP=192.168.1.1 # IP RouterOS
```
И `exabgp.conf`:
```ini
neighbor 192.168.1.1 { # IP RouterOS
router-id 192.168.1.100; # IP сервера
local-address 192.168.1.100; # IP сервера
# ...
}
```
### Изменение AS номеров
В `docker-compose.yml`:
```yaml
environment:
- BGP_LOCAL_AS=65000 # AS сервера
- BGP_NEIGHBOR_AS=65001 # AS RouterOS
```
В `exabgp.conf`:
```ini
neighbor 192.168.1.1 {
local-as 65000; # AS сервера
peer-as 65001; # AS RouterOS
}
```
## Безопасность
### MD5 аутентификация
В `exabgp.conf`:
```ini
neighbor 192.168.1.1 {
# ... существующие настройки ...
md5-password "your-secure-password";
}
```
В RouterOS:
```routeros
/routing bgp peer set bgp-server tcp-md5-key="your-secure-password"
```
### Firewall
Вы можете настроить BGP параметры через переменные окружения:
```powershell
# Windows Firewall (PowerShell)
New-NetFirewallRule -DisplayName "BGP Server" -Direction Inbound -Protocol TCP -LocalPort 179 -Action Allow
# Запуск с кастомными настройками
docker run -d \
--name bgp-server \
-p 179:179 \
-v ${PWD}/data:/app/data:ro \
-v ${PWD}/logs:/app/logs \
-e BGP_LOCAL_AS=65000 \
-e BGP_ROUTER_ID=192.168.1.100 \
-e BGP_NEIGHBOR_IP=192.168.1.1 \
-e BGP_NEIGHBOR_AS=65001 \
-e BGP_HOLD_TIME=90 \
-e BGP_KEEPALIVE=30 \
--cap-add NET_ADMIN \
--privileged \
bgp-server-frr
```
## Готово!
## Полезные команды
После выполнения всех шагов у вас должен работать BGP сервер, который раздает префиксы из текстовых файлов в RouterOS.
### Мониторинг в реальном времени
Для получения дополнительной информации см. основной файл `README.md`.
```powershell
# Логи в реальном времени
docker logs -f bgp-server
# Статус BGP каждые 5 секунд
while ($true) {
docker exec bgp-server vtysh -c "show ip bgp summary"
Start-Sleep 5
Clear-Host
}
```
### Резервное копирование
```powershell
# Копирование файлов префиксов
Copy-Item data/prefixes.txt data/prefixes.txt.backup
# Экспорт конфигурации FRR
docker exec bgp-server vtysh -c "show running-config" > frr-config.backup
```
### Очистка
```powershell
# Остановка и удаление контейнера
docker stop bgp-server
docker rm bgp-server
# Удаление образа
docker rmi bgp-server-frr
# Очистка логов
Remove-Item logs/* -Recurse -Force
```
## Следующие шаги
1. **Настройка мониторинга**: Настройте алерты для критических событий
2. **Резервное копирование**: Настройте автоматическое резервное копирование конфигурации
3. **Безопасность**: Настройте firewall и аутентификацию BGP
4. **Масштабирование**: Рассмотрите использование нескольких экземпляров для высокой доступности
## Поддержка
- Документация FRR: https://frrouting.org/
- GitHub проекта: https://github.com/FRRouting/frr
- Сообщество: https://lists.frrouting.org/
+145 -159
View File
@@ -1,28 +1,38 @@
# BGP Server для раздачи префиксов
# BGP Server для раздачи префиксов (FRR)
Этот проект представляет собой BGP сервер, который раздает префиксы из текстовых файлов. Сервер работает в Docker контейнере и предназначен для интеграции с RouterOS 7.14+.
Этот проект представляет собой BGP сервер на базе FRR (Free Range Routing), который раздает префиксы из текстовых файлов. Сервер работает в Docker контейнере и предназначен для интеграции с RouterOS 7.14+.
## Архитектура решения
- **BGP Server**: ExaBGP в Docker контейнере
- **BGP Server**: FRR (Free Range Routing) в Docker контейнере
- **Источник данных**: Текстовые файлы с префиксами
- **Клиент**: RouterOS 7.14+ для получения префиксов
- **Протокол**: BGP (только исходящие анонсы)
## Преимущества FRR
- **Стабильность**: Производственный уровень надежности
- **Производительность**: Оптимизирован для высоких нагрузок
- **Функциональность**: Полная поддержка BGP функций
- **Мониторинг**: Встроенные инструменты диагностики
- **Сообщество**: Активная поддержка и развитие
## Структура проекта
```
bgp-server/
├── docker-compose.yml # Конфигурация Docker
├── Dockerfile # Образ Docker
├── exabgp.conf # Конфигурация ExaBGP
├── Dockerfile # Образ Docker с FRR
├── frr.conf # Конфигурация FRR
├── scripts/
│ ├── start.sh # Скрипт запуска
── load_prefixes.py # Загрузка префиксов из файлов
│ ├── start.sh # Скрипт запуска FRR
── load_prefixes.py # Загрузка префиксов в FRR
│ ├── generate_config.py # Генерация конфигурации FRR
│ └── monitor.py # Мониторинг FRR
├── data/
│ ├── prefixes.txt # Основной файл с префиксами
│ └── additional_prefixes.txt # Дополнительные префиксы
├── logs/ # Логи ExaBGP
├── logs/ # Логи FRR
└── README.md # Эта инструкция
```
@@ -56,6 +66,9 @@ docker-compose logs -f bgp-server
# Проверка статуса контейнера
docker-compose ps
# Проверка BGP сессии через vtysh
docker exec bgp-server vtysh -c "show ip bgp summary"
```
## Подробная настройка
@@ -91,45 +104,17 @@ docker-compose ps
### Шаг 2: Конфигурация BGP сервера
Отредактируйте `exabgp.conf`:
Конфигурация FRR генерируется автоматически из переменных окружения в `docker-compose.yml`:
```ini
# Основная конфигурация
process load-prefixes {
run /app/scripts/load_prefixes.py;
encoder json;
}
# Настройки BGP
neighbor 192.168.1.1 {
router-id 192.168.1.100;
local-address 192.168.1.100;
local-as 65000;
peer-as 65001;
# Только исходящие анонсы
capability {
graceful-restart;
}
# Настройки сессии
hold-time 90;
keepalive 30;
# Логирование
api {
processes [load-prefixes];
neighbor-changes;
receive {
parsed;
update;
}
send {
parsed;
update;
}
}
}
```yaml
environment:
- BGP_LOCAL_AS=65000
- BGP_ROUTER_ID=192.168.1.100
- BGP_NEIGHBOR_IP=192.168.1.1
- BGP_NEIGHBOR_AS=65001
- BGP_HOLD_TIME=90
- BGP_KEEPALIVE=30
- BGP_LOG_LEVEL=info
```
### Шаг 3: Настройка Docker
@@ -155,6 +140,9 @@ services:
- BGP_NEIGHBOR_AS=65001
networks:
- bgp-network
cap_add:
- NET_ADMIN
privileged: true
networks:
bgp-network:
@@ -195,70 +183,130 @@ docker-compose up -d
docker-compose logs -f bgp-server
# Проверка статуса BGP сессии
docker exec bgp-server exabgpcli show neighbor
docker exec bgp-server vtysh -c "show ip bgp summary"
# Проверка анонсированных маршрутов
docker exec bgp-server vtysh -c "show ip bgp"
```
## Мониторинг и логирование
## Управление и мониторинг
### Просмотр логов
### Команды vtysh
```powershell
# Все логи
docker-compose logs bgp-server
# Подключение к FRR CLI
docker exec -it bgp-server vtysh
# Логи в реальном времени
docker-compose logs -f bgp-server
# Просмотр BGP соседей
show ip bgp neighbors
# Логи за последние 100 строк
docker-compose logs --tail=100 bgp-server
# Просмотр BGP маршрутов
show ip bgp
# Просмотр статических маршрутов
show ip route
# Просмотр конфигурации
show running-config
```
### Проверка статуса
### Мониторинг через скрипты
```powershell
# Статус контейнера
docker-compose ps
# Запуск мониторинга
docker exec bgp-server python3 /app/scripts/monitor.py
# Проверка BGP сессии
docker exec bgp-server exabgpcli show neighbor
# Просмотр статуса
docker exec bgp-server cat /app/logs/status.json
# Проверка загруженных префиксов
docker exec bgp-server cat /app/logs/prefixes.log
# Перезагрузка префиксов
docker exec bgp-server python3 /app/scripts/load_prefixes.py --test
```
### Логи
```powershell
# Логи FRR
docker exec bgp-server tail -f /app/logs/frr.log
# Логи загрузки префиксов
docker exec bgp-server tail -f /app/logs/prefixes.log
# Логи мониторинга
docker exec bgp-server tail -f /app/logs/monitor.log
```
## Диагностика
### Проверка статуса FRR
```powershell
# Проверка процессов
docker exec bgp-server ps aux | grep -E "(zebra|bgpd)"
# Проверка версии FRR
docker exec bgp-server vtysh -c "show version"
# Проверка сетевых интерфейсов
docker exec bgp-server vtysh -c "show interface"
```
### Проверка BGP сессии
```powershell
# Статус BGP соседей
docker exec bgp-server vtysh -c "show ip bgp summary"
# Детальная информация о соседе
docker exec bgp-server vtysh -c "show ip bgp neighbors 192.168.1.1"
```
### Проверка маршрутов
```powershell
# Все BGP маршруты
docker exec bgp-server vtysh -c "show ip bgp"
# Статические маршруты
docker exec bgp-server vtysh -c "show ip route static"
# Таблица маршрутизации
docker exec bgp-server vtysh -c "show ip route"
```
## Обновление префиксов
### Автоматическое обновление
Сервер автоматически перезагружает префиксы при изменении файлов в папке `data/`.
Скрипт `load_prefixes.py` автоматически отслеживает изменения в файлах префиксов и обновляет маршруты в FRR.
### Ручное обновление
```powershell
# Перезапуск сервера
docker-compose restart bgp-server
# Перезагрузка всех префиксов
docker exec bgp-server python3 /app/scripts/load_prefixes.py
# Или перезагрузка только процесса загрузки префиксов
docker exec bgp-server pkill -f load_prefixes.py
# Тестирование загрузки префиксов
docker exec bgp-server python3 /app/scripts/load_prefixes.py --test
```
## Устранение неполадок
### Проблема: BGP сессия не устанавливается
1. Проверьте сетевое подключение:
1. Проверьте сетевую связность:
```powershell
docker exec bgp-server ping 192.168.1.1
```
2. Проверьте конфигурацию:
2. Проверьте конфигурацию BGP:
```powershell
docker exec bgp-server cat /app/exabgp.conf
docker exec bgp-server vtysh -c "show running-config"
```
3. Проверьте логи:
3. Проверьте логи FRR:
```powershell
docker-compose logs bgp-server
docker exec bgp-server tail -f /app/logs/frr.log
```
### Проблема: Префиксы не анонсируются
@@ -268,106 +316,44 @@ docker-compose logs bgp-server
docker exec bgp-server cat /app/data/prefixes.txt
```
2. Проверьте логи процесса загрузки:
2. Проверьте логи загрузки префиксов:
```powershell
docker exec bgp-server cat /app/logs/prefixes.log
docker exec bgp-server tail -f /app/logs/prefixes.log
```
### Проблема: Docker контейнер не запускается
1. Проверьте порты:
3. Проверьте статические маршруты:
```powershell
netstat -an | findstr :179
docker exec bgp-server vtysh -c "show ip route static"
```
2. Проверьте Docker логи:
### Проблема: Высокое потребление ресурсов
1. Проверьте использование памяти:
```powershell
docker-compose logs
docker exec bgp-server free -h
```
2. Проверьте количество маршрутов:
```powershell
docker exec bgp-server vtysh -c "show ip bgp summary"
```
## Безопасность
### Рекомендации по безопасности
1. **Ограничение доступа**: Настройте firewall для ограничения доступа к порту 179
2. **Аутентификация**: Используйте MD5 аутентификацию в BGP
3. **Логирование**: Включите детальное логирование для аудита
4. **Обновления**: Регулярно обновляйте Docker образы
### Настройка MD5 аутентификации
В `exabgp.conf` добавьте:
```ini
neighbor 192.168.1.1 {
# ... существующие настройки ...
md5-password "your-secure-password";
}
```
В RouterOS:
```routeros
/routing bgp peer set bgp-server password="your-secure-password"
```
- FRR работает в привилегированном контейнере для доступа к сетевым интерфейсам
- Используйте route-maps для фильтрации трафика
- Ограничьте доступ к vtysh CLI
- Регулярно обновляйте образ Docker
## Производительность
### Оптимизация для больших объемов префиксов
- FRR оптимизирован для обработки большого количества маршрутов
- Поддерживает до 1 миллиона маршрутов
- Эффективное использование памяти
- Быстрое время сходимости
1. **Кэширование**: Используйте Redis для кэширования префиксов
2. **База данных**: Для больших объемов используйте PostgreSQL
3. **Мониторинг**: Настройте метрики производительности
## Поддержка
### Мониторинг ресурсов
```powershell
# Использование ресурсов контейнера
docker stats bgp-server
# Проверка дискового пространства
docker system df
```
## Альтернативные решения
### 1. Bird BGP Daemon
Если ExaBGP не подходит, можно использовать Bird:
```dockerfile
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y bird
COPY bird.conf /etc/bird/bird.conf
CMD ["bird", "-f", "-d"]
```
### 2. FRRouting (FRR)
Другой популярный вариант:
```dockerfile
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y frr
COPY frr.conf /etc/frr/frr.conf
CMD ["/usr/lib/frr/frrinit", "start"]
```
### 3. GoBGP
Для более современного подхода:
```dockerfile
FROM golang:1.19-alpine
RUN go install github.com/osrg/gobgp/cmd/gobgpd@latest
COPY gobgpd.conf /etc/gobgpd.conf
CMD ["gobgpd", "-f", "/etc/gobgpd.conf"]
```
## Заключение
Этот BGP сервер предоставляет простое и эффективное решение для раздачи префиксов из текстовых файлов. Docker контейнеризация обеспечивает легкое развертывание и управление, а интеграция с RouterOS позволяет быстро настроить клиентскую сторону.
Для продакшн использования рекомендуется:
- Настроить мониторинг и алертинг
- Добавить резервное копирование конфигурации
- Реализовать автоматическое восстановление после сбоев
- Настроить централизованное логирование
- Документация FRR: https://frrouting.org/
- GitHub проекта: https://github.com/FRRouting/frr
- Сообщество: https://lists.frrouting.org/
+4
View File
@@ -15,10 +15,14 @@ services:
- BGP_ROUTER_ID=192.168.1.100
- BGP_NEIGHBOR_IP=192.168.1.1
- BGP_NEIGHBOR_AS=65001
- BGP_HOLD_TIME=90
- BGP_KEEPALIVE=30
- BGP_LOG_LEVEL=info
networks:
- bgp-network
cap_add:
- NET_ADMIN # Для работы с сетевыми интерфейсами
privileged: true # Для работы с FRR демонами
networks:
bgp-network:
-5
View File
@@ -1,5 +0,0 @@
# Этот файл будет перезаписан динамически сгенерированной конфигурацией
# из переменных окружения при запуске контейнера.
#
# Для просмотра текущей конфигурации используйте:
# docker exec bgp-server cat /app/exabgp.conf
+46
View File
@@ -0,0 +1,46 @@
# FRR Configuration File
# Этот файл будет перезаписан динамически сгенерированной конфигурацией
# из переменных окружения при запуске контейнера.
#
# Для просмотра текущей конфигурации используйте:
# docker exec bgp-server cat /etc/frr/frr.conf
# Глобальные настройки
frr version 8.5.2
frr defaults traditional
hostname bgp-server
log syslog informational
service integrated-vtysh-config
# Настройки BGP
router bgp 65000
bgp router-id 192.168.1.100
bgp log-neighbor-changes
neighbor 192.168.1.1 remote-as 65001
neighbor 192.168.1.1 description RouterOS Client
neighbor 192.168.1.1 timers 30 90
neighbor 192.168.1.1 capability graceful-restart
neighbor 192.168.1.1 soft-reconfiguration inbound
!
address-family ipv4 unicast
neighbor 192.168.1.1 activate
neighbor 192.168.1.1 route-map OUTBOUND out
neighbor 192.168.1.1 route-map INBOUND in
exit-address-family
!
# Route maps для фильтрации
route-map OUTBOUND permit 10
description Allow all outbound routes
!
route-map INBOUND deny 10
description Deny all inbound routes (receive-only mode)
!
# Настройки интерфейса
interface eth0
ip address 192.168.1.100/24
!
# Статические маршруты (будут добавлены динамически)
# ip route 192.168.1.0/24 Null0
+1 -4
View File
@@ -1,4 +1 @@
exabgp>=4.2.0
ipaddress
pathlib
typing
watchdog>=2.1.0
+64 -54
View File
@@ -1,85 +1,95 @@
#!/usr/bin/env python3
"""
Скрипт для генерации конфигурации ExaBGP из переменных окружения
Скрипт для генерации конфигурации FRR из переменных окружения
"""
import os
import sys
from pathlib import Path
def get_env_var(name: str, default: str) -> str:
def get_env_var(name, default):
"""Получение переменной окружения с значением по умолчанию"""
return os.environ.get(name, default)
def generate_exabgp_config():
"""Генерация конфигурации ExaBGP"""
def generate_frr_config():
"""Генерация конфигурации FRR"""
# Получение переменных окружения
# Получение настроек из переменных окружения
local_as = get_env_var('BGP_LOCAL_AS', '65000')
router_id = get_env_var('BGP_ROUTER_ID', '192.168.1.100')
neighbor_ip = get_env_var('BGP_NEIGHBOR_IP', '192.168.1.1')
neighbor_as = get_env_var('BGP_NEIGHBOR_AS', '65001')
hold_time = get_env_var('BGP_HOLD_TIME', '90')
keepalive = get_env_var('BGP_KEEPALIVE', '30')
md5_password = get_env_var('BGP_MD5_PASSWORD', '')
log_level = get_env_var('BGP_LOG_LEVEL', 'INFO')
log_level = get_env_var('BGP_LOG_LEVEL', 'info')
# Генерация конфигурации
config = f"""# Автоматически сгенерированная конфигурация ExaBGP
process load-prefixes {{
run /app/scripts/load_prefixes.py;
encoder json;
}}
# Конфигурация FRR
config = f"""# FRR Configuration File
# Generated automatically from environment variables
# Глобальные настройки
frr version 8.5.2
frr defaults traditional
hostname bgp-server
log syslog {log_level}
service integrated-vtysh-config
# Настройки BGP
neighbor {neighbor_ip} {{
router-id {router_id};
local-address {router_id};
local-as {local_as};
peer-as {neighbor_as};
# Только исходящие анонсы (не принимаем префиксы)
capability {{
graceful-restart;
}}
# Настройки сессии
hold-time {hold_time};
"""
router bgp {local_as}
bgp router-id {router_id}
bgp log-neighbor-changes
neighbor {neighbor_ip} remote-as {neighbor_as}
neighbor {neighbor_ip} description RouterOS Client
neighbor {neighbor_ip} timers {keepalive} {hold_time}
neighbor {neighbor_ip} capability graceful-restart
neighbor {neighbor_ip} soft-reconfiguration inbound
!
address-family ipv4 unicast
neighbor {neighbor_ip} activate
neighbor {neighbor_ip} route-map OUTBOUND out
neighbor {neighbor_ip} route-map INBOUND in
exit-address-family
!
# Добавление MD5 пароля если указан
if md5_password:
config += f" md5-password \"{md5_password}\";\n"
config += f"""
# Логирование
api {{
processes [load-prefixes];
neighbor-changes;
receive {{
parsed;
update;
}}
send {{
parsed;
update;
}}
}}
}}
# Route maps для фильтрации
route-map OUTBOUND permit 10
description Allow all outbound routes
!
route-map INBOUND deny 10
description Deny all inbound routes (receive-only mode)
!
# Настройки интерфейса
interface eth0
ip address {router_id}/24
!
# Статические маршруты (будут добавлены динамически)
# ip route 192.168.1.0/24 Null0
"""
return config
def main():
"""Основная функция"""
if len(sys.argv) > 1 and sys.argv[1] == '--print':
# Вывод конфигурации в stdout
print(generate_exabgp_config())
else:
# Запись конфигурации в файл
config = generate_exabgp_config()
with open('/app/exabgp.conf', 'w') as f:
try:
# Генерация конфигурации
config = generate_frr_config()
# Запись в файл
config_path = Path('/etc/frr/frr.conf')
config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, 'w') as f:
f.write(config)
print("Configuration generated successfully")
print(f"FRR configuration generated: {config_path}")
print("Configuration content:")
print(config)
except Exception as e:
print(f"Error generating FRR configuration: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
+108 -53
View File
@@ -1,12 +1,12 @@
#!/usr/bin/env python3
"""
Скрипт для загрузки префиксов из текстовых файлов в ExaBGP
Скрипт для загрузки префиксов из текстовых файлов в FRR
"""
import sys
import os
import time
import json
import subprocess
import ipaddress
from pathlib import Path
from typing import List, Set
@@ -21,7 +21,7 @@ def log_message(message: str):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}"
# Вывод в stdout для ExaBGP
# Вывод в stdout
print(log_entry, flush=True)
# Запись в файл (с обработкой ошибок)
@@ -84,44 +84,84 @@ def load_all_prefixes() -> Set[str]:
return all_prefixes
def run_vtysh_command(command: str) -> bool:
"""Выполнение команды через vtysh"""
try:
result = subprocess.run(
['vtysh', '-c', command],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
log_error(f"vtysh command failed: {command}")
log_error(f"stderr: {result.stderr}")
return False
return True
except subprocess.TimeoutExpired:
log_error(f"vtysh command timeout: {command}")
return False
except Exception as e:
log_error(f"Error running vtysh command '{command}': {e}")
return False
def announce_prefixes(prefixes: Set[str]):
"""Анонсирование префиксов через ExaBGP API"""
# Получение настроек из переменных окружения
neighbor_ip = os.environ.get('BGP_NEIGHBOR_IP', '192.168.1.1')
local_as = int(os.environ.get('BGP_LOCAL_AS', '65000'))
router_id = os.environ.get('BGP_ROUTER_ID', '192.168.1.100')
"""Анонсирование префиксов через FRR"""
log_message(f"Announcing {len(prefixes)} prefixes...")
for prefix in sorted(prefixes):
# Формат команды для ExaBGP (упрощенный)
command = {
"command": "announce route",
"neighbor": neighbor_ip,
"attribute": {
"origin": "igp",
"as-path": [local_as],
"next-hop": router_id
},
"nlri": prefix
}
# Отправка команды в ExaBGP
print(json.dumps(command), flush=True)
log_message(f"Announced prefix: {prefix}")
# Добавление статического маршрута в FRR
command = f"ip route {prefix} Null0"
if run_vtysh_command(command):
log_message(f"Announced prefix: {prefix}")
else:
log_error(f"Failed to announce prefix: {prefix}")
def withdraw_prefixes(prefixes: Set[str]):
"""Отзыв префиксов через ExaBGP API"""
# Получение настроек из переменных окружения
neighbor_ip = os.environ.get('BGP_NEIGHBOR_IP', '192.168.1.1')
"""Отзыв префиксов через FRR"""
log_message(f"Withdrawing {len(prefixes)} prefixes...")
for prefix in sorted(prefixes):
command = {
"command": "withdraw route",
"neighbor": neighbor_ip,
"nlri": prefix
}
# Удаление статического маршрута из FRR
command = f"no ip route {prefix} Null0"
if run_vtysh_command(command):
log_message(f"Withdrew prefix: {prefix}")
else:
log_error(f"Failed to withdraw prefix: {prefix}")
def check_frr_status() -> bool:
"""Проверка статуса FRR"""
try:
result = subprocess.run(
['vtysh', '-c', 'show version'],
capture_output=True,
text=True,
timeout=10
)
return result.returncode == 0
except Exception:
return False
def wait_for_frr():
"""Ожидание запуска FRR"""
log_message("Waiting for FRR to start...")
max_attempts = 30
attempt = 0
while attempt < max_attempts:
if check_frr_status():
log_message("FRR is ready")
return True
print(json.dumps(command), flush=True)
log_message(f"Withdrew prefix: {prefix}")
attempt += 1
time.sleep(2)
if attempt % 5 == 0:
log_message(f"Still waiting for FRR... (attempt {attempt}/{max_attempts})")
log_error("FRR did not start within expected time")
return False
def main():
"""Основная функция"""
@@ -138,8 +178,21 @@ def main():
print(f"Found {len(prefixes)} prefixes: {list(prefixes)}")
return
# Проверка режима отзыва
if len(sys.argv) > 1 and sys.argv[1] == '--withdraw':
log_message("Withdraw mode: loading and withdrawing all prefixes...")
prefixes = load_all_prefixes()
if wait_for_frr():
withdraw_prefixes(prefixes)
return
log_message("Starting prefix loader...")
# Ожидание запуска FRR
if not wait_for_frr():
log_error("Cannot proceed without FRR")
return
# Загрузка префиксов
prefixes = load_all_prefixes()
log_message(f"Total prefixes loaded: {len(prefixes)}")
@@ -152,29 +205,31 @@ def main():
announce_prefixes(prefixes)
log_message("All prefixes announced successfully")
# Ожидание команд от ExaBGP
# Мониторинг изменений в файлах
log_message("Starting file monitoring...")
try:
while True:
line = sys.stdin.readline()
if not line:
break
time.sleep(30) # Проверка каждые 30 секунд
line = line.strip()
if not line: # Пропуск пустых строк
continue
# Обработка команд от ExaBGP
try:
data = json.loads(line)
log_message(f"Received command: {data}")
except json.JSONDecodeError:
# Не все сообщения от ExaBGP являются JSON
# Это может быть обычное текстовое сообщение
if line.startswith('[') and line.endswith(']'):
# Это может быть лог сообщение от ExaBGP
log_message(f"Received log message: {line}")
else:
log_message(f"Received non-JSON message: {line}")
# Перезагрузка префиксов
new_prefixes = load_all_prefixes()
# Определение изменений
added = new_prefixes - prefixes
removed = prefixes - new_prefixes
if added:
log_message(f"Adding {len(added)} new prefixes: {list(added)}")
announce_prefixes(added)
if removed:
log_message(f"Removing {len(removed)} prefixes: {list(removed)}")
withdraw_prefixes(removed)
if added or removed:
prefixes = new_prefixes
log_message(f"Updated prefix count: {len(prefixes)}")
except KeyboardInterrupt:
log_message("Received interrupt signal")
+174 -73
View File
@@ -1,93 +1,194 @@
#!/usr/bin/env python3
"""
Скрипт мониторинга BGP сервера
Скрипт мониторинга FRR BGP сервера
"""
import sys
import os
import time
import subprocess
import json
import time
import sys
from datetime import datetime
from pathlib import Path
from typing import Dict, Any
def run_command(cmd):
"""Выполнение команды и возврат результата"""
# Настройки
LOG_FILE = "/app/logs/monitor.log"
STATUS_FILE = "/app/logs/status.json"
def log_message(message: str):
"""Запись сообщения в лог"""
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}"
print(log_entry, flush=True)
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return result.returncode == 0, result.stdout, result.stderr
with open(LOG_FILE, "a") as f:
f.write(log_entry + "\n")
except (PermissionError, OSError):
pass
def run_vtysh_command(command: str) -> str:
"""Выполнение команды через vtysh"""
try:
result = subprocess.run(
['vtysh', '-c', command],
capture_output=True,
text=True,
timeout=30
)
if result.returncode == 0:
return result.stdout.strip()
else:
log_message(f"vtysh command failed: {command}")
return ""
except Exception as e:
return False, "", str(e)
log_message(f"Error running vtysh command '{command}': {e}")
return ""
def check_container_status():
"""Проверка статуса Docker контейнера"""
success, output, error = run_command("docker ps --filter name=bgp-server --format '{{.Status}}'")
if success and output.strip():
return True, output.strip()
return False, "Container not running"
def get_bgp_summary() -> Dict[str, Any]:
"""Получение сводки BGP"""
summary = run_vtysh_command("show ip bgp summary")
if not summary:
return {"error": "Could not get BGP summary"}
# Парсинг вывода BGP summary
lines = summary.split('\n')
neighbors = []
for line in lines:
if 'BGP neighbor' in line and 'remote AS' in line:
parts = line.split()
if len(parts) >= 8:
neighbor = {
"ip": parts[2].rstrip(','),
"remote_as": parts[7],
"state": parts[-1] if len(parts) > 7 else "Unknown"
}
neighbors.append(neighbor)
return {
"neighbors": neighbors,
"raw_output": summary
}
def check_bgp_session():
"""Проверка BGP сессии"""
success, output, error = run_command("docker exec bgp-server exabgpcli show neighbor")
if success:
return True, output
return False, "Cannot check BGP session"
def get_bgp_routes() -> Dict[str, Any]:
"""Получение BGP маршрутов"""
routes = run_vtysh_command("show ip bgp")
if not routes:
return {"error": "Could not get BGP routes"}
# Подсчет маршрутов
route_count = 0
for line in routes.split('\n'):
if line.strip() and not line.startswith('BGP table') and not line.startswith('*>'):
if any(char.isdigit() for char in line):
route_count += 1
return {
"route_count": route_count,
"raw_output": routes
}
def check_prefixes():
"""Проверка загруженных префиксов"""
def get_frr_status() -> Dict[str, Any]:
"""Получение статуса FRR"""
version = run_vtysh_command("show version")
if not version:
return {"error": "Could not get FRR version"}
return {
"version": version.split('\n')[0] if version else "Unknown",
"raw_output": version
}
def get_system_status() -> Dict[str, Any]:
"""Получение системного статуса"""
try:
with open("/app/logs/prefixes.log", "r") as f:
lines = f.readlines()
return True, f"Found {len(lines)} log entries"
except FileNotFoundError:
return False, "Prefix log not found"
# Проверка процессов FRR
zebra_running = subprocess.run(['pgrep', 'zebra'], capture_output=True).returncode == 0
bgpd_running = subprocess.run(['pgrep', 'bgpd'], capture_output=True).returncode == 0
# Проверка использования памяти
memory_info = {}
try:
with open('/proc/meminfo', 'r') as f:
for line in f:
if 'MemTotal:' in line:
memory_info['total'] = line.split()[1]
elif 'MemAvailable:' in line:
memory_info['available'] = line.split()[1]
except:
pass
return {
"zebra_running": zebra_running,
"bgpd_running": bgpd_running,
"memory": memory_info
}
except Exception as e:
return {"error": f"Could not get system status: {e}"}
def check_network_connectivity():
"""Проверка сетевого подключения"""
success, output, error = run_command("docker exec bgp-server ping -c 1 192.168.1.1")
return success, "Network connectivity OK" if success else "Network connectivity failed"
def save_status(status: Dict[str, Any]):
"""Сохранение статуса в файл"""
try:
with open(STATUS_FILE, 'w') as f:
json.dump(status, f, indent=2)
except Exception as e:
log_message(f"Error saving status: {e}")
def main():
"""Основная функция мониторинга"""
print("=== BGP Server Monitoring ===")
print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
"""Основная функция"""
log_message("Starting FRR monitor...")
# Проверка контейнера
print("1. Container Status:")
status, details = check_container_status()
print(f" Status: {'✓ Running' if status else '✗ Stopped'}")
print(f" Details: {details}")
print()
# Создание директории для логов
try:
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
os.makedirs(os.path.dirname(STATUS_FILE), exist_ok=True)
except (PermissionError, OSError):
pass
# Проверка сети
print("2. Network Connectivity:")
net_ok, net_details = check_network_connectivity()
print(f" Status: {'✓ OK' if net_ok else '✗ Failed'}")
print(f" Details: {net_details}")
print()
# Проверка BGP сессии
print("3. BGP Session:")
bgp_ok, bgp_details = check_bgp_session()
print(f" Status: {'✓ Active' if bgp_ok else '✗ Inactive'}")
if bgp_ok:
print(f" Details: {bgp_details[:200]}...")
else:
print(f" Details: {bgp_details}")
print()
# Проверка префиксов
print("4. Prefixes:")
prefix_ok, prefix_details = check_prefixes()
print(f" Status: {'✓ Loaded' if prefix_ok else '✗ Not loaded'}")
print(f" Details: {prefix_details}")
print()
# Общий статус
overall_status = status and net_ok and bgp_ok and prefix_ok
print("=== Overall Status ===")
print(f"Status: {'✓ HEALTHY' if overall_status else '✗ UNHEALTHY'}")
return 0 if overall_status else 1
while True:
try:
# Сбор статуса
status = {
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"frr": get_frr_status(),
"bgp_summary": get_bgp_summary(),
"bgp_routes": get_bgp_routes(),
"system": get_system_status()
}
# Сохранение статуса
save_status(status)
# Логирование важной информации
bgp_summary = status["bgp_summary"]
if "neighbors" in bgp_summary:
for neighbor in bgp_summary["neighbors"]:
log_message(f"BGP neighbor {neighbor['ip']} (AS {neighbor['remote_as']}): {neighbor['state']}")
bgp_routes = status["bgp_routes"]
if "route_count" in bgp_routes:
log_message(f"BGP routes: {bgp_routes['route_count']}")
system = status["system"]
if "zebra_running" in system and "bgpd_running" in system:
if not system["zebra_running"] or not system["bgpd_running"]:
log_message("WARNING: FRR daemons not running properly")
# Ожидание перед следующей проверкой
time.sleep(60) # Проверка каждую минуту
except KeyboardInterrupt:
log_message("Monitor stopped by user")
break
except Exception as e:
log_message(f"Error in monitor loop: {e}")
time.sleep(30) # Короткая пауза при ошибке
if __name__ == "__main__":
sys.exit(main())
main()
+177 -75
View File
@@ -1,103 +1,205 @@
#!/usr/bin/env python3
"""
Скрипт для перезагрузки префиксов без перезапуска BGP сервера
Скрипт для перезагрузки префиксов в FRR
"""
import subprocess
import sys
import os
import time
import subprocess
import ipaddress
from pathlib import Path
from typing import Set
def run_command(cmd):
"""Выполнение команды"""
# Настройки
DATA_DIR = "/app/data"
LOG_FILE = "/app/logs/reload.log"
PREFIX_FILES = ["prefixes.txt", "additional_prefixes.txt"]
def log_message(message: str):
"""Запись сообщения в лог"""
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}"
print(log_entry, flush=True)
try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return result.returncode == 0, result.stdout, result.stderr
except Exception as e:
return False, "", str(e)
with open(LOG_FILE, "a") as f:
f.write(log_entry + "\n")
except (PermissionError, OSError):
pass
def reload_prefixes():
"""Перезагрузка префиксов"""
print("Reloading prefixes...")
# Остановка процесса загрузки префиксов
print("Stopping prefix loader process...")
success, output, error = run_command("docker exec bgp-server pkill -f load_prefixes.py")
if not success:
print("Warning: Could not stop prefix loader process")
# Ожидание завершения процесса
time.sleep(2)
# Проверка что процесс остановлен
success, output, error = run_command("docker exec bgp-server pgrep -f load_prefixes.py")
if success:
print("Error: Prefix loader process is still running")
return False
print("Prefix loader process stopped successfully")
# Запуск нового процесса загрузки префиксов
print("Starting new prefix loader process...")
success, output, error = run_command("docker exec bgp-server /app/scripts/load_prefixes.py &")
if success:
print("Prefix loader process started successfully")
def validate_prefix(prefix: str) -> bool:
"""Валидация IP префикса"""
try:
ipaddress.ip_network(prefix, strict=False)
return True
else:
print(f"Error starting prefix loader: {error}")
except ValueError:
return False
def check_status():
"""Проверка статуса после перезагрузки"""
print("Checking status...")
time.sleep(5)
def load_prefixes_from_file(file_path: Path) -> Set[str]:
"""Загрузка префиксов из файла"""
prefixes = set()
# Проверка процесса
success, output, error = run_command("docker exec bgp-server pgrep -f load_prefixes.py")
if success:
print("✓ Prefix loader process is running")
else:
print("✗ Prefix loader process is not running")
if not file_path.exists():
log_message(f"File not found: {file_path}")
return prefixes
try:
with open(file_path, 'r') as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
# Пропуск пустых строк и комментариев
if not line or line.startswith('#'):
continue
# Валидация префикса
if validate_prefix(line):
prefixes.add(line)
else:
log_message(f"Invalid prefix in {file_path}:{line_num}: {line}")
except Exception as e:
log_message(f"Error reading {file_path}: {e}")
return prefixes
def load_all_prefixes() -> Set[str]:
"""Загрузка всех префиксов из всех файлов"""
all_prefixes = set()
for filename in PREFIX_FILES:
file_path = Path(DATA_DIR) / filename
prefixes = load_prefixes_from_file(file_path)
all_prefixes.update(prefixes)
log_message(f"Loaded {len(prefixes)} prefixes from {filename}")
return all_prefixes
def get_current_routes() -> Set[str]:
"""Получение текущих статических маршрутов из FRR"""
try:
result = subprocess.run(
['vtysh', '-c', 'show ip route static'],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
log_message("Could not get current routes from FRR")
return set()
routes = set()
for line in result.stdout.split('\n'):
line = line.strip()
if line and 'via Null0' in line:
# Парсинг строки маршрута
parts = line.split()
if len(parts) >= 2:
route = parts[1]
if validate_prefix(route):
routes.add(route)
return routes
except Exception as e:
log_message(f"Error getting current routes: {e}")
return set()
def run_vtysh_command(command: str) -> bool:
"""Выполнение команды через vtysh"""
try:
result = subprocess.run(
['vtysh', '-c', command],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
log_message(f"vtysh command failed: {command}")
return False
return True
except Exception as e:
log_message(f"Error running vtysh command '{command}': {e}")
return False
def announce_prefixes(prefixes: Set[str]):
"""Анонсирование префиксов через FRR"""
log_message(f"Announcing {len(prefixes)} prefixes...")
# Проверка логов
success, output, error = run_command("docker exec bgp-server tail -n 5 /app/logs/prefixes.log")
if success:
print("Recent log entries:")
print(output)
else:
print("No recent log entries found")
for prefix in sorted(prefixes):
command = f"ip route {prefix} Null0"
if run_vtysh_command(command):
log_message(f"Announced prefix: {prefix}")
else:
log_message(f"Failed to announce prefix: {prefix}")
def withdraw_prefixes(prefixes: Set[str]):
"""Отзыв префиксов через FRR"""
log_message(f"Withdrawing {len(prefixes)} prefixes...")
return True
for prefix in sorted(prefixes):
command = f"no ip route {prefix} Null0"
if run_vtysh_command(command):
log_message(f"Withdrew prefix: {prefix}")
else:
log_message(f"Failed to withdraw prefix: {prefix}")
def check_frr_status() -> bool:
"""Проверка статуса FRR"""
try:
result = subprocess.run(
['vtysh', '-c', 'show version'],
capture_output=True,
text=True,
timeout=10
)
return result.returncode == 0
except Exception:
return False
def main():
"""Основная функция"""
print("=== BGP Prefix Reloader ===")
log_message("Starting prefix reload...")
# Проверка что контейнер запущен
success, output, error = run_command("docker ps --filter name=bgp-server --format '{{.Status}}'")
if not success or not output.strip():
print("Error: BGP server container is not running")
print("Please start the container first: docker-compose up -d")
# Проверка статуса FRR
if not check_frr_status():
log_message("ERROR: FRR is not running")
return 1
print("BGP server container is running")
# Загрузка новых префиксов
new_prefixes = load_all_prefixes()
log_message(f"Loaded {len(new_prefixes)} prefixes from files")
# Перезагрузка префиксов
if reload_prefixes():
print("Prefix reload completed successfully")
# Проверка статуса
if check_status():
print("✓ All checks passed")
return 0
else:
print("✗ Some checks failed")
return 1
# Получение текущих маршрутов
current_routes = get_current_routes()
log_message(f"Found {len(current_routes)} current routes in FRR")
# Определение изменений
to_add = new_prefixes - current_routes
to_remove = current_routes - new_prefixes
log_message(f"Changes: {len(to_add)} to add, {len(to_remove)} to remove")
# Применение изменений
if to_remove:
withdraw_prefixes(to_remove)
if to_add:
announce_prefixes(to_add)
# Финальная проверка
final_routes = get_current_routes()
log_message(f"Final route count: {len(final_routes)}")
if len(final_routes) == len(new_prefixes):
log_message("Reload completed successfully!")
return 0
else:
print("✗ Prefix reload failed")
log_message("WARNING: Route count mismatch after reload")
return 1
if __name__ == "__main__":
+89 -62
View File
@@ -1,96 +1,123 @@
# PowerShell скрипт для запуска BGP сервера
# Скрипт запуска BGP Server (FRR)
param(
[string]$ContainerName = "bgp-server",
[string]$DataPath = "./data",
[string]$LogsPath = "./logs",
[switch]$Build,
[switch]$Logs,
[switch]$Monitor
[switch]$Force
)
Write-Host "=== BGP Server Management ===" -ForegroundColor Green
Write-Host "=== BGP Server (FRR) Startup Script ===" -ForegroundColor Green
# Проверка Docker
Write-Host "Checking Docker..." -ForegroundColor Yellow
try {
docker --version | Out-Null
Write-Host "✓ Docker is available" -ForegroundColor Green
} catch {
Write-Host "✗ Docker is not available. Please install Docker Desktop." -ForegroundColor Red
exit 1
# Проверка существования контейнера
$containerExists = docker ps -a --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
if ($containerExists) {
Write-Host "Found existing container: $ContainerName" -ForegroundColor Yellow
if (-not $Force) {
$response = Read-Host "Do you want to stop and remove the existing container? (y/N)"
if ($response -ne "y" -and $response -ne "Y") {
Write-Host "Operation cancelled." -ForegroundColor Red
exit 0
}
}
# Остановка и удаление старого контейнера
Write-Host "Stopping container..." -ForegroundColor Yellow
docker stop $ContainerName
Write-Host "Removing container..." -ForegroundColor Yellow
docker rm $ContainerName
}
# Проверка Docker Compose
Write-Host "Checking Docker Compose..." -ForegroundColor Yellow
try {
docker-compose --version | Out-Null
Write-Host "✓ Docker Compose is available" -ForegroundColor Green
} catch {
Write-Host "✗ Docker Compose is not available." -ForegroundColor Red
exit 1
# Создание директорий если не существуют
if (-not (Test-Path $DataPath)) {
Write-Host "Creating data directory: $DataPath" -ForegroundColor Yellow
New-Item -ItemType Directory -Path $DataPath -Force | Out-Null
}
# Создание необходимых директорий
Write-Host "Creating directories..." -ForegroundColor Yellow
if (!(Test-Path "logs")) {
New-Item -ItemType Directory -Path "logs" | Out-Null
Write-Host "✓ Created logs directory" -ForegroundColor Green
if (-not (Test-Path $LogsPath)) {
Write-Host "Creating logs directory: $LogsPath" -ForegroundColor Yellow
New-Item -ItemType Directory -Path $LogsPath -Force | Out-Null
}
if (!(Test-Path "data")) {
New-Item -ItemType Directory -Path "data" | Out-Null
Write-Host "✓ Created data directory" -ForegroundColor Green
# Создание файла с префиксами если не существует
$prefixesFile = Join-Path $DataPath "prefixes.txt"
if (-not (Test-Path $prefixesFile)) {
Write-Host "Creating default prefixes file..." -ForegroundColor Yellow
@"
# Default prefixes file
# Add your prefixes here, one per line
192.168.1.0/24
10.0.0.0/8
172.16.0.0/12
"@ | Out-File -FilePath $prefixesFile -Encoding UTF8
}
# Сборка образа если требуется
if ($Build) {
Write-Host "Building Docker image..." -ForegroundColor Yellow
docker-compose build
docker build -t bgp-server-frr .
if ($LASTEXITCODE -ne 0) {
Write-Host "✗ Build failed" -ForegroundColor Red
Write-Host "Failed to build image. Exiting." -ForegroundColor Red
exit 1
}
Write-Host "✓ Build completed" -ForegroundColor Green
}
# Остановка существующего контейнера
Write-Host "Stopping existing container..." -ForegroundColor Yellow
docker-compose down 2>$null
Write-Host "✓ Existing container stopped" -ForegroundColor Green
# Запуск контейнера
Write-Host "Starting BGP Server container..." -ForegroundColor Yellow
$currentPath = Get-Location
$dataVolume = "${currentPath}\${DataPath}:/app/data:ro"
$logsVolume = "${currentPath}\${LogsPath}:/app/logs"
# Запуск сервера
Write-Host "Starting BGP server..." -ForegroundColor Yellow
docker-compose up -d
docker run -d `
--name $ContainerName `
--restart unless-stopped `
-p 179:179 `
-v $dataVolume `
-v $logsVolume `
--cap-add NET_ADMIN `
--privileged `
bgp-server-frr
if ($LASTEXITCODE -eq 0) {
Write-Host "✓ BGP server started successfully" -ForegroundColor Green
Write-Host "Container started successfully!" -ForegroundColor Green
# Ожидание запуска
Write-Host "Waiting for server to initialize..." -ForegroundColor Yellow
Write-Host "Waiting for container to start..." -ForegroundColor Yellow
Start-Sleep -Seconds 10
# Проверка статуса
Write-Host "Checking server status..." -ForegroundColor Yellow
$status = docker-compose ps
Write-Host $status
$status = docker ps --filter "name=$ContainerName" --format "table {{.Status}}"
Write-Host "Container status: $status" -ForegroundColor Cyan
if ($Logs) {
Write-Host "Showing logs..." -ForegroundColor Yellow
docker-compose logs -f bgp-server
# Проверка FRR статуса
Write-Host "Checking FRR status..." -ForegroundColor Cyan
docker exec $ContainerName vtysh -c "show version" 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host "FRR is running successfully!" -ForegroundColor Green
# Показ BGP статуса
Write-Host "BGP Summary:" -ForegroundColor Cyan
docker exec $ContainerName vtysh -c "show ip bgp summary" 2>$null
# Показ логов
Write-Host "Recent logs:" -ForegroundColor Cyan
docker logs --tail=10 $ContainerName
Write-Host "`nBGP Server (FRR) is ready!" -ForegroundColor Green
Write-Host "To view logs: docker logs -f $ContainerName" -ForegroundColor Cyan
Write-Host "To check BGP status: docker exec $ContainerName vtysh -c 'show ip bgp summary'" -ForegroundColor Cyan
Write-Host "To access FRR CLI: docker exec -it $ContainerName vtysh" -ForegroundColor Cyan
} else {
Write-Host "FRR failed to start properly. Check logs:" -ForegroundColor Red
docker logs $ContainerName
}
if ($Monitor) {
Write-Host "Starting monitoring..." -ForegroundColor Yellow
docker exec bgp-server python3 /app/scripts/monitor.py
}
} else {
Write-Host "Failed to start BGP server" -ForegroundColor Red
Write-Host "Check logs with: docker-compose logs bgp-server" -ForegroundColor Yellow
Write-Host "Failed to start container. Check the error above." -ForegroundColor Red
exit 1
}
Write-Host "=== Setup Complete ===" -ForegroundColor Green
Write-Host "Useful commands:" -ForegroundColor Cyan
Write-Host " View logs: docker-compose logs -f bgp-server" -ForegroundColor White
Write-Host " Check status: docker-compose ps" -ForegroundColor White
Write-Host " Stop server: docker-compose down" -ForegroundColor White
Write-Host " Monitor: docker exec bgp-server python3 /app/scripts/monitor.py" -ForegroundColor White
}
+104 -154
View File
@@ -1,56 +1,24 @@
#!/bin/bash
# Скрипт запуска BGP сервера
# Скрипт запуска BGP сервера на FRR
set -e
echo "Starting BGP Server..."
echo "Starting BGP Server (FRR)..."
# Создание директорий если не существуют
mkdir -p /app/logs
mkdir -p /app/run
mkdir -p /run/exabgp
mkdir -p /app/data
mkdir -p /var/run/frr
mkdir -p /etc/frr
# Установка правильных прав доступа
chmod 755 /app/logs
chmod 755 /app/run
chmod 755 /run/exabgp
chmod 755 /app/data
# Удаление старых named pipes если они существуют
echo "Cleaning up old named pipes..."
for dir in /run/exabgp /var/run/exabgp /usr/local/run/exabgp /usr/local/var/run/exabgp; do
if [ -d "$dir" ]; then
echo "Cleaning $dir..."
rm -f $dir/exabgp.in $dir/exabgp.out
rmdir $dir 2>/dev/null || true
fi
done
# Создание named pipes для CLI в стандартном месте
echo "Creating named pipes for ExaBGP CLI..."
for dir in /run/exabgp /var/run/exabgp /usr/local/run/exabgp /usr/local/var/run/exabgp; do
mkdir -p $dir
echo "Creating named pipes in $dir..."
# Проверяем, существуют ли уже named pipes
if [ ! -p "$dir/exabgp.in" ]; then
mkfifo $dir/exabgp.in
chmod 666 $dir/exabgp.in
echo "Created $dir/exabgp.in"
else
echo "Named pipe $dir/exabgp.in already exists"
fi
if [ ! -p "$dir/exabgp.out" ]; then
mkfifo $dir/exabgp.out
chmod 666 $dir/exabgp.out
echo "Created $dir/exabgp.out"
else
echo "Named pipe $dir/exabgp.out already exists"
fi
done
chmod 755 /var/run/frr
chmod 755 /etc/frr
# Проверка наличия файлов с префиксами
if [ ! -f "/app/data/prefixes.txt" ]; then
@@ -62,9 +30,9 @@ fi
# Создание лог-файлов с правильными правами
echo "Creating log files with proper permissions..."
touch /app/logs/prefixes.log
touch /app/logs/exabgp.log
touch /app/logs/frr.log
chmod 666 /app/logs/prefixes.log
chmod 666 /app/logs/exabgp.log
chmod 666 /app/logs/frr.log
echo "Prefixes file content:"
cat /app/data/prefixes.txt
@@ -77,7 +45,7 @@ ls -la /app/scripts/
echo "---"
# Генерация конфигурации из переменных окружения
echo "Generating ExaBGP configuration from environment variables..."
echo "Generating FRR configuration from environment variables..."
echo "Environment variables:"
env | grep BGP_ || echo "No BGP_ variables found"
echo "---"
@@ -85,11 +53,20 @@ echo "---"
python3 /app/scripts/generate_config.py
# Проверка конфигурации
echo "Validating ExaBGP configuration..."
echo "Validating FRR configuration..."
echo "Configuration file content:"
cat /app/exabgp.conf
cat /etc/frr/frr.conf
echo "---"
exabgp --validate /app/exabgp.conf
# Проверка синтаксиса конфигурации FRR
if vtysh -c "show running-config" > /dev/null 2>&1; then
echo "FRR configuration validation passed"
else
echo "FRR configuration validation failed"
echo "Full config content:"
cat /etc/frr/frr.conf
exit 1
fi
# Тестовый запуск скрипта загрузки префиксов
echo "Testing prefix loader script..."
@@ -105,135 +82,108 @@ else
echo "Warning: Cannot reach $NEIGHBOR_IP. BGP session may not establish."
fi
# Запуск ExaBGP в фоновом режиме с логированием
echo "Starting ExaBGP..."
LOG_LEVEL=${BGP_LOG_LEVEL:-INFO}
# Запуск FRR демонов
echo "Starting FRR daemons..."
# Дополнительная проверка конфигурационного файла
echo "Final config file check:"
ls -la /app/exabgp.conf
echo "Config file first few lines:"
head -10 /app/exabgp.conf
echo "---"
# Запуск zebra (обязательный демон для FRR)
echo "Starting zebra daemon..."
zebra -d -f /etc/frr/frr.conf -A 127.0.0.1 -z /var/run/frr/zebra.api
sleep 2
# Проверка что ExaBGP может прочитать файл
echo "Testing ExaBGP config validation:"
if exabgp --validate /app/exabgp.conf; then
echo "Configuration validation passed"
else
echo "Configuration validation failed"
echo "Full config content:"
cat /app/exabgp.conf
exit 1
fi
echo "---"
# Запуск bgpd
echo "Starting bgpd daemon..."
bgpd -d -f /etc/frr/frr.conf -A 127.0.0.1 -z /var/run/frr/zebra.api
sleep 2
# Проверка переменных окружения и путей
echo "Environment check:"
echo "PWD: $PWD"
echo "PATH: $PATH"
echo "PYTHONPATH: $PYTHONPATH"
echo "BGP_ variables:"
env | grep BGP_ || echo "No BGP_ variables found"
echo "---"
# Проверка что демоны запустились
echo "Checking if FRR daemons are running..."
ps aux | grep -E "(zebra|bgpd)" | grep -v grep || echo "No FRR daemons found in ps"
# Запуск ExaBGP
echo "Starting ExaBGP with config: /app/exabgp.conf"
# Проверяем что файл существует и читается
if [ ! -f "/app/exabgp.conf" ]; then
echo "ERROR: Configuration file /app/exabgp.conf not found!"
exit 1
fi
if [ ! -r "/app/exabgp.conf" ]; then
echo "ERROR: Configuration file /app/exabgp.conf is not readable!"
exit 1
fi
# Запуск ExaBGP с правильными параметрами
cd /app
echo "Starting ExaBGP in background..."
# Запуск ExaBGP в фоновом режиме
if [ -n "$LOG_LEVEL" ]; then
nohup exabgp --log.level $LOG_LEVEL /app/exabgp.conf > /app/logs/exabgp.log 2>&1 &
else
nohup exabgp /app/exabgp.conf > /app/logs/exabgp.log 2>&1 &
fi
EXABGP_PID=$!
# Проверяем что процесс запустился
sleep 5
echo "Checking if ExaBGP process is running..."
ps aux | grep exabgp | grep -v grep || echo "No exabgp process found in ps"
if ! kill -0 $EXABGP_PID 2>/dev/null; then
echo "Failed to start ExaBGP. Checking logs:"
cat /app/logs/exabgp.log
echo "Trying to run ExaBGP directly for diagnosis:"
exabgp --version
echo "---"
echo "Direct execution test:"
timeout 10 exabgp /app/exabgp.conf || echo "Direct execution completed"
exit 1
fi
# Сохранение PID
echo $EXABGP_PID > /app/logs/exabgp.pid
# Сохранение PID файлов
echo "Saving PID files..."
pgrep zebra > /app/logs/zebra.pid 2>/dev/null || echo "zebra PID not found"
pgrep bgpd > /app/logs/bgpd.pid 2>/dev/null || echo "bgpd PID not found"
# Ожидание запуска
sleep 5
# Проверка статуса
if kill -0 $EXABGP_PID 2>/dev/null; then
echo "ExaBGP started successfully with PID: $EXABGP_PID"
echo "Recent logs:"
tail -10 /app/logs/exabgp.log
# Проверка статуса через vtysh
echo "Checking FRR status via vtysh..."
if vtysh -c "show version" > /dev/null 2>&1; then
echo "FRR started successfully"
echo "FRR version:"
vtysh -c "show version" 2>/dev/null || echo "Could not get version"
# Дополнительная проверка через несколько секунд
sleep 3
if kill -0 $EXABGP_PID 2>/dev/null; then
echo "ExaBGP is still running after 3 seconds"
echo "Process details:"
ps aux | grep exabgp | grep -v grep || echo "Process not found in ps output"
else
echo "ExaBGP process died after startup"
echo "Full logs:"
cat /app/logs/exabgp.log
exit 1
fi
echo "BGP neighbors:"
vtysh -c "show ip bgp neighbors" 2>/dev/null || echo "Could not get BGP neighbors"
echo "BGP summary:"
vtysh -c "show ip bgp summary" 2>/dev/null || echo "Could not get BGP summary"
else
echo "Failed to start ExaBGP"
echo "Full logs:"
cat /app/logs/exabgp.log
echo "---"
echo "Process status:"
ps aux | grep exabgp || echo "No exabgp process found"
echo "Failed to start FRR. Checking logs:"
cat /app/logs/frr.log 2>/dev/null || echo "No FRR logs found"
exit 1
fi
# Запуск скрипта загрузки префиксов в фоновом режиме
echo "Starting prefix loader in background..."
python3 /app/scripts/load_prefixes.py > /app/logs/prefixes.log 2>&1 &
PREFIX_LOADER_PID=$!
echo $PREFIX_LOADER_PID > /app/logs/prefix_loader.pid
# Запуск монитора в фоновом режиме
echo "Starting monitor in background..."
python3 /app/scripts/monitor.py > /app/logs/monitor.log 2>&1 &
MONITOR_PID=$!
echo $MONITOR_PID > /app/logs/monitor.pid
echo "All services started successfully!"
echo "Recent logs:"
tail -10 /app/logs/prefixes.log 2>/dev/null || echo "No prefix logs yet"
echo "---"
# Функция для graceful shutdown
cleanup() {
echo "Shutting down BGP server..."
if [ -f "/app/logs/exabgp.pid" ]; then
kill $(cat /app/logs/exabgp.pid) 2>/dev/null || true
echo "Received shutdown signal. Cleaning up..."
# Остановка скриптов
if [ -f "/app/logs/prefix_loader.pid" ]; then
kill $(cat /app/logs/prefix_loader.pid) 2>/dev/null || true
fi
if [ -f "/app/logs/monitor.pid" ]; then
kill $(cat /app/logs/monitor.pid) 2>/dev/null || true
fi
# Отзыв всех префиксов
echo "Withdrawing all prefixes..."
python3 /app/scripts/load_prefixes.py --withdraw > /dev/null 2>&1 || true
# Остановка FRR демонов
echo "Stopping FRR daemons..."
killall bgpd 2>/dev/null || true
killall zebra 2>/dev/null || true
echo "Cleanup completed."
exit 0
}
# Обработка сигналов
# Установка обработчиков сигналов
trap cleanup SIGTERM SIGINT
# Ожидание завершения
echo "Waiting for ExaBGP to run..."
echo "Process status:"
ps aux | grep exabgp || echo "No exabgp process found"
echo "---"
# Проверка процесса загрузки префиксов
echo "Checking prefix loader process:"
ps aux | grep load_prefixes || echo "No prefix loader process found"
echo "---"
wait $EXABGP_PID
echo "BGP Server is running. Press Ctrl+C to stop."
while true; do
sleep 10
# Проверка что демоны все еще работают
if ! pgrep zebra > /dev/null; then
echo "ERROR: zebra daemon stopped unexpectedly"
exit 1
fi
if ! pgrep bgpd > /dev/null; then
echo "ERROR: bgpd daemon stopped unexpectedly"
exit 1
fi
done
+54 -21
View File
@@ -1,33 +1,66 @@
# PowerShell скрипт для остановки BGP сервера
# Скрипт остановки BGP Server (FRR)
Write-Host "=== Stopping BGP Server ===" -ForegroundColor Yellow
param(
[string]$ContainerName = "bgp-server",
[switch]$Force
)
# Проверка что контейнер запущен
$containerStatus = docker ps --filter name=bgp-server --format "{{.Status}}"
if (!$containerStatus) {
Write-Host "BGP server is not running" -ForegroundColor Yellow
Write-Host "=== BGP Server (FRR) Stop Script ===" -ForegroundColor Green
# Проверка существования контейнера
$containerExists = docker ps -a --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
if (-not $containerExists) {
Write-Host "Container $ContainerName not found." -ForegroundColor Yellow
exit 0
}
Write-Host "BGP server is running. Stopping..." -ForegroundColor Yellow
# Проверка статуса контейнера
$containerRunning = docker ps --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
# Остановка контейнера
docker-compose down
if ($LASTEXITCODE -eq 0) {
Write-Host "✓ BGP server stopped successfully" -ForegroundColor Green
if ($containerRunning) {
Write-Host "Container $ContainerName is running. Stopping..." -ForegroundColor Yellow
if (-not $Force) {
$response = Read-Host "Do you want to stop the container? (y/N)"
if ($response -ne "y" -and $response -ne "Y") {
Write-Host "Operation cancelled." -ForegroundColor Red
exit 0
}
}
# Graceful shutdown - отзыв префиксов
Write-Host "Withdrawing prefixes..." -ForegroundColor Yellow
docker exec $ContainerName python3 /app/scripts/load_prefixes.py --withdraw 2>$null
# Остановка контейнера
Write-Host "Stopping container..." -ForegroundColor Yellow
docker stop $ContainerName
if ($LASTEXITCODE -eq 0) {
Write-Host "Container stopped successfully!" -ForegroundColor Green
} else {
Write-Host "Failed to stop container." -ForegroundColor Red
exit 1
}
} else {
Write-Host "✗ Failed to stop BGP server" -ForegroundColor Red
exit 1
Write-Host "Container $ContainerName is not running." -ForegroundColor Yellow
}
# Проверка что контейнер остановлен
$containerStatus = docker ps --filter name=bgp-server --format "{{.Status}}"
if (!$containerStatus) {
Write-Host "✓ Container is stopped" -ForegroundColor Green
# Удаление контейнера если требуется
if ($Force) {
Write-Host "Removing container..." -ForegroundColor Yellow
docker rm $ContainerName 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host "Container removed successfully!" -ForegroundColor Green
} else {
Write-Host "Container was already removed or removal failed." -ForegroundColor Yellow
}
} else {
Write-Host "Container is still running" -ForegroundColor Red
exit 1
Write-Host "Container stopped but not removed." -ForegroundColor Cyan
Write-Host "To remove container, run: docker rm $ContainerName" -ForegroundColor Cyan
Write-Host "Or use -Force parameter to stop and remove in one command." -ForegroundColor Cyan
}
Write-Host "=== BGP Server Stopped ===" -ForegroundColor Green
Write-Host "BGP Server (FRR) stopped successfully!" -ForegroundColor Green