Failover BGP y multihoming desde dos ubicaciones VPS
Anuncia el mismo prefijo desde dos ubicaciones con BGP para failover automático. Cubre LOCAL_PREF, MED, AS-path prepending, BFD y apagado graceful con configuraciones completas de BIRD2 y FRR.
Este tutorial explica cómo anunciar el mismo prefijo IP desde dos VPS separados usando BGP. Configurarás la preferencia primario/backup con LOCAL_PREF y MED, habilitarás BFD para detección de fallos en menos de un segundo, e implementarás apagado graceful (graceful shutdown) para mantenimiento planificado. Todos los ejemplos muestran BIRD2 y FRR en paralelo.
Requisitos previos:
- Una sesión BGP funcional en al menos un VPS (Configuración de BGP con BIRD2 en un VPS Linux o Configuración de BGP con FRRouting en un VPS Linux)
- Tu propio ASN y al menos un prefijo /24 (IPv4) o /48 (IPv6)
- Conocimiento básico de comunidades BGP (BGP Communities: estándar, large y extended)
¿Qué es el multihoming BGP y por qué usarlo en un VPS?
El multihoming BGP consiste en anunciar el mismo prefijo IP desde dos o más ubicaciones mediante eBGP. Cada ubicación mantiene una sesión BGP independiente con su proveedor upstream. Si una ubicación falla, la otra continúa anunciando el prefijo y absorbe todo el tráfico automáticamente. El tiempo de convergencia depende de los hold timers (normalmente 180-240 segundos con configuración por defecto) o de BFD (menos de un segundo con configuración adecuada).
En un VPS, el multihoming proporciona redundancia sin depender de un solo centro de datos. Ejecutas dos instancias VPS en ubicaciones diferentes, ambas anunciando tu prefijo. Una actúa como primaria, la otra como backup. Los atributos de ingeniería de tráfico (LOCAL_PREF, MED, AS-path prepending) controlan qué camino gestiona el tráfico en condiciones normales.
¿Cómo se diseña el failover BGP entre dos ubicaciones?
La configuración utiliza dos VPS Virtua en ubicaciones europeas diferentes, cada uno manteniendo una sesión eBGP con el router upstream local. Ambos anuncian el mismo /24 y /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
Ambos nodos pertenecen a tu AS (AS 64500 en estos ejemplos). Sustituye el ASN, los prefijos y las IPs de peering por tus valores reales.
Reglas de firewall para ambos nodos:
BGP usa el puerto TCP 179. BFD usa los puertos UDP 3784 y 3785. Abre estos puertos entre tu VPS y el peer upstream antes de continuar.
# 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
¿Cómo se controla la preferencia de ruta BGP?
Tres atributos permiten influir en el camino que toma el tráfico. Cada uno opera a un nivel diferente.
| Atributo | Dirección | Alcance | ¿Se envía a los peers? | Cuándo usarlo |
|---|---|---|---|---|
| LOCAL_PREF | Saliente (tu salida) | Dentro de tu AS | No (solo iBGP) | Controlar qué nodo envía el tráfico saliente |
| MED | Entrante (desde upstream) | Entre tú y un AS upstream | Sí (al vecino directo) | Indicar a un upstream qué punto de entrada preferir |
| AS-path prepending | Entrante (global) | Todos los AS en la ruta | Sí (se propaga) | Hacer que una ruta parezca más larga para todo Internet |
LOCAL_PREF y MED son precisos. El AS-path prepending es una herramienta gruesa pero funciona cuando tus ubicaciones están conectadas a upstreams diferentes.
¿Cómo se configura LOCAL_PREF para rutas primaria y backup?
LOCAL_PREF determina qué ruta de salida prefiere tu AS para el tráfico saliente. El valor más alto gana. El valor por defecto es 100. Establece 200 en el nodo primario y deja 100 en el backup. Esto solo afecta al tráfico que sale de tu red.
Configuración de LOCAL_PREF con BIRD2
En el nodo primario (VPS-PRI), crea o modifica el filtro de importación:
# /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;
};
}
En el nodo backup (VPS-BKP), mantén el LOCAL_PREF por defecto:
# /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;
};
}
Recarga BIRD2 y comprueba las rutas:
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
El valor BGP.local_pref: 200 en el nodo primario indica que será preferido para el tráfico saliente.
Configuración de LOCAL_PREF con FRR
En el nodo primario:
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"
En el nodo backup, usa set local-preference 100 (u omite el route-map ya que 100 es el valor por defecto).
Comprueba la tabla de rutas:
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
¿Cómo se usa MED para controlar el tráfico entrante?
MED (Multi-Exit Discriminator) indica a tu upstream qué punto de entrada preferir. El valor más bajo gana. Establece MED 0 en el primario y MED 100 en el backup. MED solo se compara entre rutas recibidas del mismo AS vecino, por lo que funciona mejor cuando ambas ubicaciones hacen peering con el mismo proveedor upstream.
Configuración de MED con BIRD2
En el nodo primario, establece MED en el filtro de exportación:
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;
};
}
En el nodo backup:
filter upstream_export_backup {
if net = 198.51.100.0/24 || net = 2001:db8::/48 then {
bgp_med = 100;
accept;
}
reject;
}
Configuración de MED con FRR
En el nodo primario:
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"
En el nodo backup, usa set metric 100.
Comprueba las rutas exportadas:
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
La columna Metric muestra 0 en el primario. El backup mostrará 100.
¿Cuándo usar AS-path prepending en lugar de MED?
Usa AS-path prepending cuando tus dos ubicaciones estén conectadas a proveedores upstream diferentes. MED solo se compara entre rutas del mismo AS, así que no tiene efecto si tus upstreams son ASes diferentes. El prepending hace que la ruta del backup parezca más larga, orientando las decisiones de enrutamiento globales hacia el primario.
Añade tu propio ASN de 1 a 3 veces en el nodo backup. Más de 3 prepends rara vez cambia las decisiones de enrutamiento y solo añade ruido.
BIRD2 (filtro de exportación del nodo backup):
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 (nodo backup):
vtysh -c "configure terminal
route-map UPSTREAM-OUT permit 10
set as-path prepend 64500 64500
exit
exit"
Tras aplicarlo, comprueba el AS path desde un looking glass o una máquina remota:
# From an external machine
traceroute -A 198.51.100.1
La ruta del backup ahora muestra 64500 64500 64500 (tu ASN aparece tres veces: una real, dos añadidas) mientras que la del primario muestra 64500 una sola vez.
¿Cómo se habilita BFD para detección rápida de fallos?
Sin BFD, BGP depende de los hold timers para detectar un fallo del peer. El hold time por defecto es de 240 segundos en BIRD2 y 180 segundos en FRR. Con BFD, la detección baja a menos de un segundo en enlaces de baja latencia.
| Parámetro | Por defecto | Recomendado para VPS |
|---|---|---|
| Intervalo de transmisión | 300 ms | 300 ms |
| Intervalo de recepción | 300 ms | 300 ms |
| Multiplicador de detección | 3 | 3 |
| Tiempo de detección efectivo | 900 ms | 900 ms |
Para entornos VPS en el mismo backbone del proveedor, intervalos de 300 ms con multiplicador 3 ofrecen detección fiable en menos de un segundo sin falsos positivos. No bajes de 100 ms en instancias VPS. El jitter de virtualización puede causar flapping.
Configuración de BFD con BIRD2
Añade un protocolo BFD y habilítalo en la sesión 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;
};
}
La opción bfd graceful hace que BIRD2 lance un reinicio graceful (conservando rutas obsoletas) en lugar de un reinicio brusco de la sesión cuando BFD detecta un fallo. Si el peer no ejecuta BFD, la sesión se establece normalmente.
Tras recargar, comprueba el estado de 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
Configuración de BFD con 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"
Comprueba el estado del peer 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 requiere que los puertos UDP 3784 y 3785 estén abiertos entre los peers. Si saltaste el paso del firewall, las sesiones BFD permanecerán en estado Down.
¿Cómo se realiza un apagado graceful para mantenimiento?
La RFC 8326 define la comunidad bien conocida GRACEFUL_SHUTDOWN (65535:0). Antes de un mantenimiento planificado, marcas todas las rutas con esta comunidad. Los peers que la respetan fijan la local-preference a 0 para esas rutas, redirigiendo el tráfico a rutas alternativas antes de cerrar la sesión. Esto evita el agujero negro de tráfico que ocurre durante la convergencia BGP normal.
El procedimiento de apagado graceful:
- Marca las rutas con la comunidad GRACEFUL_SHUTDOWN en el nodo que vas a apagar
- Espera la convergencia (30-60 segundos para que Internet redirija el tráfico)
- Comprueba que el tráfico ha cambiado de ruta usando un looking glass o contadores de tráfico
- Cierra la sesión BGP
- Realiza el mantenimiento
- Restablece la sesión y elimina la comunidad
- Confirma la re-convergencia
Apagado graceful con BIRD2
Para iniciar el apagado graceful en el nodo primario antes del mantenimiento, modifica el filtro de exportación:
# 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;
}
Aplícalo cambiando el filtro de exportación en el protocolo BGP y recargando:
# Edit bird.conf: change export filter to upstream_export_shutdown
# Then reload
birdc configure
Para respetar el apagado graceful de los peers (aplica esto en ambos nodos), añade una comprobación en el filtro de importación. El orden importa: la comprobación del apagado graceful debe llamar a accept dentro del bloque if, de lo contrario una asignación posterior de bgp_local_pref la sobrescribirá.
filter upstream_import_backup {
if (65535, 0) ~ bgp_community then {
bgp_local_pref = 0;
accept;
}
bgp_local_pref = 100;
accept;
}
Apagado graceful con FRR
FRR proporciona un solo comando que gestiona el marcado automáticamente:
vtysh -c "configure terminal
router bgp 64500
bgp graceful-shutdown
exit
exit"
Esto añade la comunidad GRACEFUL_SHUTDOWN (65535:0) a todas las rutas y fija la local-preference a 0. Se envía un refresco de rutas a todos los peers.
Para confirmar que se está enviando la comunidad:
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
Tras el mantenimiento, elimínala:
vtysh -c "configure terminal
router bgp 64500
no bgp graceful-shutdown
exit
exit"
Para que FRR respete el apagado graceful de los peers, configura un route-map de entrada:
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"
La secuencia 5 coincide con las rutas que llevan la comunidad y reduce la local-preference a 0. La secuencia 10 procesa normalmente todas las demás rutas.
¿Cómo se prueba el failover BGP?
Prueba el failover cerrando la sesión BGP primaria y observando desde el nodo backup y un punto externo.
Paso 1: Comprueba el estado de enrutamiento actual en ambos nodos.
BIRD2:
birdc show route for 198.51.100.0/24 all
FRR:
vtysh -c "show ip bgp 198.51.100.0/24"
Paso 2: Cierra la sesión BGP primaria.
BIRD2 (en VPS-PRI):
birdc disable upstream_v4
birdc disable upstream_v6
FRR (en VPS-PRI):
vtysh -c "configure terminal
router bgp 64500
neighbor 192.0.2.1 shutdown
neighbor 2001:db8:1::1 shutdown
exit
exit"
Paso 3: Observa el nodo backup.
En VPS-BKP, la ruta debería aparecer ahora como el único camino:
# BIRD2
birdc show route for 198.51.100.0/24
# FRR
vtysh -c "show ip bgp summary"
Paso 4: Prueba desde fuera.
Desde tu máquina local o un looking glass, haz un traceroute a tu prefijo:
traceroute -A 198.51.100.1
El tráfico debería entrar ahora por la ubicación backup. Con BFD habilitado, la conmutación ocurre en menos de un segundo. Sin BFD, espera la duración completa del hold timer antes de la convergencia.
| Método de detección | Tiempo de failover típico |
|---|---|
| Solo hold timer BGP (BIRD2 por defecto 240 s) | 160-240 s |
| Solo hold timer BGP (FRR por defecto 180 s) | 120-180 s |
| Hold timer reducido (ej. 30 s) | 20-30 s |
| BFD (intervalos de 300 ms, multiplicador 3) | < 1 s |
Usa NLNOG Looking Glass o bgp.tools para confirmar la convergencia del enrutamiento global.
¿Cómo se recupera el servicio tras un failover?
Restablece la sesión primaria y confirma que el tráfico vuelve a la ruta preferida.
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"
Tras unos segundos, comprueba que la ruta primaria vuelve a ser la preferida:
# 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
Ejecuta un traceroute desde un host externo de nuevo para confirmar que el tráfico vuelve a entrar por la ubicación primaria.
Comparación de configuraciones BIRD2 y FRR
| Funcionalidad | BIRD2 | FRR |
|---|---|---|
| LOCAL_PREF | bgp_local_pref = 200; en el filtro de importación |
set local-preference 200 en el route-map |
| MED | bgp_med = 0; en el filtro de exportación |
set metric 0 en el route-map |
| AS-path prepend | bgp_path.prepend(64500); en el filtro de exportación |
set as-path prepend 64500 en el route-map |
| BFD | protocol bfd {} + bfd graceful; en BGP |
sección bfd + neighbor X bfd profile Y |
| Apagado graceful (iniciar) | Añadir (65535, 0) a bgp_community en el filtro de exportación |
bgp graceful-shutdown bajo router bgp |
| Apagado graceful (respetar) | Comprobar (65535, 0) ~ bgp_community en el filtro de importación, fijar bgp_local_pref = 0 |
match community GRACEFUL_SHUTDOWN en el route-map, set local-preference 0 |
| Deshabilitar sesión | birdc disable <protocol> |
neighbor X shutdown |
| Recargar configuración | birdc configure |
write memory y luego clear ip bgp * o reinicio |
Monitorización de eventos de failover
Configura monitorización para recibir alertas cuando ocurra un failover. Monitorizar anuncios BGP con BGPalerter en Linux cubre BGPalerter para monitorización de rutas. Como mínimo, vigila:
- Cambios de estado de sesiones BGP:
journalctl -u birdojournalctl -u frr - Flaps de sesiones BFD:
birdc show bfd sessions/vtysh -c "show bfd peers" - Cambios en el número de rutas: alerta si el número de prefijos exportados cae a cero
Resolución de problemas
Sesión BGP estancada en estado Active/Connect:
- Comprueba las reglas de firewall para TCP 179
- Verifica que la IP del peer y el ASN coincidan con lo que espera tu upstream
- Revisa
journalctl -u bird -fojournalctl -u frr -fen busca de mensajes de error
Sesión BFD estancada en estado Down:
- Los puertos UDP 3784 y 3785 deben estar abiertos en ambas direcciones
- Confirma que el peer soporta BFD y lo tiene configurado
- Comprueba problemas de MTU en la ruta
MED no afecta al tráfico entrante:
- MED solo se compara entre rutas del mismo AS. Si tus upstreams son ASes diferentes, usa AS-path prepending en su lugar
- Algunos upstreams ignoran MED por política. Consulta con tu proveedor
La comunidad de apagado graceful no se respeta:
- El peer debe soportar explícitamente la RFC 8326. No todos los upstreams lo hacen
- Consulta con tu proveedor si respetan la comunidad GRACEFUL_SHUTDOWN
- Algunas implementaciones requieren configuración explícita para respetar la comunidad
El tráfico no conmuta:
- Verifica que ambos nodos anuncian el mismo prefijo con
birdc show route export upstream_v4ovtysh -c "show ip bgp neighbors X advertised-routes" - Comprueba desde un looking glass externo, no desde los propios nodos
- El TTL de DNS puede mantener a los clientes apuntando a la IP antigua si usas IPs por ubicación para servicios sobre el prefijo anycast
¿Listo para probarlo?
Ejecute sesiones BGP en su propio espacio IP con VPS Virtua.Cloud. →