Failover BGP e multihoming da due VPS

11 min di lettura·Matthieu·bird2bfdfailoverfrrbgpmultihoming|

Annuncia lo stesso prefisso da due posizioni con BGP per il failover automatico. Copre LOCAL_PREF, MED, AS-path prepending, BFD e graceful shutdown con configurazioni complete per BIRD2 e FRR.

Questo tutorial spiega come annunciare lo stesso prefisso IP da due VPS separati tramite BGP. Configurerai la preferenza primario/backup con LOCAL_PREF e MED, abiliterai BFD per il rilevamento guasti in meno di un secondo e implementerai il graceful shutdown per la manutenzione pianificata. Tutti gli esempi mostrano BIRD2 e FRR affiancati.

Prerequisiti:

Cos'è il multihoming BGP e perché usarlo su un VPS?

Il multihoming BGP significa annunciare lo stesso prefisso IP da due o più posizioni tramite eBGP. Ogni posizione mantiene una sessione BGP indipendente con il proprio provider upstream. Se una posizione si guasta, l'altra continua ad annunciare il prefisso e assorbe automaticamente tutto il traffico. Il tempo di convergenza dipende dagli hold timer (tipicamente 180-240 secondi con le impostazioni predefinite) o da BFD (sotto il secondo con configurazione corretta).

Su un VPS, il multihoming offre ridondanza senza dipendere da un singolo data center. Esegui due istanze VPS in posizioni diverse, entrambe che annunciano il tuo prefisso. Una funge da primaria, l'altra da backup. Gli attributi di traffic engineering (LOCAL_PREF, MED, AS-path prepending) controllano quale percorso gestisce il traffico in condizioni normali.

Come si progetta il failover BGP tra due posizioni?

Il setup utilizza due VPS Virtua in posizioni europee diverse, ciascuno con una sessione eBGP verso il router upstream locale. Entrambi annunciano lo stesso /24 e /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

Entrambi i nodi appartengono al tuo AS (AS 64500 in questi esempi). Sostituisci ASN, prefissi e IP di peering con i tuoi valori reali.

Regole firewall per entrambi i nodi:

BGP usa la porta TCP 179. BFD usa le porte UDP 3784 e 3785. Apri queste porte tra il tuo VPS e il peer upstream prima di procedere.

# 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

Come si controlla la preferenza di percorso BGP?

Tre attributi permettono di influenzare quale percorso segue il traffico. Ognuno opera a un livello diverso.

Attributo Direzione Ambito Inviato ai peer? Quando usarlo
LOCAL_PREF Uscita (la tua uscita) All'interno del tuo AS No (solo iBGP) Controllare quale nodo invia il traffico in uscita
MED Ingresso (dall'upstream) Tra te e un AS upstream Sì (al vicino diretto) Indicare a un upstream quale punto di ingresso preferire
AS-path prepending Ingresso (globale) Tutti gli AS nel percorso Sì (propagato) Far apparire un percorso più lungo a tutta Internet

LOCAL_PREF e MED sono precisi. L'AS-path prepending è uno strumento grossolano ma funziona quando le tue posizioni sono connesse a upstream diversi.

Come si configura LOCAL_PREF per i percorsi primario e backup?

LOCAL_PREF determina quale percorso di uscita preferisce il tuo AS per il traffico in uscita. Il valore più alto vince. Il valore predefinito è 100. Imposta 200 sul nodo primario e lascia 100 sul backup. Questo influisce solo sul traffico che lascia la tua rete.

Configurazione LOCAL_PREF con BIRD2

Sul nodo primario (VPS-PRI), crea o modifica il filtro di import:

# /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;
    };
}

Sul nodo backup (VPS-BKP), mantieni il LOCAL_PREF predefinito:

# /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;
    };
}

Ricarica BIRD2 e controlla le rotte:

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

Il valore BGP.local_pref: 200 sul nodo primario significa che sarà preferito per il traffico in uscita.

Configurazione LOCAL_PREF con FRR

Sul 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"

Sul nodo backup, imposta set local-preference 100 (o ometti la route-map dato che 100 è il valore predefinito).

Controlla la tabella di routing:

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

Come si usa MED per controllare il traffico in ingresso?

MED (Multi-Exit Discriminator) indica al tuo upstream quale punto di ingresso preferire. Il valore più basso vince. Imposta MED 0 sul primario e MED 100 sul backup. MED viene confrontato solo tra percorsi ricevuti dallo stesso AS vicino, quindi funziona meglio quando entrambe le posizioni fanno peering con lo stesso provider upstream.

Configurazione MED con BIRD2

Sul nodo primario, imposta MED nel filtro di export:

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;
    };
}

Sul nodo backup:

filter upstream_export_backup {
    if net = 198.51.100.0/24 || net = 2001:db8::/48 then {
        bgp_med = 100;
        accept;
    }
    reject;
}

Configurazione MED con FRR

Sul 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"

Sul nodo backup, usa set metric 100.

Controlla le rotte esportate:

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 colonna Metric mostra 0 sul primario. Il backup mostrerà 100.

Quando usare AS-path prepending invece di MED?

