Configurer une session BGP avec FRRouting sur Debian et Ubuntu

Installer FRRouting sur Debian ou Ubuntu, monter une session eBGP avec un transitaire, annoncer votre préfixe IPv4 et IPv6, filtrer ce que vous envoyez et recevez, puis sécuriser la session : le tutoriel pas à pas, avec une configuration complète.

EXAGROUP Publié le 12 min de lecture

Annoncer ses propres adresses IP sur Internet n'est plus réservé aux grands opérateurs. Un serveur Linux et FRRouting (FRR), la suite de routage libre issue de Quagga, suffisent pour monter une session BGP avec un transitaire. Chez EXAGROUP, opérateur du réseau AS202827, c'est un outil que nous utilisons au quotidien. Ce tutoriel montre comment configurer une session eBGP propre sur Debian ou Ubuntu : annonce d'un préfixe IPv4 et IPv6, filtres en entrée et en sortie, vérifications et bonnes pratiques de sécurité.

L'essentiel en 30 secondes

  • Objectif : annoncer votre préfixe à un transitaire et recevoir ses routes, avec une session eBGP par famille d'adresses (IPv4 et IPv6).
  • Règle d'or : filtrez toujours ce que vous annoncez (seulement vos préfixes) et ce que vous recevez (pas de bogons, pas vos propres préfixes, pas de préfixes trop spécifiques).
  • Depuis FRR 7.4, une session eBGP sans route-map en entrée et en sortie n'échange aucune route (RFC 8212) : c'est voulu, et c'est une protection.
  • En production : ROA publiée pour vos préfixes, validation RPKI, limite de préfixes, et si possible GTSM ou mot de passe TCP-MD5.

Ce qu'il vous faut avant de commencer

  • Un numéro d'AS (ASN) attribué par un registre régional (le RIPE NCC en Europe), en général via un LIR sponsor.
  • Un préfixe à annoncer : au moins un /24 en IPv4 et un /48 en IPv6. Les préfixes plus spécifiques sont filtrés par la plupart des réseaux.
  • Des objets IRR à jour : un objet route (IPv4) et un objet route6 (IPv6) dans la base du RIPE, avec votre AS comme origine. Beaucoup de transitaires construisent leurs filtres à partir de ces objets.
  • Les paramètres de session fournis par votre transitaire : son AS, les adresses IP du lien d'interconnexion, le mot de passe éventuel, et ce qu'il vous envoie (table complète, route par défaut ou routes partielles).
  • Un serveur Debian 12 ou Ubuntu 24.04 (ou plus récent), avec un accès root, l'interface d'interconnexion déjà configurée et une console de secours : une erreur de filtrage peut vous couper du réseau.

Le plan d'adressage de l'exemple

Toutes les adresses et tous les numéros d'AS de ce tutoriel sont réservés à la documentation (RFC 5737, RFC 3849 et RFC 5398). Remplacez-les par vos valeurs.

ÉlémentValeur d'exemple
Votre AS64500
AS du transitaire64496
Votre préfixe IPv4203.0.113.0/24
Votre préfixe IPv62001:db8:1000::/48
Lien d'interconnexion IPv4198.51.100.0/30 : transitaire 198.51.100.1, vous 198.51.100.2
Lien d'interconnexion IPv62001:db8:ffff::/64 : transitaire 2001:db8:ffff::1, vous 2001:db8:ffff::2

Étape 1 : installer FRRouting

Debian et Ubuntu proposent un paquet frr, mais il est souvent en retard de plusieurs versions. Le dépôt officiel du projet fournit les versions stables récentes :

sudo apt install curl gnupg lsb-release
curl -s https://deb.frrouting.org/frr/keys.gpg | sudo tee /usr/share/keyrings/frrouting.gpg > /dev/null
echo deb '[signed-by=/usr/share/keyrings/frrouting.gpg]' https://deb.frrouting.org/frr \
     $(lsb_release -s -c) frr-stable | sudo tee /etc/apt/sources.list.d/frr.list
sudo apt update && sudo apt install frr frr-pythontools

Le paquet frr-pythontools fournit frr-reload.py, qui permet d'appliquer une nouvelle configuration sans redémarrer les sessions. Pour figer une branche (par exemple frr-10) plutôt que de suivre la dernière stable, remplacez frr-stable dans la ligne du dépôt.

