Failover BGP et multihoming depuis deux VPS

12 min de lecture·Matthieu·bird2bfdfailoverfrrbgpmultihoming|

Annoncez le même préfixe depuis deux emplacements avec BGP pour un failover automatique. Couvre LOCAL_PREF, MED, AS-path prepending, BFD et l'arrêt gracieux avec des configurations complètes BIRD2 et FRR.

Ce tutoriel explique comment annoncer le même préfixe IP depuis deux VPS distincts via BGP. Vous configurerez la préférence primaire/backup avec LOCAL_PREF et MED, activerez BFD pour une détection de panne en moins d'une seconde, et mettrez en place l'arrêt gracieux pour la maintenance planifiée. Tous les exemples présentent BIRD2 et FRR côte à côte.

Prérequis :

Qu'est-ce que le multihoming BGP et pourquoi l'utiliser sur un VPS ?

Le multihoming BGP consiste à annoncer le même préfixe IP depuis deux emplacements ou plus via eBGP. Chaque emplacement maintient une session BGP indépendante avec son fournisseur en amont. Si un emplacement tombe en panne, l'autre continue d'annoncer le préfixe et absorbe automatiquement tout le trafic. Le temps de convergence dépend des hold timers (généralement 180 à 240 secondes avec les paramètres par défaut) ou de BFD (moins d'une seconde avec une configuration adaptée).

Sur un VPS, le multihoming offre de la redondance sans dépendre d'un seul centre de données. Vous faites tourner deux instances VPS dans des emplacements différents, les deux annonçant votre préfixe. L'une agit comme primaire, l'autre comme backup. Les attributs d'ingénierie de trafic (LOCAL_PREF, MED, AS-path prepending) contrôlent quel chemin gère le trafic en conditions normales.

Comment architecturer le failover BGP entre deux emplacements ?

Le dispositif utilise deux VPS Virtua dans des emplacements européens différents, chacun maintenant une session eBGP avec le routeur amont local. Les deux annoncent le même /24 et /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

Les deux nœuds appartiennent à votre AS (AS 64500 dans ces exemples). Remplacez l'ASN, les préfixes et les IP de peering par vos valeurs réelles.

Règles de pare-feu pour les deux nœuds :

BGP utilise le port TCP 179. BFD utilise les ports UDP 3784 et 3785. Ouvrez ces ports entre votre VPS et le pair amont avant de continuer.

# 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

Comment contrôler la préférence de chemin BGP ?

Trois attributs permettent d'influencer le chemin emprunté par le trafic. Chacun opère à un niveau différent.

Attribut Direction Portée Envoyé aux pairs ? Quand l'utiliser
LOCAL_PREF Sortant (votre sortie) Au sein de votre AS Non (iBGP uniquement) Contrôler quel nœud envoie le trafic sortant
MED Entrant (depuis l'amont) Entre vous et un AS amont Oui (au voisin direct) Indiquer à un amont quel point d'entrée préférer
AS-path prepending Entrant (global) Tous les AS du chemin Oui (propagé) Rendre un chemin plus long pour tout Internet

LOCAL_PREF et MED sont précis. L'AS-path prepending est un outil grossier mais fonctionne quand vos emplacements sont connectés à des amonts différents.

Comment configurer LOCAL_PREF pour les chemins primaire et backup ?

LOCAL_PREF détermine quel chemin de sortie votre AS préfère pour le trafic sortant. La valeur la plus élevée gagne. La valeur par défaut est 100. Mettez 200 sur le nœud primaire et laissez 100 sur le backup. Cela n'affecte que le trafic quittant votre réseau.

Configuration LOCAL_PREF avec BIRD2

Sur le nœud primaire (VPS-PRI), créez ou modifiez le filtre d'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;
    };
}

Sur le nœud backup (VPS-BKP), gardez le LOCAL_PREF par défaut :

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

Rechargez BIRD2 et vérifiez les routes :

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

La valeur BGP.local_pref: 200 sur le nœud primaire signifie qu'il sera préféré pour le trafic sortant.

Configuration LOCAL_PREF avec FRR

Sur le nœud primaire :

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"

Sur le nœud backup, mettez set local-preference 100 (ou omettez la route-map puisque 100 est la valeur par défaut).

Vérifiez la table de routage :

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

Comment utiliser MED pour contrôler le trafic entrant ?

MED (Multi-Exit Discriminator) indique à votre amont quel point d'entrée préférer. La valeur la plus basse gagne. Mettez MED 0 sur le primaire et MED 100 sur le backup. MED n'est comparé qu'entre les chemins reçus du même AS voisin, il fonctionne donc mieux quand les deux emplacements sont connectés au même fournisseur amont.

Configuration MED avec BIRD2

Sur le nœud primaire, définissez MED dans le filtre d'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;
    };
}

Sur le nœud backup :

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

Configuration MED avec FRR

Sur le nœud primaire :

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"

Sur le nœud backup, utilisez set metric 100.

Vérifiez les routes exportées :

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 colonne Metric affiche 0 sur le primaire. Le backup affichera 100.