Usa l'AS-path prepending quando le tue due posizioni sono connesse a provider upstream diversi. MED viene confrontato solo tra percorsi dello stesso AS, quindi non ha effetto se i tuoi upstream sono AS diversi. Il prepending fa apparire il percorso del backup più lungo, orientando le decisioni di routing globali verso il primario.

Aggiungi il tuo ASN da 1 a 3 volte sul nodo backup. Più di 3 prepend raramente cambia le decisioni di routing e aggiunge solo rumore.

BIRD2 (filtro di export 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"

Dopo l'applicazione, controlla l'AS path da un looking glass o un host remoto:

# From an external machine
traceroute -A 198.51.100.1

Il percorso del backup ora mostra 64500 64500 64500 (il tuo ASN appare tre volte: una reale, due aggiunte) mentre il primario mostra 64500 una sola volta.

Come si abilita BFD per il rilevamento rapido dei guasti?

Senza BFD, BGP si affida agli hold timer per rilevare un guasto del peer. L'hold time predefinito è di 240 secondi in BIRD2 e 180 secondi in FRR. Con BFD, il rilevamento scende sotto il secondo su link a bassa latenza.

Parametro Predefinito Raccomandato per VPS
Intervallo di trasmissione 300 ms 300 ms
Intervallo di ricezione 300 ms 300 ms
Moltiplicatore di rilevamento 3 3
Tempo di rilevamento effettivo 900 ms 900 ms

Per ambienti VPS sullo stesso backbone del provider, intervalli di 300 ms con moltiplicatore 3 garantiscono un rilevamento affidabile sotto il secondo senza falsi positivi. Non scendere sotto i 100 ms su istanze VPS. Il jitter della virtualizzazione può causare flapping.

Configurazione BFD con BIRD2

Aggiungi un protocollo BFD e abilitalo sulla sessione 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;
    };
}

L'opzione bfd graceful significa che BIRD2 attiverà un graceful restart (conservando le rotte obsolete) anziché un hard reset della sessione quando BFD rileva un guasto. Se il peer non esegue BFD, la sessione si stabilisce normalmente.

Dopo il ricaricamento, controlla lo stato 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

Configurazione 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"

Controlla lo stato 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 richiede che le porte UDP 3784 e 3785 siano aperte tra i peer. Se hai saltato il passaggio del firewall, le sessioni BFD rimarranno nello stato Down.

Come si esegue un graceful shutdown per la manutenzione?

La RFC 8326 definisce la community ben nota GRACEFUL_SHUTDOWN (65535:0). Prima di una manutenzione pianificata, contrassegni tutte le rotte con questa community. I peer che la rispettano impostano la local-preference a 0 per quelle rotte, facendo spostare il traffico su percorsi alternativi prima di chiudere la sessione. Questo evita il buco nero di traffico che si verifica durante la normale convergenza BGP.

La procedura di graceful shutdown:

  1. Contrassegna le rotte con la community GRACEFUL_SHUTDOWN sul nodo che stai per spegnere
  2. Attendi la convergenza (30-60 secondi perché Internet reindirizzi il traffico)
  3. Verifica che il traffico si sia spostato tramite looking glass o contatori di traffico
  4. Chiudi la sessione BGP
  5. Esegui la manutenzione
  6. Ripristina la sessione e rimuovi la community
  7. Conferma la ri-convergenza

Graceful shutdown con BIRD2

Per avviare il graceful shutdown sul nodo primario prima della manutenzione, modifica il filtro di export:

# 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;
}

Applicalo cambiando il filtro di export nel protocollo BGP e ricaricando:

# Edit bird.conf: change export filter to upstream_export_shutdown
# Then reload
birdc configure

Per rispettare il graceful shutdown dai peer (applica su entrambi i nodi), aggiungi un controllo nel filtro di import. L'ordine conta: il controllo del graceful shutdown deve chiamare accept dentro il blocco if, altrimenti un'assegnazione successiva di bgp_local_pref la sovrascriverà.

filter upstream_import_backup {
    if (65535, 0) ~ bgp_community then {
        bgp_local_pref = 0;
        accept;
    }
    bgp_local_pref = 100;
    accept;
}

Graceful shutdown con FRR

FRR fornisce un singolo comando che gestisce il tagging automaticamente:

vtysh -c "configure terminal
router bgp 64500
 bgp graceful-shutdown
exit
exit"

Questo aggiunge la community GRACEFUL_SHUTDOWN (65535:0) a tutte le rotte e imposta la local-preference a 0. Viene inviato un route refresh a tutti i peer.

Per confermare che la community viene inviata:

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

Dopo la manutenzione, rimuovila:

vtysh -c "configure terminal
router bgp 64500
 no bgp graceful-shutdown
exit
exit"

Per far sì che FRR rispetti il graceful shutdown dai peer, configura una route-map in ingresso:

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 sequenza 5 corrisponde alle rotte con la community e abbassa la local-preference a 0. La sequenza 10 gestisce normalmente tutte le altre rotte.

Come si testa il failover BGP?

Testa il failover chiudendo la sessione BGP primaria e osservando dal nodo backup e da un punto esterno.