Étape 2 : activer le démon BGP

Par défaut, seuls les démons de base (zebra, staticd…) sont lancés. Activez bgpd dans /etc/frr/daemons :

sudo sed -i 's/^bgpd=no/bgpd=yes/' /etc/frr/daemons
sudo systemctl restart frr
sudo vtysh -c "show version"

Si votre serveur doit aussi router du trafic vers d'autres machines (et pas seulement annoncer un préfixe qu'il héberge), activez le routage IP dans le noyau :

printf 'net.ipv4.ip_forward=1\nnet.ipv6.conf.all.forwarding=1\n' | sudo tee /etc/sysctl.d/90-routage.conf
sudo sysctl --system

Étape 3 : écrire les filtres

On définit les filtres avant la session, pour qu'elle n'échange jamais de routes non filtrées. Toute la configuration qui suit va dans /etc/frr/frr.conf. Vous pouvez aussi la saisir dans vtysh, après configure terminal.

Ce que vous annoncez : vos préfixes, et rien d'autre

ip prefix-list PL-OUT-V4 seq 10 permit 203.0.113.0/24
ipv6 prefix-list PL-OUT-V6 seq 10 permit 2001:db8:1000::/48
!
route-map RM-TRANSIT-OUT-V4 permit 10
 match ip address prefix-list PL-OUT-V4
exit
!
route-map RM-TRANSIT-OUT-V6 permit 10
 match ipv6 address prefix-list PL-OUT-V6
exit

Une route-map se termine par un refus implicite : tout ce qui ne correspond à aucune entrée permit est rejeté. Si vous recevez un jour les routes d'un second transitaire ou de clients, elles ne repartiront pas par erreur vers le premier : c'est ainsi qu'on évite de devenir un transit involontaire (une « fuite de routes »).

Ce que vous acceptez : pas de bogons, pas vos propres préfixes