Quand utiliser l'AS-path prepending au lieu de MED ?

Utilisez l'AS-path prepending quand vos deux emplacements sont connectés à des fournisseurs amont différents. MED n'est comparé qu'entre les chemins du même AS, il n'a donc aucun effet si vos amonts sont des AS différents. Le prepending allonge artificiellement le chemin du backup, orientant les décisions de routage globales vers le primaire.

Ajoutez votre propre ASN 1 à 3 fois sur le nœud backup. Plus de 3 prepends change rarement les décisions de routage et ne fait qu'ajouter du bruit.

BIRD2 (filtre d'export du nœud 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 (nœud backup) :

vtysh -c "configure terminal
route-map UPSTREAM-OUT permit 10
 set as-path prepend 64500 64500
exit
exit"

Après application, vérifiez l'AS path depuis un looking glass ou une machine distante :

# From an external machine
traceroute -A 198.51.100.1

Le chemin backup affiche maintenant 64500 64500 64500 (votre ASN apparait trois fois : une fois réel, deux fois ajouté) tandis que le primaire affiche 64500 une seule fois.

Comment activer BFD pour une détection rapide des pannes ?

Sans BFD, BGP repose sur les hold timers pour détecter une panne du pair. Le hold time par défaut est de 240 secondes dans BIRD2 et 180 secondes dans FRR. Avec BFD, la détection passe en dessous de la seconde sur les liens à faible latence.

Paramètre Par défaut Recommandé pour VPS
Intervalle d'émission 300 ms 300 ms
Intervalle de réception 300 ms 300 ms
Multiplicateur de détection 3 3
Temps de détection effectif 900 ms 900 ms

Pour les environnements VPS sur le même backbone, des intervalles de 300 ms avec un multiplicateur de 3 offrent une détection fiable en moins d'une seconde sans faux positifs. Ne descendez pas en dessous de 100 ms sur des instances VPS. La gigue de virtualisation peut provoquer du flapping.

Configuration BFD avec BIRD2

Ajoutez un protocole BFD et activez-le sur la session 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'option bfd graceful signifie que BIRD2 déclenchera un redémarrage gracieux (en conservant les routes obsolètes) plutôt qu'une réinitialisation brutale de la session quand BFD détecte une panne. Si le pair n'utilise pas BFD, la session s'établit normalement.

Après le rechargement, vérifiez l'état 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

Configuration BFD avec 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"

Vérifiez l'état du pair 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 nécessite que les ports UDP 3784 et 3785 soient ouverts entre les pairs. Si vous avez sauté l'étape du pare-feu, les sessions BFD resteront à l'état Down.

Comment effectuer un arrêt gracieux pour la maintenance ?

La RFC 8326 définit la communauté bien connue GRACEFUL_SHUTDOWN (65535:0). Avant une maintenance planifiée, vous marquez toutes les routes avec cette communauté. Les pairs qui la respectent fixent la local-preference à 0 pour ces routes, ce qui redirige le trafic vers les chemins alternatifs avant l'arrêt de la session. Cela évite le trou noir de trafic qui survient pendant la convergence BGP normale.

La procédure d'arrêt gracieux :

  1. Marquez les routes avec la communauté GRACEFUL_SHUTDOWN sur le nœud que vous allez arrêter
  2. Attendez la convergence (30 à 60 secondes pour qu'Internet reroute le trafic)
  3. Vérifiez que le trafic a basculé via un looking glass ou des compteurs de trafic
  4. Arrêtez la session BGP
  5. Effectuez la maintenance
  6. Rétablissez la session et retirez la communauté
  7. Confirmez la re-convergence

Arrêt gracieux avec BIRD2

Pour initier l'arrêt gracieux sur le nœud primaire avant la maintenance, modifiez le filtre d'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;
}

Appliquez-le en changeant le filtre d'export dans le protocole BGP et en rechargeant :

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

Pour honorer l'arrêt gracieux des pairs (appliquez ceci sur les deux nœuds), ajoutez une vérification dans le filtre d'import. L'ordre est important : la vérification de l'arrêt gracieux doit appeler accept dans le bloc if, sinon une assignation ultérieure de bgp_local_pref l'écrasera.

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

Arrêt gracieux avec FRR

FRR fournit une commande unique qui gère le marquage automatiquement :

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

Cela ajoute la communauté GRACEFUL_SHUTDOWN (65535:0) à toutes les routes et fixe la local-preference à 0. Un rafraichissement des routes est déclenché vers tous les pairs.

Pour confirmer que la communauté est envoyée :

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

Après la maintenance, retirez-la :

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

Pour que FRR honore l'arrêt gracieux des pairs, configurez une route-map en entrée :

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 séquence 5 correspond aux routes portant la communauté et abaisse la local-preference à 0. La séquence 10 traite normalement toutes les autres routes.

Comment tester le failover BGP ?

Testez le failover en arrêtant la session BGP primaire et en observant depuis le nœud backup et un point de vue externe.

Étape 1 : Vérifiez l'état de routage actuel sur les deux nœuds.

BIRD2 :

birdc show route for 198.51.100.0/24 all

FRR :

vtysh -c "show ip bgp 198.51.100.0/24"

Étape 2 : Arrêtez la session BGP primaire.

BIRD2 (sur VPS-PRI) :

birdc disable upstream_v4
birdc disable upstream_v6

FRR (sur VPS-PRI) :

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

Étape 3 : Observez le nœud backup.

Sur VPS-BKP, la route devrait maintenant apparaitre comme le seul chemin :

# BIRD2
birdc show route for 198.51.100.0/24

# FRR
vtysh -c "show ip bgp summary"

Étape 4 : Testez depuis l'extérieur.

Depuis votre machine locale ou un looking glass, faites un traceroute vers votre préfixe :

traceroute -A 198.51.100.1

Le trafic devrait maintenant entrer par l'emplacement backup. Avec BFD activé, le basculement se fait en moins d'une seconde. Sans BFD, comptez la durée complète du hold timer avant la convergence.

Méthode de détection Temps de failover typique
Hold timer BGP seul (BIRD2 par défaut 240 s) 160-240 s
Hold timer BGP seul (FRR par défaut 180 s) 120-180 s
Hold timer réduit (par ex. 30 s) 20-30 s
BFD (intervalles de 300 ms, multiplicateur 3) < 1 s

Utilisez NLNOG Looking Glass ou bgp.tools pour confirmer la convergence du routage global.

Comment rétablir le service après un failover ?

Rétablissez la session primaire et confirmez que le trafic revient sur le chemin préféré.

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"

Après quelques secondes, vérifiez que le chemin primaire est de nouveau préféré :

# 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

Relancez un traceroute depuis un hôte externe pour confirmer que le trafic entre de nouveau par l'emplacement primaire.

Comparaison des configurations BIRD2 et FRR

Fonctionnalité BIRD2 FRR
LOCAL_PREF bgp_local_pref = 200; dans le filtre d'import set local-preference 200 dans la route-map
MED bgp_med = 0; dans le filtre d'export set metric 0 dans la route-map
AS-path prepend bgp_path.prepend(64500); dans le filtre d'export set as-path prepend 64500 dans la route-map
BFD protocol bfd {} + bfd graceful; dans BGP section bfd + neighbor X bfd profile Y
Arrêt gracieux (initier) Ajouter (65535, 0) à bgp_community dans le filtre d'export bgp graceful-shutdown sous router bgp
Arrêt gracieux (honorer) Vérifier (65535, 0) ~ bgp_community dans le filtre d'import, fixer bgp_local_pref = 0 match community GRACEFUL_SHUTDOWN dans la route-map, set local-preference 0
Désactiver une session birdc disable <protocol> neighbor X shutdown
Recharger la config birdc configure write memory puis clear ip bgp * ou redémarrage

Surveillance des événements de failover

Mettez en place une surveillance pour recevoir des alertes en cas de basculement. Surveiller les annonces BGP avec BGPalerter sur Linux couvre BGPalerter pour la surveillance des routes. Au minimum, surveillez :

  • Les changements d'état des sessions BGP : journalctl -u bird ou journalctl -u frr
  • Les flaps des sessions BFD : birdc show bfd sessions / vtysh -c "show bfd peers"
  • Les changements du nombre de routes : alertez si le nombre de préfixes exportés tombe à zéro

Dépannage

Session BGP bloquée à l'état Active/Connect :

  • Vérifiez les règles de pare-feu pour le port TCP 179
  • Vérifiez que l'IP du pair et l'ASN correspondent à ce qu'attend votre amont
  • Consultez journalctl -u bird -f ou journalctl -u frr -f pour les messages d'erreur

Session BFD bloquée à l'état Down :

  • Les ports UDP 3784 et 3785 doivent être ouverts dans les deux sens
  • Confirmez que le pair supporte BFD et l'a configuré
  • Vérifiez les problèmes de MTU sur le chemin

MED n'affecte pas le trafic entrant :

  • MED n'est comparé qu'entre les chemins du même AS. Si vos amonts sont des AS différents, utilisez l'AS-path prepending à la place
  • Certains amonts ignorent MED par politique. Demandez à votre fournisseur

La communauté de l'arrêt gracieux n'est pas honorée :

  • Le pair doit explicitement supporter la RFC 8326. Tous les amonts ne le font pas
  • Vérifiez auprès de votre fournisseur s'il honore la communauté GRACEFUL_SHUTDOWN
  • Certaines implémentations nécessitent une configuration explicite pour respecter la communauté

Le trafic ne bascule pas :

  • Vérifiez que les deux nœuds annoncent le même préfixe avec birdc show route export upstream_v4 ou vtysh -c "show ip bgp neighbors X advertised-routes"
  • Vérifiez depuis un looking glass externe, pas depuis les nœuds eux-mêmes
  • Le TTL DNS peut maintenir les clients dirigés vers l'ancienne IP si vous utilisez des IP par emplacement pour les services au-dessus du préfixe anycast