BIRD v2 route-server: автообновление BGP-префиксов по категориям через RIPEstat и Antifilter

В продакшене мы не ставим BIRD v2 «из коробки» — разворачиваем route-server, где bird.conf живёт в git, а локальные настройки и BGP-пиры хранятся отдельно. Фильтры и community обновляются одной командой git pull, не задевая номер AS, router id и список пиров.

bird2-bgp-prefix-updater — Python-агрегатор, который скачивает IPv4-префиксы из RIPEstat и двух источников Antifilter, маркирует их 12 активных BGP community (коды 100–112, один зарезервирован) и раздаёт клиентам через фильтры BIRD v2. BIRD v2 ветки 2.16.1 держит более 1000 BGP-сессий в одном потоке при расходе менее 250 МБ RAM на два полных routing view.

bird2 автообновление префиксов

Ключевой тезис: bird2 автообновление префиксов через bird2-bgp-prefix-updater даёт 12 активных BGP community (коды 100–112, один зарезервирован) для гибкого сплита трафика и переживает сбои источников до 7 дней за счёт резервного кэша.

Содержание

Зачем route-server с BGP community: сплит трафика по категориям

Route-server с community — один BIRD v2, который маркирует все нужные категории префиксов числовыми метками. MikroTik, Linux-роутеры, edge-маршрутизаторы получают маршруты с метками и сами решают, что с ними делать: направить через локальный канал, через WireGuard-туннель или отбросить.

Один из частых случаев — отделить российский трафик от заблокированных подсетей. Префикс может одновременно лежать в RU Combined (community 100) и в списке РКН (community 101). Без явных фильтров такой маршрут попадёт в обе сессии и поедет туда, куда не должен. В bird.conf мы пишем фильтры, которые сначала отбрасывают пересечения, потом разрешают нужную категорию.

Второй сценарий — обход блокировок отдельных сервисов. Скрипт держит community для Stripe (107), ByteDance (108), Akamai (109), Roblox (110), Pinterest (111) и Fastly (112). Если клиенту нужен прозрачный доступ к Stripe API из платёжного шлюза, а остальной трафик идёт по обычному маршруту — фильтр if (bgp_community ~ [(MY_AS, 107)]) then accept; уводит трафик в Stripe через нужный аплинк, не задевая ничего больше.

Третий сценарий — раздача гос-сетей и custom-листа отдельной BGP-сессии. Community 103 (Gov Networks) и 104 (Telegram, Cloudflare, Google и custom.lst) живут в разных списках Antifilter и обновлются независимо. Клиенту нужен только Telegram CDN — фильтр if (bgp_community ~ [(MY_AS, 104)]) then accept; отдаст ровно его, без шума соседних категорий.

Альтернатива — держать N статических списков на каждом клиенте и обновлять их cron-скриптами. Это работает, пока у вас один-два роутера. Когда клиентов больше пяти, обновлять списки централизованно через BGP дешевле и надёжнее: BIRD v2 переотдаёт маршруты по событию (route refresh), и через несколько секунд после очередного запуска агрегатора все клиенты видят новый список без перезагрузок и без ручного захода на каждый MikroTik.

Зачем route-server с BGP community: сплит трафика по категориям

Как установить BIRD v2 и развернуть bird2-bgp-prefix-updater?

Минимальные требования у нас фиксированы: Linux (Debian/Ubuntu или RHEL/Alma/CentOS), BIRD v2 или v3, Python 3 в системном репозитории. На Debian 11 (Bullseye) BIRD 2.0.7 уже доступен в стабильной ветке, обновляться до текущей 2.16.1 имеет смысл, если нужны новые фильтры или фиксы BGP Flowspec, ради которых BIRD 2 и был выпущен в 2017 году вместе с поддержкой VPN и EVPN. Bird2-bgp-prefix-updater работает и с BIRD v3.

Команда установки на Debian/Ubuntu — apt install -y bird2 python3; на RHEL-семействе — сначала dnf install -y epel-release, затем dnf install -y bird python3. После установки BIRD ставится с шаблонной конфигурацией, которую мы заменяем на свою из git: git clone https://github.com/IT-for-Prof/bird2-bgp-prefix-updater /opt/bird2-bgp-prefix-updater.