Passo 1: Controlla lo stato di routing attuale su entrambi i nodi.

BIRD2:

birdc show route for 198.51.100.0/24 all

FRR:

vtysh -c "show ip bgp 198.51.100.0/24"

Passo 2: Chiudi la sessione BGP primaria.

BIRD2 (su VPS-PRI):

birdc disable upstream_v4
birdc disable upstream_v6

FRR (su VPS-PRI):

vtysh -c "configure terminal
router bgp 64500
 neighbor 192.0.2.1 shutdown
 neighbor 2001:db8:1::1 shutdown
exit
exit"

Passo 3: Osserva il nodo backup.

Su VPS-BKP, la rotta dovrebbe ora apparire come unico percorso:

# BIRD2
birdc show route for 198.51.100.0/24

# FRR
vtysh -c "show ip bgp summary"

Passo 4: Testa dall'esterno.

Dal tuo computer locale o da un looking glass, esegui un traceroute verso il tuo prefisso:

traceroute -A 198.51.100.1

Il traffico dovrebbe ora entrare dalla posizione di backup. Con BFD abilitato, il passaggio avviene in meno di un secondo. Senza BFD, aspettati la durata completa dell'hold timer prima della convergenza.

Metodo di rilevamento Tempo di failover tipico
Solo hold timer BGP (BIRD2 predefinito 240 s) 160-240 s
Solo hold timer BGP (FRR predefinito 180 s) 120-180 s
Hold timer ridotto (es. 30 s) 20-30 s
BFD (intervalli 300 ms, moltiplicatore 3) < 1 s

Usa NLNOG Looking Glass o bgp.tools per confermare la convergenza del routing globale.

Come si ripristina il servizio dopo un failover?

Ripristina la sessione primaria e conferma che il traffico torna sul percorso preferito.

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"

Dopo qualche secondo, verifica che il percorso primario sia di nuovo preferito:

# 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

Esegui di nuovo un traceroute da un host esterno per confermare che il traffico rientra dalla posizione primaria.

Confronto configurazioni BIRD2 e FRR

Funzionalità BIRD2 FRR
LOCAL_PREF bgp_local_pref = 200; nel filtro di import set local-preference 200 nella route-map
MED bgp_med = 0; nel filtro di export set metric 0 nella route-map
AS-path prepend bgp_path.prepend(64500); nel filtro di export set as-path prepend 64500 nella route-map
BFD protocol bfd {} + bfd graceful; in BGP sezione bfd + neighbor X bfd profile Y
Graceful shutdown (avviare) Aggiungere (65535, 0) a bgp_community nel filtro di export bgp graceful-shutdown sotto router bgp
Graceful shutdown (rispettare) Controllare (65535, 0) ~ bgp_community nel filtro di import, impostare bgp_local_pref = 0 match community GRACEFUL_SHUTDOWN nella route-map, set local-preference 0
Disabilitare sessione birdc disable <protocol> neighbor X shutdown
Ricaricare configurazione birdc configure write memory poi clear ip bgp * o riavvio

Monitoraggio degli eventi di failover

Configura il monitoraggio per ricevere avvisi quando si verifica un failover. Monitorare gli annunci BGP con BGPalerter su Linux copre BGPalerter per il monitoraggio delle rotte. Come minimo, monitora:

  • Cambiamenti di stato delle sessioni BGP: journalctl -u bird o journalctl -u frr
  • Flap delle sessioni BFD: birdc show bfd sessions / vtysh -c "show bfd peers"
  • Variazioni nel numero di rotte: allarme se il numero di prefissi esportati scende a zero

Risoluzione dei problemi

Sessione BGP bloccata nello stato Active/Connect:

  • Controlla le regole firewall per TCP 179
  • Verifica che l'IP del peer e l'ASN corrispondano a quanto si aspetta il tuo upstream
  • Consulta journalctl -u bird -f o journalctl -u frr -f per messaggi di errore

Sessione BFD bloccata nello stato Down:

  • Le porte UDP 3784 e 3785 devono essere aperte in entrambe le direzioni
  • Conferma che il peer supporti BFD e lo abbia configurato
  • Controlla problemi di MTU sul percorso

MED non influenza il traffico in ingresso:

  • MED viene confrontato solo tra percorsi dello stesso AS. Se i tuoi upstream sono AS diversi, usa l'AS-path prepending
  • Alcuni upstream ignorano MED per policy. Chiedi al tuo provider

La community di graceful shutdown non viene rispettata:

  • Il peer deve supportare esplicitamente la RFC 8326. Non tutti gli upstream lo fanno
  • Verifica con il tuo provider se rispettano la community GRACEFUL_SHUTDOWN
  • Alcune implementazioni richiedono una configurazione esplicita per rispettare la community

Il traffico non effettua il failover:

  • Verifica che entrambi i nodi annuncino lo stesso prefisso con birdc show route export upstream_v4 o vtysh -c "show ip bgp neighbors X advertised-routes"
  • Controlla da un looking glass esterno, non dai nodi stessi
  • Il TTL DNS può mantenere i client puntati al vecchio IP se usi IP per posizione per i servizi sopra il prefisso anycast