BGP-фейловер и мультихоминг с двух VPS-локаций
Анонсируйте один и тот же префикс с двух локаций через BGP для автоматического фейловера. Рассматриваются LOCAL_PREF, MED, AS-path prepending, BFD и graceful shutdown с полными конфигурациями BIRD2 и FRR.
В этом руководстве разбирается анонсирование одного и того же IP-префикса с двух отдельных VPS-локаций через BGP. Вы настроите приоритет основного/резервного узла с помощью LOCAL_PREF и MED, включите BFD для обнаружения сбоев менее чем за секунду и реализуете graceful shutdown для планового обслуживания. Все примеры приведены параллельно для BIRD2 и FRR.
Предварительные требования:
- Работающая BGP-сессия хотя бы на одном VPS (Настройка BGP в BIRD2 на Linux VPS или Настройка BGP в FRRouting на Linux VPS)
- Собственный ASN и хотя бы один префикс /24 (IPv4) или /48 (IPv6)
- Базовое понимание BGP communities (BGP Communities: стандартные, large и extended)
Что такое BGP-мультихоминг и зачем он на VPS?
BGP-мультихоминг означает анонсирование одного и того же IP-префикса с двух или более локаций через eBGP. Каждая локация поддерживает независимую BGP-сессию со своим аплинком. Если одна локация выходит из строя, другая продолжает анонсировать префикс и автоматически принимает весь трафик. Время конвергенции зависит от hold-таймеров (обычно 180-240 секунд при стандартных настройках) или BFD (менее секунды при правильной конфигурации).
На VPS мультихоминг даёт резервирование без привязки к одному дата-центру. Вы запускаете два VPS в разных локациях, оба анонсируют ваш префикс. Один работает как основной, другой как резервный. Атрибуты управления трафиком (LOCAL_PREF, MED, AS-path prepending) определяют, какой путь обрабатывает трафик в нормальных условиях.
Как спроектировать BGP-фейловер между двумя локациями?
Схема использует два Virtua VPS в разных европейских локациях, каждый с eBGP-сессией к локальному аплинк-маршрутизатору. Оба анонсируют одинаковые /24 и /48.
Internet
/ \
Upstream A Upstream B
(Frankfurt) (Amsterdam)
| |
eBGP session eBGP session
| |
+-----------+ +-----------+
| VPS-PRI | | VPS-BKP |
| AS 64500 | | AS 64500 |
| BIRD2/FRR | | BIRD2/FRR |
+-----------+ +-----------+
announces announces
198.51.100.0/24 198.51.100.0/24
2001:db8::/48 2001:db8::/48
Оба узла принадлежат вашему AS (AS 64500 в этих примерах). Замените ASN, префиксы и IP-адреса пиров на свои реальные значения.
Правила файрвола для обоих узлов:
BGP использует TCP-порт 179. BFD использует UDP-порты 3784 и 3785. Откройте их между вашим VPS и аплинк-пиром, прежде чем продолжать.
# nftables example - adjust PEER_IP to your upstream
nft add rule inet filter input ip saddr PEER_IP tcp dport 179 accept
nft add rule inet filter input ip saddr PEER_IP udp dport { 3784, 3785 } accept
Как управлять предпочтением BGP-маршрута?
Три атрибута позволяют влиять на выбор пути для трафика. Каждый работает на своём уровне.
| Атрибут | Направление | Область | Передаётся пирам? | Когда использовать |
|---|---|---|---|---|
| LOCAL_PREF | Исходящий (ваш выход) | Внутри вашего AS | Нет (только iBGP) | Управление тем, какой узел отправляет исходящий трафик |
| MED | Входящий (от аплинка) | Между вами и одним AS-аплинком | Да (прямому соседу) | Указать аплинку, какую точку входа предпочесть |
| AS-path prepending | Входящий (глобальный) | Все AS в пути | Да (распространяется) | Сделать путь длиннее для всего интернета |
LOCAL_PREF и MED — точные инструменты. AS-path prepending — грубый, но работает, когда ваши локации подключены к разным аплинкам.
Как настроить LOCAL_PREF для основного и резервного маршрутов?
LOCAL_PREF определяет, какой выходной путь предпочитает ваш AS для исходящего трафика. Побеждает большее значение. По умолчанию — 100. Установите 200 на основном узле и оставьте 100 на резервном. Это влияет только на трафик, покидающий вашу сеть.
Настройка LOCAL_PREF в BIRD2
На основном узле (VPS-PRI) создайте или измените фильтр импорта:
# /etc/bird/bird.conf - Primary node
filter upstream_import_primary {
bgp_local_pref = 200;
accept;
}
protocol bgp upstream_v4 {
local 192.0.2.2 as 64500;
neighbor 192.0.2.1 as 64496;
ipv4 {
import filter upstream_import_primary;
export where net = 198.51.100.0/24;
};
}
protocol bgp upstream_v6 {
local 2001:db8:1::2 as 64500;
neighbor 2001:db8:1::1 as 64496;
ipv6 {
import filter upstream_import_primary;
export where net = 2001:db8::/48;
};
}
На резервном узле (VPS-BKP) оставьте LOCAL_PREF по умолчанию:
# /etc/bird/bird.conf - Backup node
filter upstream_import_backup {
bgp_local_pref = 100;
accept;
}
protocol bgp upstream_v4 {
local 203.0.113.2 as 64500;
neighbor 203.0.113.1 as 64497;
ipv4 {
import filter upstream_import_backup;
export where net = 198.51.100.0/24;
};
}
Перезагрузите BIRD2 и проверьте маршруты:
birdc configure
birdc show route for 0.0.0.0/0 all
0.0.0.0/0 unicast [upstream_v4 12:00:00] * (100/?) [AS64496i]
via 192.0.2.1 on eth0
Type: BGP univ
BGP.origin: IGP
BGP.as_path: 64496
BGP.local_pref: 200
Значение BGP.local_pref: 200 на основном узле означает, что он будет предпочтён для исходящего трафика.
Настройка LOCAL_PREF в FRR
На основном узле:
vtysh -c "configure terminal
route-map UPSTREAM-IN permit 10
set local-preference 200
exit
router bgp 64500
neighbor 192.0.2.1 remote-as 64496
address-family ipv4 unicast
neighbor 192.0.2.1 route-map UPSTREAM-IN in
network 198.51.100.0/24
exit-address-family
neighbor 2001:db8:1::1 remote-as 64496
address-family ipv6 unicast
neighbor 2001:db8:1::1 route-map UPSTREAM-IN in
network 2001:db8::/48
exit-address-family
exit
exit"
На резервном узле задайте set local-preference 100 (или опустите route-map, так как 100 — значение по умолчанию).
Проверьте таблицу маршрутизации:
vtysh -c "show ip bgp"
Network Next Hop Metric LocPrf Weight Path
*> 0.0.0.0/0 192.0.2.1 200 0 64496 i
Как использовать MED для управления входящим трафиком?
MED (Multi-Exit Discriminator) говорит вашему аплинку, какую точку входа предпочесть. Побеждает меньшее значение. Установите MED 0 на основном и MED 100 на резервном узле. MED сравнивается только между маршрутами от одного и того же соседнего AS, поэтому лучше всего работает, когда обе локации пирятся с одним аплинк-провайдером.
Настройка MED в BIRD2
На основном узле задайте MED в фильтре экспорта:
filter upstream_export_primary {
if net = 198.51.100.0/24 || net = 2001:db8::/48 then {
bgp_med = 0;
accept;
}
reject;
}
protocol bgp upstream_v4 {
local 192.0.2.2 as 64500;
neighbor 192.0.2.1 as 64496;
ipv4 {
import filter upstream_import_primary;
export filter upstream_export_primary;
};
}
На резервном узле:
filter upstream_export_backup {
if net = 198.51.100.0/24 || net = 2001:db8::/48 then {
bgp_med = 100;
accept;
}
reject;
}
Настройка MED в FRR
На основном узле:
vtysh -c "configure terminal
route-map UPSTREAM-OUT permit 10
set metric 0
exit
router bgp 64500
address-family ipv4 unicast
neighbor 192.0.2.1 route-map UPSTREAM-OUT out
exit-address-family
exit
exit"
На резервном узле используйте set metric 100.
Проверьте экспортируемые маршруты:
vtysh -c "show ip bgp neighbors 192.0.2.1 advertised-routes"
Network Next Hop Metric LocPrf Weight Path
*> 198.51.100.0/24 0.0.0.0 0 32768 i
Колонка Metric показывает 0 на основном узле. Резервный покажет 100.
Когда использовать AS-path prepending вместо MED?
Используйте AS-path prepending, когда ваши две локации подключены к разным аплинк-провайдерам. MED сравнивается только между маршрутами от одного AS, поэтому не работает, если аплинки — разные AS. Prepending удлиняет резервный путь, направляя глобальные решения маршрутизации к основному узлу.
Добавьте свой ASN от 1 до 3 раз на резервном узле. Больше 3 prepend'ов редко меняет решения маршрутизации и только добавляет шум.
BIRD2 (фильтр экспорта резервного узла):
filter upstream_export_backup_prepend {
if net = 198.51.100.0/24 || net = 2001:db8::/48 then {
bgp_path.prepend(64500);
bgp_path.prepend(64500);
accept;
}
reject;
}
FRR (резервный узел):
vtysh -c "configure terminal
route-map UPSTREAM-OUT permit 10
set as-path prepend 64500 64500
exit
exit"
После применения проверьте AS-путь через looking glass или с удалённой машины:
# From an external machine
traceroute -A 198.51.100.1
Резервный путь теперь показывает 64500 64500 64500 (ваш ASN появляется трижды: один раз реальный, дважды добавленный), а основной показывает 64500 один раз.
Как включить BFD для быстрого обнаружения сбоев?
Без BFD протокол BGP полагается на hold-таймеры для обнаружения сбоя пира. Hold-таймер по умолчанию составляет 240 секунд в BIRD2 и 180 секунд в FRR. С BFD обнаружение падает до менее чем секунды на каналах с низкой задержкой.
| Параметр | По умолчанию | Рекомендуется для VPS |
|---|---|---|
| Интервал передачи | 300 мс | 300 мс |
| Интервал приёма | 300 мс | 300 мс |
| Множитель обнаружения | 3 | 3 |
| Эффективное время обнаружения | 900 мс | 900 мс |
Для VPS-сред на одном бэкбоне провайдера интервалы в 300 мс с множителем 3 дают надёжное обнаружение менее чем за секунду без ложных срабатываний. Не ставьте интервалы ниже 100 мс на VPS-инстансах. Джиттер виртуализации может вызвать флаппинг.
Настройка BFD в BIRD2
Добавьте протокол BFD и включите его на BGP-сессии:
protocol bfd {
interface "*" {
min rx interval 300 ms;
min tx interval 300 ms;
multiplier 3;
};
}
protocol bgp upstream_v4 {
local 192.0.2.2 as 64500;
neighbor 192.0.2.1 as 64496;
bfd graceful;
ipv4 {
import filter upstream_import_primary;
export filter upstream_export_primary;
};
}
Опция bfd graceful означает, что при обнаружении сбоя через BFD BIRD2 инициирует graceful restart (сохраняя устаревшие маршруты) вместо жёсткого сброса сессии. Если пир не поддерживает BFD, сессия устанавливается в обычном режиме.
После перезагрузки проверьте состояние BFD:
birdc show bfd sessions
BFD sessions:
IP address Interface State Since Interval Timeout
192.0.2.1 eth0 Up 12:00:00 300 ms 900 ms
Настройка BFD в FRR
vtysh -c "configure terminal
bfd
profile vps-detect
receive-interval 300
transmit-interval 300
detect-multiplier 3
exit
exit
router bgp 64500
neighbor 192.0.2.1 bfd profile vps-detect
neighbor 2001:db8:1::1 bfd profile vps-detect
exit
exit"
Проверьте состояние BFD-пира:
vtysh -c "show bfd peers"
BFD Peers:
peer 192.0.2.1 vrf default
ID: 1
Remote ID: 2
Status: up
Uptime: 5 minute(s)
Diagnostics: ok
Remote diagnostics: ok
Peer Type: configured
Local timers:
Receive interval: 300ms
Transmission interval: 300ms
Echo receive interval: disabled
Echo transmission interval: disabled
Peer timers:
Receive interval: 300ms
Transmission interval: 300ms
Echo receive interval: disabled
BFD требует открытых UDP-портов 3784 и 3785 между пирами. Если вы пропустили шаг с файрволом, BFD-сессии останутся в состоянии Down.
Как выполнить graceful shutdown для обслуживания?
RFC 8326 определяет well-known community GRACEFUL_SHUTDOWN (65535:0). Перед плановым обслуживанием вы помечаете все маршруты этим community. Пиры, которые его учитывают, устанавливают local-preference в 0 для этих маршрутов, перенаправляя трафик на альтернативные пути до отключения сессии. Это позволяет избежать чёрной дыры трафика, которая возникает при обычной конвергенции BGP.
Процедура graceful shutdown:
- Пометьте маршруты community GRACEFUL_SHUTDOWN на узле, который вы отключаете
- Дождитесь конвергенции (30-60 секунд, пока интернет перемаршрутизирует трафик)
- Убедитесь, что трафик переключился, через looking glass или счётчики трафика
- Остановите BGP-сессию
- Выполните обслуживание
- Восстановите сессию и удалите community
- Подтвердите реконвергенцию
Graceful shutdown в BIRD2
Чтобы инициировать graceful shutdown на основном узле перед обслуживанием, измените фильтр экспорта:
# Temporary export filter for graceful shutdown
filter upstream_export_shutdown {
if net = 198.51.100.0/24 || net = 2001:db8::/48 then {
bgp_community.add((65535, 0));
bgp_med = 65535;
accept;
}
reject;
}
Примените его, изменив фильтр экспорта в протоколе BGP и перезагрузив конфигурацию:
# Edit bird.conf: change export filter to upstream_export_shutdown
# Then reload
birdc configure
Чтобы учитывать graceful shutdown от пиров (примените на обоих узлах), добавьте проверку в фильтр импорта. Порядок важен: проверка graceful shutdown должна вызывать accept внутри блока if, иначе последующее присвоение bgp_local_pref перезапишет значение.
filter upstream_import_backup {
if (65535, 0) ~ bgp_community then {
bgp_local_pref = 0;
accept;
}
bgp_local_pref = 100;
accept;
}
Graceful shutdown в FRR
FRR предоставляет одну команду, которая выполняет маркировку автоматически:
vtysh -c "configure terminal
router bgp 64500
bgp graceful-shutdown
exit
exit"
Это добавляет community GRACEFUL_SHUTDOWN (65535:0) ко всем маршрутам и устанавливает local-preference в 0. Всем пирам отправляется route refresh.
Чтобы подтвердить отправку community:
vtysh -c "show ip bgp neighbors 192.0.2.1 advertised-routes"
Network Next Hop Metric LocPrf Weight Path
*> 198.51.100.0/24 0.0.0.0 0 0 32768 i
Community: graceful-shutdown
После обслуживания удалите:
vtysh -c "configure terminal
router bgp 64500
no bgp graceful-shutdown
exit
exit"
Чтобы FRR учитывал graceful shutdown от пиров, настройте входящий route-map:
vtysh -c "configure terminal
bgp community-list standard GRACEFUL_SHUTDOWN permit graceful-shutdown
route-map UPSTREAM-IN permit 5
match community GRACEFUL_SHUTDOWN
set local-preference 0
exit
route-map UPSTREAM-IN permit 10
set local-preference 200
exit
exit"
Sequence 5 выбирает маршруты с community и снижает local-preference до 0. Sequence 10 обрабатывает все остальные маршруты в обычном режиме.
Как протестировать BGP-фейловер?
Протестируйте фейловер, отключив основную BGP-сессию и наблюдая с резервного узла и внешней точки.
Шаг 1: Проверьте текущее состояние маршрутизации на обоих узлах.
BIRD2:
birdc show route for 198.51.100.0/24 all
FRR:
vtysh -c "show ip bgp 198.51.100.0/24"
Шаг 2: Отключите основную BGP-сессию.
BIRD2 (на VPS-PRI):
birdc disable upstream_v4
birdc disable upstream_v6
FRR (на VPS-PRI):
vtysh -c "configure terminal
router bgp 64500
neighbor 192.0.2.1 shutdown
neighbor 2001:db8:1::1 shutdown
exit
exit"
Шаг 3: Наблюдайте за резервным узлом.
На VPS-BKP маршрут теперь должен отображаться как единственный путь:
# BIRD2
birdc show route for 198.51.100.0/24
# FRR
vtysh -c "show ip bgp summary"
Шаг 4: Проверьте извне.
С вашей локальной машины или looking glass выполните traceroute к вашему префиксу:
traceroute -A 198.51.100.1
Трафик теперь должен входить через резервную локацию. С включённым BFD переключение происходит менее чем за секунду. Без BFD ожидайте полную длительность hold-таймера до конвергенции.
| Метод обнаружения | Типичное время фейловера |
|---|---|
| Только BGP hold-таймер (BIRD2 по умолчанию 240 с) | 160-240 с |
| Только BGP hold-таймер (FRR по умолчанию 180 с) | 120-180 с |
| Сниженный hold-таймер (напр. 30 с) | 20-30 с |
| BFD (интервалы 300 мс, множитель 3) | < 1 с |
Используйте NLNOG Looking Glass или bgp.tools для подтверждения глобальной конвергенции маршрутизации.
Как восстановить работу после фейловера?
Восстановите основную сессию и убедитесь, что трафик вернулся на предпочтительный путь.
BIRD2:
birdc enable upstream_v4
birdc enable upstream_v6
FRR:
vtysh -c "configure terminal
router bgp 64500
no neighbor 192.0.2.1 shutdown
no neighbor 2001:db8:1::1 shutdown
exit
exit"
Через несколько секунд проверьте, что основной путь снова предпочтён:
# BIRD2
birdc show route for 0.0.0.0/0 all | grep local_pref
BGP.local_pref: 200
# FRR
vtysh -c "show ip bgp"
Network Next Hop Metric LocPrf Weight Path
*> 0.0.0.0/0 192.0.2.1 200 0 64496 i
Снова выполните traceroute с внешнего хоста, чтобы подтвердить, что трафик вновь входит через основную локацию.
Сравнение конфигураций BIRD2 и FRR
| Функция | BIRD2 | FRR |
|---|---|---|
| LOCAL_PREF | bgp_local_pref = 200; в фильтре импорта |
set local-preference 200 в route-map |
| MED | bgp_med = 0; в фильтре экспорта |
set metric 0 в route-map |
| AS-path prepend | bgp_path.prepend(64500); в фильтре экспорта |
set as-path prepend 64500 в route-map |
| BFD | protocol bfd {} + bfd graceful; в BGP |
секция bfd + neighbor X bfd profile Y |
| Graceful shutdown (инициация) | Добавить (65535, 0) в bgp_community в фильтре экспорта |
bgp graceful-shutdown под router bgp |
| Graceful shutdown (учёт) | Проверить (65535, 0) ~ bgp_community в фильтре импорта, установить bgp_local_pref = 0 |
match community GRACEFUL_SHUTDOWN в route-map, set local-preference 0 |
| Отключение сессии | birdc disable <protocol> |
neighbor X shutdown |
| Перезагрузка конфигурации | birdc configure |
write memory затем clear ip bgp * или перезапуск |
Мониторинг событий фейловера
Настройте мониторинг для получения оповещений при фейловере. Мониторинг BGP-анонсов с помощью BGPalerter на Linux описывает BGPalerter для мониторинга маршрутов. Как минимум отслеживайте:
- Изменения состояния BGP-сессий:
journalctl -u birdилиjournalctl -u frr - Флапы BFD-сессий:
birdc show bfd sessions/vtysh -c "show bfd peers" - Изменения количества маршрутов: оповещение, если число экспортируемых префиксов падает до нуля
Устранение неполадок
BGP-сессия зависла в состоянии Active/Connect:
- Проверьте правила файрвола для TCP 179
- Убедитесь, что IP пира и ASN совпадают с тем, что ожидает ваш аплинк
- Смотрите
journalctl -u bird -fилиjournalctl -u frr -fна предмет ошибок
BFD-сессия зависла в состоянии Down:
- UDP-порты 3784 и 3785 должны быть открыты в обоих направлениях
- Убедитесь, что пир поддерживает BFD и настроил его
- Проверьте проблемы MTU на пути
MED не влияет на входящий трафик:
- MED сравнивается только между маршрутами от одного AS. Если ваши аплинки — разные AS, используйте AS-path prepending
- Некоторые аплинки игнорируют MED по политике. Уточните у провайдера
Community graceful shutdown не учитывается:
- Пир должен явно поддерживать RFC 8326. Не все аплинки это делают
- Уточните у провайдера, учитывают ли они community GRACEFUL_SHUTDOWN
- Некоторые реализации требуют явной настройки для учёта community
Трафик не переключается:
- Убедитесь, что оба узла анонсируют один и тот же префикс:
birdc show route export upstream_v4илиvtysh -c "show ip bgp neighbors X advertised-routes" - Проверяйте с внешнего looking glass, а не с самих узлов
- DNS TTL может удерживать клиентов на старом IP, если вы используете отдельные IP для сервисов поверх anycast-префикса
Готовы попробовать?
Запускайте BGP-сессии на собственном IP-пространстве с VPS Virtua.Cloud. →