3 Commits
15 changed files with 1242 additions and 837 deletions
+17 -9
View File
@@ -1,21 +1,27 @@
FROM python:3.9-slim FROM ubuntu:22.04
# Установка системных зависимостей # Установка системных зависимостей и FRR
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
frr \
frr-pythontools \
python3 \
python3-pip \
iproute2 \ iproute2 \
iputils-ping \ iputils-ping \
net-tools \ net-tools \
procps \ procps \
vim \
curl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Установка ExaBGP # Установка Python зависимостей
RUN pip install exabgp 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 scripts/ /app/scripts/
COPY data/ /app/data/ COPY data/ /app/data/
@@ -23,6 +29,7 @@ COPY data/ /app/data/
RUN chmod +x /app/scripts/start.sh RUN chmod +x /app/scripts/start.sh
RUN chmod +x /app/scripts/load_prefixes.py RUN chmod +x /app/scripts/load_prefixes.py
RUN chmod +x /app/scripts/generate_config.py RUN chmod +x /app/scripts/generate_config.py
RUN chmod +x /app/scripts/monitor.py
# Рабочая директория # Рабочая директория
WORKDIR /app WORKDIR /app
@@ -32,12 +39,13 @@ EXPOSE 179
# Установка переменных окружения по умолчанию # Установка переменных окружения по умолчанию
ENV BGP_LOCAL_AS=65000 ENV BGP_LOCAL_AS=65000
ENV BGP_ROUTER_ID=192.168.1.100 ENV BGP_ROUTER_ID=192.168.100.99
ENV BGP_NEIGHBOR_IP=192.168.1.1 ENV BGP_NEIGHBOR_IP=192.168.0.254
ENV BGP_NEIGHBOR_AS=65001 ENV BGP_NEIGHBOR_AS=65001
ENV BGP_HOLD_TIME=90 ENV BGP_HOLD_TIME=90
ENV BGP_KEEPALIVE=30 ENV BGP_KEEPALIVE=30
ENV BGP_LOG_LEVEL=INFO ENV BGP_LOG_LEVEL=info
ENV FRR_DAEMONS="bgpd zebra"
# Команда запуска # Команда запуска
ENTRYPOINT ["/app/scripts/start.sh"] ENTRYPOINT ["/app/scripts/start.sh"]
+242 -146
View File
@@ -1,228 +1,324 @@
# Быстрый старт BGP сервера # Быстрый старт BGP Server (FRR)
## Минимальные требования Этот документ поможет вам быстро запустить BGP сервер на базе FRR для раздачи префиксов.
## Предварительные требования
- Docker Desktop для Windows - Docker Desktop для Windows
- PowerShell - PowerShell
- RouterOS 7.14+ (на стороне клиента) - RouterOS 7.14+ (для клиентской стороны)
## Быстрый запуск (5 минут) ## Шаг 1: Подготовка файлов
### 1. Клонирование и подготовка ### Создание файла с префиксами
```powershell Создайте файл `data/prefixes.txt` с вашими префиксами:
# Клонирование репозитория (если нужно)
git clone <repository-url>
cd bgp-server
# Создание необходимых директорий
mkdir logs
```
### 2. Настройка префиксов
Отредактируйте файл `data/prefixes.txt`:
``` ```
# Основные префиксы
192.168.1.0/24 192.168.1.0/24
192.168.2.0/24
10.0.0.0/8 10.0.0.0/8
172.16.0.0/12 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 ```powershell
# Запуск с автоматической сборкой # Запуск с автоматической сборкой образа
.\scripts\start-server.ps1 -Build .\scripts\start-server.ps1 -Build
# Или вручную # Или запуск без пересборки
docker-compose up -d --build .\scripts\start-server.ps1
``` ```
### 4. Проверка работы ### Вариант B: Использование Docker Compose
```powershell ```powershell
# Проверка статуса # Сборка и запуск
docker-compose ps docker-compose up -d --build
# Просмотр логов # Или только запуск
docker-compose logs -f bgp-server docker-compose up -d
# Мониторинг
docker exec bgp-server python3 /app/scripts/monitor.py
``` ```
### 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 ```routeros
/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 /routing bgp instance
/routing bgp peer add name=bgp-server remote-address=192.168.1.100 remote-as=65000 instance=bgp-server add name=bgp-server as=65001 router-id=192.168.0.254
# Настройка BGP сети
/routing bgp network
add network=192.168.0.0/24
# Настройка BGP пира
/routing bgp peer
add name=bgp-server remote-address=192.168.100.99 remote-as=65000 instance=bgp-server
# Включение BGP
/routing bgp instance set bgp-server disabled=no /routing bgp instance set bgp-server disabled=no
``` ```
### 6. Проверка BGP сессии ### Проверка BGP сессии
В RouterOS:
```routeros ```routeros
# Статус BGP
/routing bgp peer print /routing bgp peer print
# Полученные маршруты
/routing bgp route print
``` ```
Ожидаемый результат: ## Шаг 5: Мониторинг
```
Flags: X - disabled, I - invalid, D - dynamic, E - established
0 name="bgp-server" ... state=established uptime=1m30s prefix-count=8
```
## Полезные команды ### Просмотр логов
### Управление сервером
```powershell ```powershell
# Запуск # Логи FRR
.\scripts\start-server.ps1 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 .\scripts\stop-server.ps1
# Перезапуск # Остановка с удалением контейнера
docker-compose restart .\scripts\stop-server.ps1 -Force
# Просмотр логов
docker-compose logs -f bgp-server
``` ```
### Мониторинг ### Перезагрузка префиксов
```powershell ```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 exec bgp-server python3 /app/scripts/reload_prefixes.py
# Или перезапуск сервера
docker-compose restart
``` ```
## Устранение неполадок ### Обновление контейнера
```powershell
# Обновление с пересборкой
.\scripts\update-container.ps1 -Force
```
## Диагностика
### Проблема: Контейнер не запускается ### Проблема: Контейнер не запускается
```powershell ```powershell
# Проверка логов # Проверка логов
docker-compose logs bgp-server docker logs bgp-server
# Проверка портов # Проверка портов
netstat -an | findstr :179 netstat -an | findstr :179
# Пересборка образа # Проверка Docker
docker-compose build --no-cache docker system info
``` ```
### Проблема: BGP сессия не устанавливается ### Проблема: BGP сессия не устанавливается
```powershell ```powershell
# Проверка сетевого подключения # Проверка сетевой связности
docker exec bgp-server ping 192.168.1.1 docker exec bgp-server ping 192.168.0.254
# Проверка конфигурации # Проверка конфигурации FRR
docker exec bgp-server cat /app/exabgp.conf docker exec bgp-server vtysh -c "show running-config"
# Проверка логов # Проверка статуса BGP
docker-compose logs bgp-server docker exec bgp-server vtysh -c "show ip bgp summary"
``` ```
### Проблема: Префиксы не анонсируются ### Проблема: Префиксы не анонсируются
```powershell ```powershell
# Проверка файлов с префиксами # Проверка файлов префиксов
docker exec bgp-server cat /app/data/prefixes.txt 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 адресов Вы можете настроить BGP параметры через переменные окружения:
Отредактируйте `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
```powershell ```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.100.99 \
-e BGP_NEIGHBOR_IP=192.168.0.254 \
-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/
+152 -166
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+ для получения префиксов - **Клиент**: RouterOS 7.14+ для получения префиксов
- **Протокол**: BGP (только исходящие анонсы) - **Протокол**: BGP (только исходящие анонсы)
## Преимущества FRR
- **Стабильность**: Производственный уровень надежности
- **Производительность**: Оптимизирован для высоких нагрузок
- **Функциональность**: Полная поддержка BGP функций
- **Мониторинг**: Встроенные инструменты диагностики
- **Сообщество**: Активная поддержка и развитие
## Структура проекта ## Структура проекта
``` ```
bgp-server/ bgp-server/
├── docker-compose.yml # Конфигурация Docker ├── docker-compose.yml # Конфигурация Docker
├── Dockerfile # Образ Docker ├── Dockerfile # Образ Docker с FRR
├── exabgp.conf # Конфигурация ExaBGP ├── frr.conf # Конфигурация FRR
├── scripts/ ├── scripts/
│ ├── start.sh # Скрипт запуска │ ├── start.sh # Скрипт запуска FRR
── load_prefixes.py # Загрузка префиксов из файлов ── load_prefixes.py # Загрузка префиксов в FRR
│ ├── generate_config.py # Генерация конфигурации FRR
│ └── monitor.py # Мониторинг FRR
├── data/ ├── data/
│ ├── prefixes.txt # Основной файл с префиксами │ ├── prefixes.txt # Основной файл с префиксами
│ └── additional_prefixes.txt # Дополнительные префиксы │ └── additional_prefixes.txt # Дополнительные префиксы
├── logs/ # Логи ExaBGP ├── logs/ # Логи FRR
└── README.md # Эта инструкция └── README.md # Эта инструкция
``` ```
@@ -56,6 +66,9 @@ docker-compose logs -f bgp-server
# Проверка статуса контейнера # Проверка статуса контейнера
docker-compose ps docker-compose ps
# Проверка BGP сессии через vtysh
docker exec bgp-server vtysh -c "show ip bgp summary"
``` ```
## Подробная настройка ## Подробная настройка
@@ -91,45 +104,17 @@ docker-compose ps
### Шаг 2: Конфигурация BGP сервера ### Шаг 2: Конфигурация BGP сервера
Отредактируйте `exabgp.conf`: Конфигурация FRR генерируется автоматически из переменных окружения в `docker-compose.yml`:
```ini ```yaml
# Основная конфигурация environment:
process load-prefixes { - BGP_LOCAL_AS=65000
run /app/scripts/load_prefixes.py; - BGP_ROUTER_ID=192.168.1.100
encoder json; - BGP_NEIGHBOR_IP=192.168.1.1
} - BGP_NEIGHBOR_AS=65001
- BGP_HOLD_TIME=90
# Настройки BGP - BGP_KEEPALIVE=30
neighbor 192.168.1.1 { - BGP_LOG_LEVEL=info
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;
}
}
}
``` ```
### Шаг 3: Настройка Docker ### Шаг 3: Настройка Docker
@@ -150,18 +135,21 @@ services:
- ./logs:/app/logs - ./logs:/app/logs
environment: environment:
- BGP_LOCAL_AS=65000 - BGP_LOCAL_AS=65000
- BGP_ROUTER_ID=192.168.1.100 - BGP_ROUTER_ID=192.168.100.99
- BGP_NEIGHBOR_IP=192.168.1.1 - BGP_NEIGHBOR_IP=192.168.0.254
- BGP_NEIGHBOR_AS=65001 - BGP_NEIGHBOR_AS=65001
networks: networks:
- bgp-network - bgp-network
cap_add:
- NET_ADMIN
privileged: true
networks: networks:
bgp-network: bgp-network:
driver: bridge driver: bridge
ipam: ipam:
config: config:
- subnet: 192.168.1.0/24 - subnet: 192.168.100.0/24
``` ```
### Шаг 4: Настройка RouterOS ### Шаг 4: Настройка RouterOS
@@ -171,15 +159,15 @@ networks:
```routeros ```routeros
# Создание BGP экземпляра # Создание BGP экземпляра
/routing bgp instance /routing bgp instance
add name=bgp-server as=65001 router-id=192.168.1.1 add name=bgp-server as=65001 router-id=192.168.0.254
# Настройка BGP сети # Настройка BGP сети
/routing bgp network /routing bgp network
add network=192.168.1.0/24 add network=192.168.0.0/24
# Настройка BGP пира # Настройка BGP пира
/routing bgp peer /routing bgp peer
add name=bgp-server remote-address=192.168.1.100 remote-as=65000 instance=bgp-server add name=bgp-server remote-address=192.168.100.99 remote-as=65000 instance=bgp-server
# Включение BGP # Включение BGP
/routing bgp instance set bgp-server disabled=no /routing bgp instance set bgp-server disabled=no
@@ -195,70 +183,130 @@ docker-compose up -d
docker-compose logs -f bgp-server docker-compose logs -f bgp-server
# Проверка статуса BGP сессии # Проверка статуса 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 ```powershell
# Все логи # Подключение к FRR CLI
docker-compose logs bgp-server docker exec -it bgp-server vtysh
# Логи в реальном времени # Просмотр BGP соседей
docker-compose logs -f bgp-server show ip bgp neighbors
# Логи за последние 100 строк # Просмотр BGP маршрутов
docker-compose logs --tail=100 bgp-server show ip bgp
# Просмотр статических маршрутов
show ip route
# Просмотр конфигурации
show running-config
``` ```
### Проверка статуса ### Мониторинг через скрипты
```powershell ```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.0.254"
```
### Проверка маршрутов
```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 ```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 сессия не устанавливается ### Проблема: BGP сессия не устанавливается
1. Проверьте сетевое подключение: 1. Проверьте сетевую связность:
```powershell ```powershell
docker exec bgp-server ping 192.168.1.1 docker exec bgp-server ping 192.168.0.254
``` ```
2. Проверьте конфигурацию: 2. Проверьте конфигурацию BGP:
```powershell ```powershell
docker exec bgp-server cat /app/exabgp.conf docker exec bgp-server vtysh -c "show running-config"
``` ```
3. Проверьте логи: 3. Проверьте логи FRR:
```powershell ```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 docker exec bgp-server cat /app/data/prefixes.txt
``` ```
2. Проверьте логи процесса загрузки: 2. Проверьте логи загрузки префиксов:
```powershell ```powershell
docker exec bgp-server cat /app/logs/prefixes.log docker exec bgp-server tail -f /app/logs/prefixes.log
``` ```
### Проблема: Docker контейнер не запускается 3. Проверьте статические маршруты:
1. Проверьте порты:
```powershell ```powershell
netstat -an | findstr :179 docker exec bgp-server vtysh -c "show ip route static"
``` ```
2. Проверьте Docker логи: ### Проблема: Высокое потребление ресурсов
1. Проверьте использование памяти:
```powershell ```powershell
docker-compose logs docker exec bgp-server free -h
```
2. Проверьте количество маршрутов:
```powershell
docker exec bgp-server vtysh -c "show ip bgp summary"
``` ```
## Безопасность ## Безопасность
### Рекомендации по безопасности - FRR работает в привилегированном контейнере для доступа к сетевым интерфейсам
- Используйте route-maps для фильтрации трафика
1. **Ограничение доступа**: Настройте firewall для ограничения доступа к порту 179 - Ограничьте доступ к vtysh CLI
2. **Аутентификация**: Используйте MD5 аутентификацию в BGP - Регулярно обновляйте образ Docker
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 оптимизирован для обработки большого количества маршрутов
- Поддерживает до 1 миллиона маршрутов
- Эффективное использование памяти
- Быстрое время сходимости
1. **Кэширование**: Используйте Redis для кэширования префиксов ## Поддержка
2. **База данных**: Для больших объемов используйте PostgreSQL
3. **Мониторинг**: Настройте метрики производительности
### Мониторинг ресурсов - Документация FRR: https://frrouting.org/
- GitHub проекта: https://github.com/FRRouting/frr
```powershell - Сообщество: https://lists.frrouting.org/
# Использование ресурсов контейнера
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 позволяет быстро настроить клиентскую сторону.
Для продакшн использования рекомендуется:
- Настроить мониторинг и алертинг
- Добавить резервное копирование конфигурации
- Реализовать автоматическое восстановление после сбоев
- Настроить централизованное логирование
+5 -10
View File
@@ -1,14 +1,9 @@
# Основные префиксы для анонсирования # Основные префиксы
# Формат: IP/маска (например: 192.168.1.0/24) 192.168.100.0/24
192.168.101.0/24
# Приватные сети
192.168.1.0/24
192.168.2.0/24
192.168.10.0/24
10.0.0.0/8 10.0.0.0/8
172.16.0.0/12 172.16.0.0/12
# Дополнительные сети # Дополнительные префиксы
203.0.113.0/24 203.0.113.0/24
198.51.100.0/24 198.51.100.0/24
203.0.113.1/32
+7 -3
View File
@@ -12,17 +12,21 @@ services:
- ./logs:/app/logs - ./logs:/app/logs
environment: environment:
- BGP_LOCAL_AS=65000 - BGP_LOCAL_AS=65000
- BGP_ROUTER_ID=192.168.1.100 - BGP_ROUTER_ID=192.168.100.99
- BGP_NEIGHBOR_IP=192.168.1.1 - BGP_NEIGHBOR_IP=192.168.0.254
- BGP_NEIGHBOR_AS=65001 - BGP_NEIGHBOR_AS=65001
- BGP_HOLD_TIME=90
- BGP_KEEPALIVE=30
- BGP_LOG_LEVEL=info
networks: networks:
- bgp-network - bgp-network
cap_add: cap_add:
- NET_ADMIN # Для работы с сетевыми интерфейсами - NET_ADMIN # Для работы с сетевыми интерфейсами
privileged: true # Для работы с FRR демонами
networks: networks:
bgp-network: bgp-network:
driver: bridge driver: bridge
ipam: ipam:
config: config:
- subnet: 192.168.1.0/24 - subnet: 192.168.100.0/24
-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 info
service integrated-vtysh-config
# Настройки BGP
router bgp 65000
bgp router-id 192.168.100.99
bgp log-neighbor-changes
neighbor 192.168.0.254 remote-as 65001
neighbor 192.168.0.254 description RouterOS Client
neighbor 192.168.0.254 timers 30 90
neighbor 192.168.0.254 capability graceful-restart
neighbor 192.168.0.254 soft-reconfiguration inbound
!
address-family ipv4 unicast
neighbor 192.168.0.254 activate
neighbor 192.168.0.254 route-map OUTBOUND out
neighbor 192.168.0.254 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.100.99/24
!
# Статические маршруты (будут добавлены динамически)
# ip route 192.168.1.0/24 Null0
+1 -4
View File
@@ -1,4 +1 @@
exabgp>=4.2.0 watchdog>=2.1.0
ipaddress
pathlib
typing
+66 -56
View File
@@ -1,85 +1,95 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Скрипт для генерации конфигурации ExaBGP из переменных окружения Скрипт для генерации конфигурации FRR из переменных окружения
""" """
import os import os
import sys 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) return os.environ.get(name, default)
def generate_exabgp_config(): def generate_frr_config():
"""Генерация конфигурации ExaBGP""" """Генерация конфигурации FRR"""
# Получение переменных окружения # Получение настроек из переменных окружения
local_as = get_env_var('BGP_LOCAL_AS', '65000') local_as = get_env_var('BGP_LOCAL_AS', '65000')
router_id = get_env_var('BGP_ROUTER_ID', '192.168.1.100') router_id = get_env_var('BGP_ROUTER_ID', '192.168.100.99')
neighbor_ip = get_env_var('BGP_NEIGHBOR_IP', '192.168.1.1') neighbor_ip = get_env_var('BGP_NEIGHBOR_IP', '192.168.0.254')
neighbor_as = get_env_var('BGP_NEIGHBOR_AS', '65001') neighbor_as = get_env_var('BGP_NEIGHBOR_AS', '65001')
hold_time = get_env_var('BGP_HOLD_TIME', '90') hold_time = get_env_var('BGP_HOLD_TIME', '90')
keepalive = get_env_var('BGP_KEEPALIVE', '30') 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')
# Генерация конфигурации # Конфигурация FRR
config = f"""# Автоматически сгенерированная конфигурация ExaBGP config = f"""# FRR Configuration File
process load-prefixes {{ # Generated automatically from environment variables
run /app/scripts/load_prefixes.py;
encoder json; # Глобальные настройки
}} frr version 8.5.2
frr defaults traditional
hostname bgp-server
log syslog {log_level}
service integrated-vtysh-config
# Настройки BGP # Настройки BGP
neighbor {neighbor_ip} {{ router bgp {local_as}
router-id {router_id}; bgp router-id {router_id}
local-address {router_id}; bgp log-neighbor-changes
local-as {local_as}; neighbor {neighbor_ip} remote-as {neighbor_as}
peer-as {neighbor_as}; neighbor {neighbor_ip} description RouterOS Client
neighbor {neighbor_ip} timers {keepalive} {hold_time}
# Только исходящие анонсы (не принимаем префиксы) neighbor {neighbor_ip} capability graceful-restart
capability {{ neighbor {neighbor_ip} soft-reconfiguration inbound
graceful-restart; !
}} address-family ipv4 unicast
neighbor {neighbor_ip} activate
# Настройки сессии neighbor {neighbor_ip} route-map OUTBOUND out
hold-time {hold_time}; neighbor {neighbor_ip} route-map INBOUND in
""" exit-address-family
!
# Добавление MD5 пароля если указан # Route maps для фильтрации
if md5_password: route-map OUTBOUND permit 10
config += f" md5-password \"{md5_password}\";\n" description Allow all outbound routes
!
config += f""" route-map INBOUND deny 10
# Логирование description Deny all inbound routes (receive-only mode)
api {{ !
processes [load-prefixes];
neighbor-changes; # Настройки интерфейса
receive {{ interface eth0
parsed; ip address {router_id}/24
update; !
}}
send {{ # Статические маршруты (будут добавлены динамически)
parsed; # ip route 192.168.1.0/24 Null0
update;
}}
}}
}}
""" """
return config return config
def main(): def main():
"""Основная функция""" """Основная функция"""
if len(sys.argv) > 1 and sys.argv[1] == '--print': try:
# Вывод конфигурации в stdout # Генерация конфигурации
print(generate_exabgp_config()) config = generate_frr_config()
else:
# Запись конфигурации в файл # Запись в файл
config = generate_exabgp_config() config_path = Path('/etc/frr/frr.conf')
with open('/app/exabgp.conf', 'w') as f: config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, 'w') as f:
f.write(config) 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__": if __name__ == "__main__":
main() main()
+108 -53
View File
@@ -1,12 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Скрипт для загрузки префиксов из текстовых файлов в ExaBGP Скрипт для загрузки префиксов из текстовых файлов в FRR
""" """
import sys import sys
import os import os
import time import time
import json import subprocess
import ipaddress import ipaddress
from pathlib import Path from pathlib import Path
from typing import List, Set from typing import List, Set
@@ -21,7 +21,7 @@ def log_message(message: str):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S") timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {message}" log_entry = f"[{timestamp}] {message}"
# Вывод в stdout для ExaBGP # Вывод в stdout
print(log_entry, flush=True) print(log_entry, flush=True)
# Запись в файл (с обработкой ошибок) # Запись в файл (с обработкой ошибок)
@@ -84,44 +84,84 @@ def load_all_prefixes() -> Set[str]:
return all_prefixes 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]): def announce_prefixes(prefixes: Set[str]):
"""Анонсирование префиксов через ExaBGP API""" """Анонсирование префиксов через FRR"""
# Получение настроек из переменных окружения log_message(f"Announcing {len(prefixes)} prefixes...")
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')
for prefix in sorted(prefixes): for prefix in sorted(prefixes):
# Формат команды для ExaBGP (упрощенный) # Добавление статического маршрута в FRR
command = { command = f"ip route {prefix} Null0"
"command": "announce route", if run_vtysh_command(command):
"neighbor": neighbor_ip, log_message(f"Announced prefix: {prefix}")
"attribute": { else:
"origin": "igp", log_error(f"Failed to announce prefix: {prefix}")
"as-path": [local_as],
"next-hop": router_id
},
"nlri": prefix
}
# Отправка команды в ExaBGP
print(json.dumps(command), flush=True)
log_message(f"Announced prefix: {prefix}")
def withdraw_prefixes(prefixes: Set[str]): def withdraw_prefixes(prefixes: Set[str]):
"""Отзыв префиксов через ExaBGP API""" """Отзыв префиксов через FRR"""
# Получение настроек из переменных окружения log_message(f"Withdrawing {len(prefixes)} prefixes...")
neighbor_ip = os.environ.get('BGP_NEIGHBOR_IP', '192.168.1.1')
for prefix in sorted(prefixes): for prefix in sorted(prefixes):
command = { # Удаление статического маршрута из FRR
"command": "withdraw route", command = f"no ip route {prefix} Null0"
"neighbor": neighbor_ip, if run_vtysh_command(command):
"nlri": prefix 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) attempt += 1
log_message(f"Withdrew prefix: {prefix}") 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(): def main():
"""Основная функция""" """Основная функция"""
@@ -138,8 +178,21 @@ def main():
print(f"Found {len(prefixes)} prefixes: {list(prefixes)}") print(f"Found {len(prefixes)} prefixes: {list(prefixes)}")
return 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...") log_message("Starting prefix loader...")
# Ожидание запуска FRR
if not wait_for_frr():
log_error("Cannot proceed without FRR")
return
# Загрузка префиксов # Загрузка префиксов
prefixes = load_all_prefixes() prefixes = load_all_prefixes()
log_message(f"Total prefixes loaded: {len(prefixes)}") log_message(f"Total prefixes loaded: {len(prefixes)}")
@@ -152,29 +205,31 @@ def main():
announce_prefixes(prefixes) announce_prefixes(prefixes)
log_message("All prefixes announced successfully") log_message("All prefixes announced successfully")
# Ожидание команд от ExaBGP # Мониторинг изменений в файлах
log_message("Starting file monitoring...")
try: try:
while True: while True:
line = sys.stdin.readline() time.sleep(30) # Проверка каждые 30 секунд
if not line:
break
line = line.strip() # Перезагрузка префиксов
if not line: # Пропуск пустых строк new_prefixes = load_all_prefixes()
continue
# Определение изменений
# Обработка команд от ExaBGP added = new_prefixes - prefixes
try: removed = prefixes - new_prefixes
data = json.loads(line)
log_message(f"Received command: {data}") if added:
except json.JSONDecodeError: log_message(f"Adding {len(added)} new prefixes: {list(added)}")
# Не все сообщения от ExaBGP являются JSON announce_prefixes(added)
# Это может быть обычное текстовое сообщение
if line.startswith('[') and line.endswith(']'): if removed:
# Это может быть лог сообщение от ExaBGP log_message(f"Removing {len(removed)} prefixes: {list(removed)}")
log_message(f"Received log message: {line}") withdraw_prefixes(removed)
else:
log_message(f"Received non-JSON message: {line}") if added or removed:
prefixes = new_prefixes
log_message(f"Updated prefix count: {len(prefixes)}")
except KeyboardInterrupt: except KeyboardInterrupt:
log_message("Received interrupt signal") log_message("Received interrupt signal")
+174 -73
View File
@@ -1,93 +1,194 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Скрипт мониторинга BGP сервера Скрипт мониторинга FRR BGP сервера
""" """
import sys
import os
import time
import subprocess import subprocess
import json import json
import time from pathlib import Path
import sys from typing import Dict, Any
from datetime import datetime
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: try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True) with open(LOG_FILE, "a") as f:
return result.returncode == 0, result.stdout, result.stderr 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: except Exception as e:
return False, "", str(e) log_message(f"Error running vtysh command '{command}': {e}")
return ""
def check_container_status(): def get_bgp_summary() -> Dict[str, Any]:
"""Проверка статуса Docker контейнера""" """Получение сводки BGP"""
success, output, error = run_command("docker ps --filter name=bgp-server --format '{{.Status}}'") summary = run_vtysh_command("show ip bgp summary")
if success and output.strip():
return True, output.strip() if not summary:
return False, "Container not running" 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(): def get_bgp_routes() -> Dict[str, Any]:
"""Проверка BGP сессии""" """Получение BGP маршрутов"""
success, output, error = run_command("docker exec bgp-server exabgpcli show neighbor") routes = run_vtysh_command("show ip bgp")
if success:
return True, output if not routes:
return False, "Cannot check BGP session" 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: try:
with open("/app/logs/prefixes.log", "r") as f: # Проверка процессов FRR
lines = f.readlines() zebra_running = subprocess.run(['pgrep', 'zebra'], capture_output=True).returncode == 0
return True, f"Found {len(lines)} log entries" bgpd_running = subprocess.run(['pgrep', 'bgpd'], capture_output=True).returncode == 0
except FileNotFoundError:
return False, "Prefix log not found" # Проверка использования памяти
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(): def save_status(status: Dict[str, Any]):
"""Проверка сетевого подключения""" """Сохранение статуса в файл"""
success, output, error = run_command("docker exec bgp-server ping -c 1 192.168.1.1") try:
return success, "Network connectivity OK" if success else "Network connectivity failed" 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(): def main():
"""Основная функция мониторинга""" """Основная функция"""
print("=== BGP Server Monitoring ===") log_message("Starting FRR monitor...")
print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
# Проверка контейнера # Создание директории для логов
print("1. Container Status:") try:
status, details = check_container_status() os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
print(f" Status: {'✓ Running' if status else '✗ Stopped'}") os.makedirs(os.path.dirname(STATUS_FILE), exist_ok=True)
print(f" Details: {details}") except (PermissionError, OSError):
print() pass
# Проверка сети while True:
print("2. Network Connectivity:") try:
net_ok, net_details = check_network_connectivity() # Сбор статуса
print(f" Status: {'✓ OK' if net_ok else '✗ Failed'}") status = {
print(f" Details: {net_details}") "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
print() "frr": get_frr_status(),
"bgp_summary": get_bgp_summary(),
# Проверка BGP сессии "bgp_routes": get_bgp_routes(),
print("3. BGP Session:") "system": get_system_status()
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]}...") save_status(status)
else:
print(f" Details: {bgp_details}") # Логирование важной информации
print() bgp_summary = status["bgp_summary"]
if "neighbors" in bgp_summary:
# Проверка префиксов for neighbor in bgp_summary["neighbors"]:
print("4. Prefixes:") log_message(f"BGP neighbor {neighbor['ip']} (AS {neighbor['remote_as']}): {neighbor['state']}")
prefix_ok, prefix_details = check_prefixes()
print(f" Status: {'✓ Loaded' if prefix_ok else '✗ Not loaded'}") bgp_routes = status["bgp_routes"]
print(f" Details: {prefix_details}") if "route_count" in bgp_routes:
print() log_message(f"BGP routes: {bgp_routes['route_count']}")
# Общий статус system = status["system"]
overall_status = status and net_ok and bgp_ok and prefix_ok if "zebra_running" in system and "bgpd_running" in system:
print("=== Overall Status ===") if not system["zebra_running"] or not system["bgpd_running"]:
print(f"Status: {'✓ HEALTHY' if overall_status else '✗ UNHEALTHY'}") log_message("WARNING: FRR daemons not running properly")
return 0 if overall_status else 1 # Ожидание перед следующей проверкой
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__": if __name__ == "__main__":
sys.exit(main()) main()
+177 -75
View File
@@ -1,103 +1,205 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Скрипт для перезагрузки префиксов без перезапуска BGP сервера Скрипт для перезагрузки префиксов в FRR
""" """
import subprocess
import sys import sys
import os
import time import time
import subprocess
import ipaddress
from pathlib import Path 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: try:
result = subprocess.run(cmd, shell=True, capture_output=True, text=True) with open(LOG_FILE, "a") as f:
return result.returncode == 0, result.stdout, result.stderr f.write(log_entry + "\n")
except Exception as e: except (PermissionError, OSError):
return False, "", str(e) pass
def reload_prefixes(): def validate_prefix(prefix: str) -> bool:
"""Перезагрузка префиксов""" """Валидация IP префикса"""
print("Reloading prefixes...") try:
ipaddress.ip_network(prefix, strict=False)
# Остановка процесса загрузки префиксов
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")
return True return True
else: except ValueError:
print(f"Error starting prefix loader: {error}")
return False return False
def check_status(): def load_prefixes_from_file(file_path: Path) -> Set[str]:
"""Проверка статуса после перезагрузки""" """Загрузка префиксов из файла"""
print("Checking status...") prefixes = set()
time.sleep(5)
# Проверка процесса if not file_path.exists():
success, output, error = run_command("docker exec bgp-server pgrep -f load_prefixes.py") log_message(f"File not found: {file_path}")
if success: return prefixes
print("✓ Prefix loader process is running")
else: try:
print("✗ Prefix loader process is not running") 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 return False
def announce_prefixes(prefixes: Set[str]):
"""Анонсирование префиксов через FRR"""
log_message(f"Announcing {len(prefixes)} prefixes...")
# Проверка логов for prefix in sorted(prefixes):
success, output, error = run_command("docker exec bgp-server tail -n 5 /app/logs/prefixes.log") command = f"ip route {prefix} Null0"
if success: if run_vtysh_command(command):
print("Recent log entries:") log_message(f"Announced prefix: {prefix}")
print(output) else:
else: log_message(f"Failed to announce prefix: {prefix}")
print("No recent log entries found")
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(): def main():
"""Основная функция""" """Основная функция"""
print("=== BGP Prefix Reloader ===") log_message("Starting prefix reload...")
# Проверка что контейнер запущен # Проверка статуса FRR
success, output, error = run_command("docker ps --filter name=bgp-server --format '{{.Status}}'") if not check_frr_status():
if not success or not output.strip(): log_message("ERROR: FRR is not running")
print("Error: BGP server container is not running")
print("Please start the container first: docker-compose up -d")
return 1 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(): current_routes = get_current_routes()
print("Prefix reload completed successfully") log_message(f"Found {len(current_routes)} current routes in FRR")
# Проверка статуса # Определение изменений
if check_status(): to_add = new_prefixes - current_routes
print("✓ All checks passed") to_remove = current_routes - new_prefixes
return 0
else: log_message(f"Changes: {len(to_add)} to add, {len(to_remove)} to remove")
print("✗ Some checks failed")
return 1 # Применение изменений
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: else:
print("✗ Prefix reload failed") log_message("WARNING: Route count mismatch after reload")
return 1 return 1
if __name__ == "__main__": if __name__ == "__main__":
+89 -62
View File
@@ -1,96 +1,123 @@
# PowerShell скрипт для запуска BGP сервера # Скрипт запуска BGP Server (FRR)
param( param(
[string]$ContainerName = "bgp-server",
[string]$DataPath = "./data",
[string]$LogsPath = "./logs",
[switch]$Build, [switch]$Build,
[switch]$Logs, [switch]$Force
[switch]$Monitor
) )
Write-Host "=== BGP Server Management ===" -ForegroundColor Green Write-Host "=== BGP Server (FRR) Startup Script ===" -ForegroundColor Green
# Проверка Docker # Проверка существования контейнера
Write-Host "Checking Docker..." -ForegroundColor Yellow $containerExists = docker ps -a --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
try {
docker --version | Out-Null if ($containerExists) {
Write-Host "✓ Docker is available" -ForegroundColor Green Write-Host "Found existing container: $ContainerName" -ForegroundColor Yellow
} catch {
Write-Host "✗ Docker is not available. Please install Docker Desktop." -ForegroundColor Red if (-not $Force) {
exit 1 $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 if (-not (Test-Path $DataPath)) {
try { Write-Host "Creating data directory: $DataPath" -ForegroundColor Yellow
docker-compose --version | Out-Null New-Item -ItemType Directory -Path $DataPath -Force | 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 $LogsPath)) {
Write-Host "Creating directories..." -ForegroundColor Yellow Write-Host "Creating logs directory: $LogsPath" -ForegroundColor Yellow
if (!(Test-Path "logs")) { New-Item -ItemType Directory -Path $LogsPath -Force | Out-Null
New-Item -ItemType Directory -Path "logs" | Out-Null
Write-Host "✓ Created logs directory" -ForegroundColor Green
} }
if (!(Test-Path "data")) { # Создание файла с префиксами если не существует
New-Item -ItemType Directory -Path "data" | Out-Null $prefixesFile = Join-Path $DataPath "prefixes.txt"
Write-Host "✓ Created data directory" -ForegroundColor Green 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.100.0/24
10.0.0.0/8
172.16.0.0/12
"@ | Out-File -FilePath $prefixesFile -Encoding UTF8
} }
# Сборка образа если требуется # Сборка образа если требуется
if ($Build) { if ($Build) {
Write-Host "Building Docker image..." -ForegroundColor Yellow Write-Host "Building Docker image..." -ForegroundColor Yellow
docker-compose build docker build -t bgp-server-frr .
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
Write-Host "✗ Build failed" -ForegroundColor Red Write-Host "Failed to build image. Exiting." -ForegroundColor Red
exit 1 exit 1
} }
Write-Host "✓ Build completed" -ForegroundColor Green
} }
# Остановка существующего контейнера # Запуск контейнера
Write-Host "Stopping existing container..." -ForegroundColor Yellow Write-Host "Starting BGP Server container..." -ForegroundColor Yellow
docker-compose down 2>$null $currentPath = Get-Location
Write-Host "✓ Existing container stopped" -ForegroundColor Green $dataVolume = "${currentPath}\${DataPath}:/app/data:ro"
$logsVolume = "${currentPath}\${LogsPath}:/app/logs"
# Запуск сервера docker run -d `
Write-Host "Starting BGP server..." -ForegroundColor Yellow --name $ContainerName `
docker-compose up -d --restart unless-stopped `
-p 179:179 `
-v $dataVolume `
-v $logsVolume `
--cap-add NET_ADMIN `
--privileged `
bgp-server-frr
if ($LASTEXITCODE -eq 0) { 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 Start-Sleep -Seconds 10
# Проверка статуса # Проверка статуса
Write-Host "Checking server status..." -ForegroundColor Yellow $status = docker ps --filter "name=$ContainerName" --format "table {{.Status}}"
$status = docker-compose ps Write-Host "Container status: $status" -ForegroundColor Cyan
Write-Host $status
if ($Logs) { # Проверка FRR статуса
Write-Host "Showing logs..." -ForegroundColor Yellow Write-Host "Checking FRR status..." -ForegroundColor Cyan
docker-compose logs -f bgp-server 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 { } else {
Write-Host "Failed to start BGP server" -ForegroundColor Red Write-Host "Failed to start container. Check the error above." -ForegroundColor Red
Write-Host "Check logs with: docker-compose logs bgp-server" -ForegroundColor Yellow
exit 1 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 #!/bin/bash
# Скрипт запуска BGP сервера # Скрипт запуска BGP сервера на FRR
set -e set -e
echo "Starting BGP Server..." echo "Starting BGP Server (FRR)..."
# Создание директорий если не существуют # Создание директорий если не существуют
mkdir -p /app/logs mkdir -p /app/logs
mkdir -p /app/run mkdir -p /app/run
mkdir -p /run/exabgp
mkdir -p /app/data mkdir -p /app/data
mkdir -p /var/run/frr
mkdir -p /etc/frr
# Установка правильных прав доступа # Установка правильных прав доступа
chmod 755 /app/logs chmod 755 /app/logs
chmod 755 /app/run chmod 755 /app/run
chmod 755 /run/exabgp
chmod 755 /app/data chmod 755 /app/data
chmod 755 /var/run/frr
# Удаление старых named pipes если они существуют chmod 755 /etc/frr
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
# Проверка наличия файлов с префиксами # Проверка наличия файлов с префиксами
if [ ! -f "/app/data/prefixes.txt" ]; then if [ ! -f "/app/data/prefixes.txt" ]; then
@@ -62,9 +30,9 @@ fi
# Создание лог-файлов с правильными правами # Создание лог-файлов с правильными правами
echo "Creating log files with proper permissions..." echo "Creating log files with proper permissions..."
touch /app/logs/prefixes.log 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/prefixes.log
chmod 666 /app/logs/exabgp.log chmod 666 /app/logs/frr.log
echo "Prefixes file content:" echo "Prefixes file content:"
cat /app/data/prefixes.txt cat /app/data/prefixes.txt
@@ -77,7 +45,7 @@ ls -la /app/scripts/
echo "---" echo "---"
# Генерация конфигурации из переменных окружения # Генерация конфигурации из переменных окружения
echo "Generating ExaBGP configuration from environment variables..." echo "Generating FRR configuration from environment variables..."
echo "Environment variables:" echo "Environment variables:"
env | grep BGP_ || echo "No BGP_ variables found" env | grep BGP_ || echo "No BGP_ variables found"
echo "---" echo "---"
@@ -85,11 +53,20 @@ echo "---"
python3 /app/scripts/generate_config.py python3 /app/scripts/generate_config.py
# Проверка конфигурации # Проверка конфигурации
echo "Validating ExaBGP configuration..." echo "Validating FRR configuration..."
echo "Configuration file content:" echo "Configuration file content:"
cat /app/exabgp.conf cat /etc/frr/frr.conf
echo "---" 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..." echo "Testing prefix loader script..."
@@ -105,135 +82,108 @@ else
echo "Warning: Cannot reach $NEIGHBOR_IP. BGP session may not establish." echo "Warning: Cannot reach $NEIGHBOR_IP. BGP session may not establish."
fi fi
# Запуск ExaBGP в фоновом режиме с логированием # Запуск FRR демонов
echo "Starting ExaBGP..." echo "Starting FRR daemons..."
LOG_LEVEL=${BGP_LOG_LEVEL:-INFO}
# Дополнительная проверка конфигурационного файла # Запуск zebra (обязательный демон для FRR)
echo "Final config file check:" echo "Starting zebra daemon..."
ls -la /app/exabgp.conf zebra -d -f /etc/frr/frr.conf -A 127.0.0.1 -z /var/run/frr/zebra.api
echo "Config file first few lines:" sleep 2
head -10 /app/exabgp.conf
echo "---"
# Проверка что ExaBGP может прочитать файл # Запуск bgpd
echo "Testing ExaBGP config validation:" echo "Starting bgpd daemon..."
if exabgp --validate /app/exabgp.conf; then bgpd -d -f /etc/frr/frr.conf -A 127.0.0.1 -z /var/run/frr/zebra.api
echo "Configuration validation passed" sleep 2
else
echo "Configuration validation failed"
echo "Full config content:"
cat /app/exabgp.conf
exit 1
fi
echo "---"
# Проверка переменных окружения и путей # Проверка что демоны запустились
echo "Environment check:" echo "Checking if FRR daemons are running..."
echo "PWD: $PWD" ps aux | grep -E "(zebra|bgpd)" | grep -v grep || echo "No FRR daemons found in ps"
echo "PATH: $PATH"
echo "PYTHONPATH: $PYTHONPATH"
echo "BGP_ variables:"
env | grep BGP_ || echo "No BGP_ variables found"
echo "---"
# Запуск ExaBGP # Сохранение PID файлов
echo "Starting ExaBGP with config: /app/exabgp.conf" 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"
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
# Ожидание запуска # Ожидание запуска
sleep 5 sleep 5
# Проверка статуса # Проверка статуса через vtysh
if kill -0 $EXABGP_PID 2>/dev/null; then echo "Checking FRR status via vtysh..."
echo "ExaBGP started successfully with PID: $EXABGP_PID" if vtysh -c "show version" > /dev/null 2>&1; then
echo "Recent logs:" echo "FRR started successfully"
tail -10 /app/logs/exabgp.log echo "FRR version:"
vtysh -c "show version" 2>/dev/null || echo "Could not get version"
# Дополнительная проверка через несколько секунд echo "BGP neighbors:"
sleep 3 vtysh -c "show ip bgp neighbors" 2>/dev/null || echo "Could not get BGP neighbors"
if kill -0 $EXABGP_PID 2>/dev/null; then
echo "ExaBGP is still running after 3 seconds" echo "BGP summary:"
echo "Process details:" vtysh -c "show ip bgp summary" 2>/dev/null || echo "Could not get BGP summary"
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
else else
echo "Failed to start ExaBGP" echo "Failed to start FRR. Checking logs:"
echo "Full logs:" cat /app/logs/frr.log 2>/dev/null || echo "No FRR logs found"
cat /app/logs/exabgp.log
echo "---"
echo "Process status:"
ps aux | grep exabgp || echo "No exabgp process found"
exit 1 exit 1
fi 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 # Функция для graceful shutdown
cleanup() { cleanup() {
echo "Shutting down BGP server..." echo "Received shutdown signal. Cleaning up..."
if [ -f "/app/logs/exabgp.pid" ]; then
kill $(cat /app/logs/exabgp.pid) 2>/dev/null || true # Остановка скриптов
if [ -f "/app/logs/prefix_loader.pid" ]; then
kill $(cat /app/logs/prefix_loader.pid) 2>/dev/null || true
fi 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 exit 0
} }
# Обработка сигналов # Установка обработчиков сигналов
trap cleanup SIGTERM SIGINT trap cleanup SIGTERM SIGINT
# Ожидание завершения # Ожидание завершения
echo "Waiting for ExaBGP to run..." echo "BGP Server is running. Press Ctrl+C to stop."
echo "Process status:" while true; do
ps aux | grep exabgp || echo "No exabgp process found" sleep 10
echo "---"
# Проверка что демоны все еще работают
# Проверка процесса загрузки префиксов if ! pgrep zebra > /dev/null; then
echo "Checking prefix loader process:" echo "ERROR: zebra daemon stopped unexpectedly"
ps aux | grep load_prefixes || echo "No prefix loader process found" exit 1
echo "---" fi
wait $EXABGP_PID 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
)
# Проверка что контейнер запущен Write-Host "=== BGP Server (FRR) Stop Script ===" -ForegroundColor Green
$containerStatus = docker ps --filter name=bgp-server --format "{{.Status}}"
if (!$containerStatus) { # Проверка существования контейнера
Write-Host "BGP server is not running" -ForegroundColor Yellow $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 exit 0
} }
Write-Host "BGP server is running. Stopping..." -ForegroundColor Yellow # Проверка статуса контейнера
$containerRunning = docker ps --filter "name=$ContainerName" --format "table {{.Names}}" | Select-String $ContainerName
# Остановка контейнера if ($containerRunning) {
docker-compose down Write-Host "Container $ContainerName is running. Stopping..." -ForegroundColor Yellow
if ($LASTEXITCODE -eq 0) { if (-not $Force) {
Write-Host "✓ BGP server stopped successfully" -ForegroundColor Green $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 { } else {
Write-Host "✗ Failed to stop BGP server" -ForegroundColor Red Write-Host "Container $ContainerName is not running." -ForegroundColor Yellow
exit 1
} }
# Проверка что контейнер остановлен # Удаление контейнера если требуется
$containerStatus = docker ps --filter name=bgp-server --format "{{.Status}}" if ($Force) {
if (!$containerStatus) { Write-Host "Removing container..." -ForegroundColor Yellow
Write-Host "✓ Container is stopped" -ForegroundColor Green 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 { } else {
Write-Host "Container is still running" -ForegroundColor Red Write-Host "Container stopped but not removed." -ForegroundColor Cyan
exit 1 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