En entrée, rejetez les plages réservées ou privées (les « bogons »), vos propres préfixes (personne d'autre ne doit vous les annoncer) et les préfixes trop spécifiques :

ip prefix-list PL-BOGONS-V4 seq 10 permit 0.0.0.0/8 le 32
ip prefix-list PL-BOGONS-V4 seq 20 permit 10.0.0.0/8 le 32
ip prefix-list PL-BOGONS-V4 seq 30 permit 100.64.0.0/10 le 32
ip prefix-list PL-BOGONS-V4 seq 40 permit 127.0.0.0/8 le 32
ip prefix-list PL-BOGONS-V4 seq 50 permit 169.254.0.0/16 le 32
ip prefix-list PL-BOGONS-V4 seq 60 permit 172.16.0.0/12 le 32
ip prefix-list PL-BOGONS-V4 seq 70 permit 192.0.0.0/24 le 32
ip prefix-list PL-BOGONS-V4 seq 80 permit 192.0.2.0/24 le 32
ip prefix-list PL-BOGONS-V4 seq 90 permit 192.168.0.0/16 le 32
ip prefix-list PL-BOGONS-V4 seq 100 permit 198.18.0.0/15 le 32
ip prefix-list PL-BOGONS-V4 seq 110 permit 198.51.100.0/24 le 32
ip prefix-list PL-BOGONS-V4 seq 120 permit 203.0.113.0/24 le 32
ip prefix-list PL-BOGONS-V4 seq 130 permit 224.0.0.0/4 le 32
ip prefix-list PL-BOGONS-V4 seq 140 permit 240.0.0.0/4 le 32
!
ip prefix-list PL-OWN-V4 seq 10 permit 203.0.113.0/24 le 32
ip prefix-list PL-ACCEPT-V4 seq 10 permit 0.0.0.0/0 le 24
!
ipv6 prefix-list PL-BOGONS-V6 seq 10 permit ::/8 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 20 permit 100::/64 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 30 permit 2001:2::/48 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 40 permit 2001:10::/28 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 50 permit 2001:db8::/32 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 60 permit 2002::/16 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 70 permit 3ffe::/16 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 80 permit fc00::/7 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 90 permit fe80::/10 le 128
ipv6 prefix-list PL-BOGONS-V6 seq 100 permit ff00::/8 le 128
!
ipv6 prefix-list PL-OWN-V6 seq 10 permit 2001:db8:1000::/48 le 128
ipv6 prefix-list PL-ACCEPT-V6 seq 10 permit 2000::/3 le 48
!
route-map RM-TRANSIT-IN-V4 deny 10
 match ip address prefix-list PL-BOGONS-V4
exit
route-map RM-TRANSIT-IN-V4 deny 20
 match ip address prefix-list PL-OWN-V4
exit
route-map RM-TRANSIT-IN-V4 permit 100
 match ip address prefix-list PL-ACCEPT-V4
exit
!
route-map RM-TRANSIT-IN-V6 deny 10
 match ipv6 address prefix-list PL-BOGONS-V6
exit
route-map RM-TRANSIT-IN-V6 deny 20
 match ipv6 address prefix-list PL-OWN-V6
exit
route-map RM-TRANSIT-IN-V6 permit 100
 match ipv6 address prefix-list PL-ACCEPT-V6
exit

Quelques précisions :

  • Dans une prefix-list, le 32 signifie « ce préfixe et tous ses sous-préfixes jusqu'au /32 ». Ici, permit veut dire « correspond » : c'est la route-map qui décide ensuite de refuser (deny) ou d'accepter.
  • PL-ACCEPT-V4 accepte tout jusqu'au /24, y compris une route par défaut si le transitaire en envoie une ; PL-ACCEPT-V6 limite l'IPv6 à l'espace global (2000::/3) jusqu'au /48.
  • Les plages de documentation figurent dans la liste des bogons : dans ce tutoriel, elles jouent le rôle de vos vraies adresses, ce qui ne pose aucun problème en entrée.
  • Ces listes ne sont pas exhaustives et évoluent : comparez-les régulièrement aux registres de l'IANA ou aux listes de bogons maintenues par la communauté.

Étape 4 : configurer la session BGP

Pour qu'un préfixe soit annoncé avec network, FRR exige qu'il existe dans la table de routage du serveur (comportement par défaut depuis FRR 7.4). Si vos adresses sont réparties sur plusieurs interfaces, ajoutez une route « blackhole » pour l'agrégat : les sous-réseaux plus spécifiques, réellement configurés sur vos interfaces, restent prioritaires.

ip route 203.0.113.0/24 blackhole
ipv6 route 2001:db8:1000::/48 blackhole
!
router bgp 64500
 bgp router-id 198.51.100.2
 bgp log-neighbor-changes
 no bgp default ipv4-unicast
 neighbor 198.51.100.1 remote-as 64496
 neighbor 198.51.100.1 description Transit-A-v4
 neighbor 2001:db8:ffff::1 remote-as 64496
 neighbor 2001:db8:ffff::1 description Transit-A-v6
 !
 address-family ipv4 unicast
  network 203.0.113.0/24
  neighbor 198.51.100.1 activate
  neighbor 198.51.100.1 soft-reconfiguration inbound
  neighbor 198.51.100.1 route-map RM-TRANSIT-IN-V4 in
  neighbor 198.51.100.1 route-map RM-TRANSIT-OUT-V4 out
  neighbor 198.51.100.1 maximum-prefix 1200000 90
 exit-address-family
 !
 address-family ipv6 unicast
  network 2001:db8:1000::/48
  neighbor 2001:db8:ffff::1 activate
  neighbor 2001:db8:ffff::1 soft-reconfiguration inbound
  neighbor 2001:db8:ffff::1 route-map RM-TRANSIT-IN-V6 in
  neighbor 2001:db8:ffff::1 route-map RM-TRANSIT-OUT-V6 out
  neighbor 2001:db8:ffff::1 maximum-prefix 300000 90
 exit-address-family
exit

Ce qu'il faut retenir de ce bloc :

  • no bgp default ipv4-unicast : aucune famille d'adresses n'est activée implicitement. Chaque voisin est activé explicitement (activate) dans sa famille : la session IPv4 ne transporte que de l'IPv4, la session IPv6 que de l'IPv6.
  • soft-reconfiguration inbound conserve une copie des routes reçues avant filtrage. Pratique pour déboguer et pour réappliquer une politique sans couper la session, mais cela augmente la consommation de mémoire avec une table complète. Retirez-la si la RAM est comptée.
  • maximum-prefix 1200000 90 coupe la session au-delà de 1 200 000 préfixes et prévient dans les journaux à 90 %. Ajustez ces valeurs à ce que vous envoie réellement votre transitaire, avec une marge : une table complète, une route par défaut seule ou quelques routes partielles n'appellent pas la même limite.

Vérifiez la syntaxe du fichier, puis appliquez-le sans redémarrer FRR :

sudo vtysh -C -f /etc/frr/frr.conf
sudo systemctl reload frr

Si vous configurez dans vtysh, n'oubliez pas write memory pour enregistrer la configuration dans /etc/frr/frr.conf.

Étape 5 : vérifier la session

Commencez par la vue d'ensemble :

sudo vtysh -c "show bgp summary"

Pour chaque voisin, la colonne Up/Down donne la durée depuis le dernier changement d'état, State/PfxRcd le nombre de préfixes acceptés (ou l'état de la session si elle n'est pas établie : Idle, Connect, Active…) et PfxSnt le nombre de préfixes envoyés. Ici, PfxSnt doit valoir 1 sur chaque session.

Ensuite, dans vtysh :

show bgp ipv4 unicast neighbors 198.51.100.1
show bgp ipv4 unicast neighbors 198.51.100.1 advertised-routes
show bgp ipv4 unicast neighbors 198.51.100.1 received-routes
show bgp ipv4 unicast neighbors 198.51.100.1 routes
show bgp ipv4 unicast 203.0.113.0/24
show ip route bgp
  • La première commande doit afficher BGP state = Established.
  • advertised-routes ne doit lister que votre préfixe. Si autre chose apparaît, votre filtre de sortie est faux : corrigez-le immédiatement.
  • received-routes (disponible grâce à soft-reconfiguration inbound) montre tout ce que le transitaire envoie ; routes montre ce que vous avez accepté après filtrage.
  • Remplacez ipv4 par ipv6 et l'adresse du voisin pour contrôler la session IPv6.

Après une modification de route-map, réappliquez les politiques sans couper la session :

clear bgp ipv4 unicast 198.51.100.1 soft in
clear bgp ipv4 unicast 198.51.100.1 soft out

Enfin, contrôlez la propagation depuis l'extérieur : un looking glass public, RIPEstat ou bgp.tools doivent voir votre préfixe avec votre AS comme origine, quelques minutes après l'établissement de la session.

Sécuriser la session : les bonnes pratiques

Publier une ROA et valider le RPKI

Le RPKI permet de prouver quel AS a le droit d'annoncer un préfixe. Commencez par créer une ROA pour chacun de vos préfixes dans l'interface de votre registre (le tableau de bord RPKI du RIPE NCC, par exemple) : AS d'origine, préfixe et longueur maximale. Fixez la longueur maximale à la taille réellement annoncée (/24, /48) plutôt que de l'élargir « au cas où » : une ROA trop permissive facilite le détournement de sous-préfixes.

Validez ensuite vous-même les routes reçues. Il vous faut un validateur RPKI (Routinator, rpki-client avec StayRTR, Fort…) qui expose le protocole RTR, puis le module RPKI de FRR :

sudo apt install frr-rpki-rtrlib
sudo sed -i 's/^bgpd_options="   -A 127.0.0.1"/bgpd_options="   -A 127.0.0.1 -M rpki"/' /etc/frr/daemons
sudo systemctl restart frr

Vérifiez que la ligne bgpd_options contient bien -M rpki (son format exact peut varier). Déclarez ensuite le cache RTR et rejetez les routes invalides, en tête des route-maps d'entrée :

rpki
 rpki cache tcp 127.0.0.1 3323 preference 1
exit
!
route-map RM-TRANSIT-IN-V4 deny 5
 match rpki invalid
exit
route-map RM-TRANSIT-IN-V6 deny 5
 match rpki invalid
exit

Le mot-clé tcp est requis à partir de FRR 10.1. Avec FRR 8.x, 9.x ou 10.0, écrivez rpki cache 127.0.0.1 3323 preference 1. Le port 3323 est celui de Routinator par défaut ; adaptez-le à votre validateur. Contrôlez ensuite la connexion et les données reçues :

show rpki cache-connection
show rpki prefix-table

Limiter le nombre de préfixes

La limite maximum-prefix vue plus haut vous protège d'une fuite chez votre transitaire (qui vous enverrait d'un coup des centaines de milliers de routes inattendues) ou d'une erreur de filtre. Sur une session qui ne doit recevoir qu'une route par défaut, une limite à quelques unités est parfaitement raisonnable.