Дальше мы копируем три набора файлов. Первый — общие конфиги BIRD: install -m644 conf/bird.conf /etc/bird/bird.conf и install -m644 conf/custom.lst /etc/bird/custom.lst. Второй — systemd-юниты: install -m644 systemd/bird2-bgp-prefix-updater.service /etc/systemd/system/ и аналогично для .timer. Третий — рабочие директории: mkdir -p /var/lib/bird /var/lib/bird/prefix-cache и touch /etc/bird/prefixes.bird.

На Debian/Ubuntu нужно отдельно выставить владельца сгенерированному файлу маршрутов: chown bird:bird /etc/bird/prefixes.bird — иначе BIRD откажется его читать после daemon-reload. На RHEL пользователь обычно называется bird, но проверять стоит через id bird до chown.

Перед первым запуском нужно создать /etc/bird/local-settings.conf со своим router id и MY_AS — иначе скрипт не определит номер AS для community. Затем запускаем агрегатор вручную: python3 /opt/bird2-bgp-prefix-updater/src/prefix_updater.py. Он должен прочитать MY_AS из local-settings.conf, скачать списки и записать /etc/bird/prefixes.bird. После успешного прогона — systemctl daemon-reload, systemctl enable --now bird, systemctl enable --now bird2-bgp-prefix-updater.timer. Таймер дальше будет вызывать обновление по расписанию, и bird2 автообновление префиксов начнёт работать в фоне без ручного вмешательства.

				
					# Debian/Ubuntu
apt install -y bird2 python3

# RHEL/Alma/CentOS
dnf install -y epel-release
dnf install -y bird python3

# Клонируем проект
git clone https://github.com/IT-for-Prof/bird2-bgp-prefix-updater /opt/bird2-bgp-prefix-updater

# Копируем конфиги BIRD и systemd-юниты
install -m644 conf/bird.conf /etc/bird/bird.conf
install -m644 conf/custom.lst /etc/bird/custom.lst
install -m644 systemd/bird2-bgp-prefix-updater.service /etc/systemd/system/
install -m644 systemd/bird2-bgp-prefix-updater.timer /etc/systemd/system/

# Рабочие директории и права
mkdir -p /var/lib/bird /var/lib/bird/prefix-cache
touch /etc/bird/prefixes.bird
chown bird:bird /etc/bird/prefixes.bird

# Первый запуск и активация таймера
python3 /opt/bird2-bgp-prefix-updater/src/prefix_updater.py
systemctl daemon-reload
systemctl enable --now bird
systemctl enable --now bird2-bgp-prefix-updater.timer
				
			
Установка BIRD v2 и разворачивание bird2-bgp-prefix-updater

Файловая архитектура: bird.conf из git, local-settings.conf под ваш сервер

Главный архитектурный приём проекта — разделить общую конфигурацию и локальные настройки. В /etc/bird/bird.conf лежат фильтры, описание community и шаблоны t_client — этот файл приходит из git и обновляется командой git pull. В /etc/bird/local-settings.conf хранится router id, MY_AS и параметры логирования — этот файл создаётся один раз и в репозиторий не попадает. Агрегатор читает MY_AS из local-settings.conf: один и тот же bird.conf деплоится на любое количество route-серверов с разными номерами AS.

Третий слой — /etc/bird/peers.d/*.conf, по одному файлу на BGP-сессию. Каждый пир выглядит как короткий блок protocol bgp my_peer from t_client { neighbor 192.0.2.2 as 65002; ipv4 { export filter export_only_ru; }; } и наследует фильтры из шаблона t_client в общей конфигурации. Когда мы добавляем нового клиента, мы кладём ему отдельный файл в peers.d, не трогая bird.conf.

Мы держим bird.conf в git как submodule: при изменении фильтров делаем cd /opt/bird2-bgp-prefix-updater && git pull, потом install -m644 conf/bird.conf /etc/bird/bird.conf, перезагружаем BIRD через birdc configure.

Файл prefixes.bird — единственный, который пишет агрегатор. Он подключается из bird.conf через include "/etc/bird/prefixes.bird"; и содержит десятки тысяч строк route-объявлений с community. Файл custom.lst — статический список ваших дополнительных IP, который агрегатор склеивает с остальными источниками под community 104: туда удобно класть локальные исключения и сети, которых нет в Antifilter.

Такая архитектура снимает классическую боль конфигурационных репозиториев: вы не зальёте чужой router id и не сотрёте чужих пиров при обновлении. Изменения фильтров через git pull прилетают всем route-серверам в одну команду. Если нужно добавить community 113 для нового сервиса — мерджим в репозиторий и git pull на каждом узле, больше ничего.

				
					# /etc/bird/peers.d/my_peer.conf
protocol bgp my_peer from t_client {
    neighbor 192.0.2.2 as 65002;
    ipv4 {
        export filter export_only_ru;
    };
}

# Обновление bird.conf из git без рестарта BGP-сессий
cd /opt/bird2-bgp-prefix-updater && git pull
install -m644 conf/bird.conf /etc/bird/bird.conf
birdc configure
				
			

BGP community в скрипте: таблица кодов от 100 до 112

В bird2 автообновление префиксов все community имеют формат LOCAL_AS:ID, где LOCAL_AS — это ваш MY_AS из local-settings.conf, а ID — числовая метка категории. Скрипт пишет одну или несколько меток на каждый префикс, в зависимости от того, в каких источниках он встретился.

Полный список из 13 категорий выглядит так:

IDНазваниеЧто внутри
100RU CombinedВсе IPv4-сети РФ из RIPEstat
101Blocked SmartСуммаризация списков РКН (/32 — /23) из ipsmart.lst
102RKN SubnetsПодсети из официальных списков Antifilter
103Gov NetworksСети государственных структур и ведомств
104Custom UserTelegram, Cloudflare, Google и custom.lst
105ReservedЗарезервировано на будущее
106Blocked IPСписок ip.lst Antifilter
107Stripe IPСети Stripe (API, Webhooks)
108ByteDanceAS396986 (ByteDance, TikTok)
109AkamaiAS20940 (Akamai)
110RobloxAS22697 (Roblox)
111PinterestAS53620 (Pinterest)
112FastlyAS54113 (Fastly CDN)

В RFC 6996 диапазон приватных AS — 64512–65534, и для community мы рекомендуем брать MY_AS именно отсюда, чтобы избежать конфликтов с публичными сообществами провайдеров. Если в качестве MY_AS вы используете 4-байтовый AS, формат community остаётся тем же — (MY_AS, ID), BIRD v2 корректно работает с обоими вариантами.

Ловушка, в которую периодически попадают новички — наложение 100 и 101..110 на одном префиксе. Российская сеть 5.45.0.0/16 может одновременно лежать в RIPEstat (100) и в списке РКН (101). Если фильтр клиента написан как «отдавать всё с community 100», заблокированный префикс уйдёт ему вместе с обычным трафиком. Поэтому в bird.conf мы держим парный фильтр export_only_ru, который сначала отбрасывает 101..112, а потом разрешает 100 — порядок важен.

Как prefix_updater.py скачивает и агрегирует префиксы

Скрипт prefix_updater.py работает как простой агрегатор: на каждый запуск он обходит список источников, парсит ответы, нормализует CIDR и пишет результат в два файла. /var/lib/bird/prefixes.txt — чистый список CIDR без community, удобен для отладки и сравнения версий. /etc/bird/prefixes.bird — рабочий файл, который читает BIRD: каждая строка содержит route-объявление с community-метками.

RIPEstat — основной источник для community 100. Скрипт обращается к официальному data-API RIPEstat (endpoints для BGP State, Routing Status и BGP Updates) и забирает все IPv4-префиксы для нужного региона — полное покрытие RU без зависимости от частных источников. Antifilter.network и Antifilter.download дают остальные категории: ipsmart.lst (101), Antifilter subnets (102), gov-сети (103), ip.lst (106), Stripe (107) и AS-листы для 108–112.

Чтобы не дёргать источники по сто раз в день при отладке, скрипт кэширует скачанные ответы в /var/lib/bird/prefix-cache на 6 часов (значение по умолчанию, переопределяется через переменную среды CACHE_TTL). Повторный запуск в течение 6 часов не порождает сетевого трафика — данные берутся из кэша. Принудительное обновление — флаг --force-refresh, который нужен только при критичных изменениях.

Отдельная подсистема — резервный кэш в /var/lib/bird/prefix-cache со сроком жизни 7 дней. Если все источники недоступны больше 6 часов, скрипт не обнуляет prefixes.bird — берёт последнюю успешную копию оттуда. Раз-два в год RIPEstat уходит на техобслуживание или Antifilter получает DDoS: в эти часы BGP-сессии клиентов продолжают работать без изменений.

Отладочный режим --check IP показывает, из какого источника пришёл конкретный адрес. Команда prefix_updater.py --check 194.67.72.31 прогоняет адрес по всем спискам и выводит название источника, URL и присваиваемый community ID. Когда клиент пишет «у меня блокируется 194.67.72.31, разберитесь» — за минуту видно, в каком списке лежит неправильный префикс. После этого либо подаём обращение в Antifilter, либо дописываем локальный override в custom.lst.

Как защитить конфигурацию BIRD v2 от частичных записей?

Когда BIRD читает prefixes.bird в момент его частичной перезаписи, он либо падает с syntax error, либо подхватывает наполовину обновлённый список. Поэтому в продакшене мы пишем prefixes.bird только атомарно: новый файл генерируется как prefixes.bird.new в той же файловой системе, после чего вызывается os.rename() или mv -f. POSIX гарантирует, что rename внутри одного раздела атомарен — BIRD никогда не увидит полусырое состояние.

Второй слой защиты — smoke test перед заменой. Перед тем как заменить prefixes.bird, скрипт пропускает его через bird -p -c /etc/bird/bird.conf: ключ -p включает parse-only режим, BIRD проверяет синтаксис и community, не трогая текущую сессию. Если проверка прошла — atomic rename и birdc configure; если нет — оставляем старый файл и пишем тревожный лог в journald.

Третий слой — резервный кэш до 7 дней. При сбое всех источников скрипт не пытается записать пустой prefixes.bird (это вырубило бы все маршруты), а выбирает последний успешный кэш-снепшот из /var/lib/bird/prefix-cache и регенерирует prefixes.bird из него. На клиентских сессиях это незаметно — BGP-таблица та же, что час назад.

Дополнительная страховка — логировать diff к предыдущему запуску и количество префиксов на community. Резкое падение — скажем, RU Combined упал с 32 000 до 30 за один цикл — повод не катить изменения. Мы добавляем sanity-check: если новый список меньше предыдущего более чем на 10%, обновление откладывается до ручной проверки и в Telegram прилетает алерт.

Последнее, о чём легко забыть — права на файлы. prefixes.bird должен принадлежать пользователю bird (или соответствующему на RHEL), иначе BIRD откажется его перечитать. Перед каждым atomic rename делаем chown bird:bird и chmod 644 на временный файл — после rename права уже корректные. Эта мелочь экономит час отладки в тот день, когда после первой установки BIRD молча игнорирует свежий prefixes.bird и нет очевидных ошибок в логах.

Как диагностировать bird2-bgp-prefix-updater через systemd и birdc?

Запуск агрегатора по расписанию — задача systemd-таймера bird2-bgp-prefix-updater.timer. После systemctl enable --now bird2-bgp-prefix-updater.timer юнит запускает service по расписанию (по умолчанию каждые 15–30 минут) — свежие списки Antifilter появляются с задержкой не больше получаса.

Логи обновления смотрим через journalctl: journalctl -u bird2-bgp-prefix-updater.service -f показывает live-вывод последнего запуска, а journalctl -u bird2-bgp-prefix-updater.service --since "1 hour ago" — историю за час. В логах виден тайминг по каждому источнику, число префиксов на community и финальный размер prefixes.bird. Счётчик числа строк удобно вынести в Prometheus через node_exporter textfile collector — так ловятся регрессы по RIPEstat-времени и просадки в отдельных категориях. После каждого успешного цикла bird2 автообновление префиксов отражается в этих счётчиках — сразу видно, сколько маршрутов добавилось по каждой категории и не упало ли их число. Для полной картины трафика на edge-узле метрики BIRD v2 удобно дополнить анализатором NetFlow или sFlow — он покажет, куда реально уходит каждая категория префиксов в разрезе IP-пар.

Состояние BGP-сессий проверяем через birdc — командный интерфейс BIRD. birdc show protocols выводит таблицу всех протоколов и статусов сессий: established, idle, active. Если пир упал, тут же видно причину. birdc "show route table t_bgp_prefixes all" показывает таблицу route-server со всеми community — проверить, как скрипт пометил конкретный префикс.

Если клиент сообщает «у меня блокируется адрес 194.67.72.31, разберитесь», маршрут проверяем командой prefix_updater.py --check 194.67.72.31. Скрипт прогонит адрес по всем источникам и покажет, в каком списке он лежит и под каким community уйдёт клиенту. После этого либо подаём обращение в источник, либо дополняем custom.lst локальным override и перезапускаем агрегатор.

Обновление проекта на свежую версию — стандартный cd /opt/bird2-bgp-prefix-updater && git pull, после чего переустанавливаем скрипт и юниты: install -m755 src/prefix_updater.py /usr/local/bin/prefix_updater.py и systemctl daemon-reload. Затем systemctl restart bird2-bgp-prefix-updater.service прогоняет цикл вручную и сразу видны изменения в логах. На обновление BIRD-конфига отдельная команда birdc configure — без рестарта BGP-сессий, что особенно ценно на route-сервере с десятком клиентов. Для полноценного контроля доступности BGP-сессий в продакшене стоит интегрировать BIRD v2 в систему мониторинга — например, как описано в кейсе про круглосуточный Zabbix-мониторинг.

				
					# Логи текущего запуска (live)
journalctl -u bird2-bgp-prefix-updater.service -f

# История за последний час
journalctl -u bird2-bgp-prefix-updater.service --since "1 hour ago"

# Статус всех BGP-сессий
birdc show protocols

# Таблица маршрутов route-server с community
birdc "show route table t_bgp_prefixes all"

# Проверка конкретного адреса по источникам
prefix_updater.py --check 194.67.72.31

# Обновление проекта до свежей версии
cd /opt/bird2-bgp-prefix-updater && git pull
install -m755 src/prefix_updater.py /usr/local/bin/prefix_updater.py
systemctl daemon-reload
systemctl restart bird2-bgp-prefix-updater.service
birdc configure
				
			

Итог

Часто задаваемые вопросы

Ответы на часто задаваемые вопросы по теме статьи.

Настройка bird2 автообновление префиксов состоит из четырёх шагов: установить BIRD v2 и Python 3, склонировать bird2-bgp-prefix-updater в /opt/, разложить bird.conf, local-settings.conf и peers.d/, активировать systemd-таймер. Скрипт сам прочитает MY_AS из local-settings.conf, скачает списки из RIPEstat и Antifilter и запишет /etc/bird/prefixes.bird с community 100–112. Дальше birdc configure перечитает таблицу без рестарта сессий.

В BIRD v2 community проверяется через bgp_community и оператор тильда. Чтобы отдать клиенту только российские сети без блокировок, пишем filter export_only_ru: сначала reject для bgp_community в диапазоне (MY_AS, 101..112), потом accept для COMM_RU_COMBINED, в конце reject. Порядок важен — сначала отбрасываем пересечения с заблокированными списками, потом разрешаем нужную категорию. RFC 6996 рекомендует MY_AS из приватного диапазона 64512–65534.

bird2-bgp-prefix-updater — Python-агрегатор, который раз в 15–30 минут скачивает IPv4-префиксы из RIPEstat (community 100, RU Combined), Antifilter.network и Antifilter.download (community 101–106) и AS-листы крупных сервисов: Stripe (107), ByteDance AS396986 (108), Akamai AS20940 (109), Roblox AS22697 (110), Pinterest AS53620 (111), Fastly AS54113 (112). Результат пишется в /etc/bird/prefixes.bird и подключается из bird.conf.

Расписание обновления задаёт systemd-таймер bird2-bgp-prefix-updater.timer. После каждого успешного запуска скрипт атомарно перезаписывает /etc/bird/prefixes.bird, после чего достаточно вызова birdc configure для перечитывания таблицы — текущие BGP-сессии остаются установленными. Резервный кэш до 7 дней защищает от пустых обновлений при сбое источников: если все API недоступны, скрипт берёт последнюю успешную копию вместо записи пустого файла.

Константин Тютюнник, основатель IT For Prof. 15 лет опыта в IT-аутсорсинге для B2B. Эксперт по DevOps, Linux-инфраструктуре и импортозамещению.

Если у вас уже есть BGP-инфраструктура и нужно настроить bird2 автообновление префиксов с нуля или починить разваливающийся route-server — мы развернём BIRD v2, bird2-bgp-prefix-updater и community-фильтры под ваши сценарии. Полное администрирование Linux-серверов с круглосуточным мониторингом снимает с вас и BGP, и резервное копирование, и реагирование на инциденты.