GTSM et mot de passe TCP-MD5 (optionnels)

Ces deux protections se configurent dans le bloc router bgp et doivent être activées des deux côtés : convenez-en avec votre transitaire avant de les mettre en place.

router bgp 64500
 neighbor 198.51.100.1 ttl-security hops 1
 neighbor 198.51.100.1 password MotDePasseConvenuAvecLeTransitaire
exit
  • GTSM (RFC 5082) n'accepte que les paquets BGP venus d'un voisin directement connecté : un attaquant situé plusieurs sauts plus loin ne peut pas atteindre la session. Cette option est incompatible avec ebgp-multihop.
  • TCP-MD5 (RFC 2385) signe chaque segment TCP de la session avec un secret partagé. Un mot de passe différent de chaque côté empêche simplement la session de s'établir.

Filtrer le port 179

Seul votre transitaire doit pouvoir joindre le port TCP 179 de votre routeur. Avec UFW, par exemple (autorisez votre accès SSH avant d'activer le pare-feu) :

sudo ufw allow from 198.51.100.1 to any port 179 proto tcp
sudo ufw allow from 2001:db8:ffff::1 to any port 179 proto tcp

Les erreurs les plus fréquentes

  • (Policy) dans show bgp summary : la session est établie, mais aucune route-map n'est appliquée en entrée ou en sortie. FRR applique la RFC 8212 et n'échange rien. Ajoutez les route-maps plutôt que de désactiver la protection avec no bgp ebgp-requires-policy.
  • PfxSnt à 0 : le préfixe déclaré avec network n'existe pas dans la table de routage. Vérifiez la route blackhole avec show ip route 203.0.113.0/24, puis votre filtre de sortie.
  • Session bloquée en Active ou Connect : adresse ou numéro d'AS erroné, port 179 filtré, mot de passe MD5 différent, ou GTSM activé d'un seul côté. Consultez les journaux avec journalctl -u frr.
  • Session établie mais préfixe invisible sur Internet : objet route ou route6 absent, ROA manquante ou invalide, ou préfixe plus spécifique qu'un /24 ou un /48. Le filtrage se fait souvent en amont, chez le transitaire ou ses propres transitaires.

Héberger votre routeur chez EXAGROUP

EXAGROUP exploite son propre réseau, AS202827. Si vous voulez annoncer vos préfixes avec votre ASN sans gérer de lien physique, notre tunnel BGP/GRE commence à 1,67 €/mois. Pour faire tourner FRRouting sur votre propre matériel, le housing accueille vos serveurs et routeurs dans notre datacenter ; si vous préférez louer la machine, voyez nos serveurs dédiés (et notre comparatif housing ou serveur dédié).

Un projet d'annonce BGP ou une question sur votre configuration ? Écrivez-nous, nous vous répondrons par ticket.

Questions fréquentes

Faut-il un numéro d'AS pour monter une session BGP ?

Pour annoncer vos propres préfixes en votre nom, oui : il vous faut un ASN attribué par un registre régional (le RIPE NCC en Europe), en général par l'intermédiaire d'un LIR sponsor. Votre transitaire vous fournit de son côté son numéro d'AS et les adresses du lien d'interconnexion.

Quelle est la plus petite taille de préfixe que l'on peut annoncer ?

En pratique, un /24 en IPv4 et un /48 en IPv6. Les préfixes plus spécifiques sont filtrés par la plupart des réseaux et ne seraient donc pas visibles sur tout Internet.

Que signifie « (Policy) » dans show bgp summary avec FRRouting ?

La session est établie, mais aucune route-map n'est appliquée en entrée ou en sortie. Depuis la version 7.4, FRR applique la RFC 8212 avec les réglages par défaut : une session eBGP sans politique n'échange aucune route. Appliquez une route-map en entrée et en sortie pour chaque voisin plutôt que de désactiver la protection.

Le RPKI est-il obligatoire pour annoncer un préfixe ?

Non, mais il est fortement recommandé. De nombreux opérateurs rejettent les annonces dont la validation RPKI est invalide : créez une ROA pour chacun de vos préfixes, avec la bonne origine et une longueur maximale égale à la taille annoncée, et validez vous-même les routes reçues avec un validateur RPKI et le module RPKI de FRR.