BGP Route Filtering : Prefix Lists, Filtres AS-Path, Rejet des Bogons et GTSM
Référence pratique pour durcir les sessions BGP sur Linux avec des filtres en couches. Couvre les prefix-lists, le rejet des bogons, les filtres AS-path, les limites max-prefix et le GTSM en syntaxe BIRD2 et FRR avec étapes de vérification.
RPKI valide qu'un AS est autorisé à originer un préfixe. Il ne protège pas contre les fuites de routes (route leaks), l'injection de bogons, l'explosion de table depuis un pair mal configuré, ou les paquets BGP usurpés depuis des hôtes non adjacents. Cet article couvre les filtres qui gèrent tout ce que RPKI ne couvre pas.
Chaque filtre est présenté en syntaxe BIRD2 et FRR, avec des exemples IPv4 et IPv6. Chaque section explique ce que le filtre empêche, donne la configuration, puis montre comment vérifier qu'il fonctionne.
Si vous n'avez pas encore configuré la validation d'origine RPKI, faites-le d'abord. Voir RPKI ROA pour BGP : créer des ROAs, valider les routes dans BIRD2 et FRR.
Pour la configuration de base d'une session BGP, voir Configuration BGP avec BIRD2 sur un VPS Linux (BIRD2) ou Configuration BGP avec FRRouting sur un VPS Linux (FRR). Cet article suppose que vous avez déjà une session BGP fonctionnelle et que vous souhaitez la durcir.
Pourquoi BGP a-t-il besoin de filtrage de routes au-delà de RPKI ?
Le filtrage de routes BGP consiste à accepter ou rejeter des annonces BGP en fonction du préfixe, de l'AS-path ou des attributs d'origine. Il prévient les fuites de routes, les détournements de préfixes (prefix hijacks), l'injection de bogons et l'explosion de la table de routage. RPKI couvre uniquement la validation d'origine. Sans filtres supplémentaires, votre routeur est exposé à toutes les autres catégories d'incidents BGP.
Voici ce que chaque couche empêche :
| Type de filtre | Menace bloquée | Ce qui se passe sans lui |
|---|---|---|
| Rejet de préfixes bogons | Espace privé/réservé dans le DFZ | Votre routeur achemine le trafic vers l'espace RFC 1918. Black hole. |
| Rejet de petits préfixes | Détournements plus-spécifiques (/25+, /49+) | Un attaquant annonce un /32 couvrant une partie d'un /24 que vous acceptez. Sa route gagne par longest match. |
| Filtrage bogon AS-path | ASNs privés/réservés dans les chemins | Des routes avec AS 65535 ou AS 4200000000 s'infiltrent dans votre table. Vous acheminez du trafic basé sur des chemins invalides. |
| Limite de longueur AS-path | Attaques par inflation de chemin, gonflement de table | Un pair envoie des routes avec 50+ sauts AS. Votre mémoire se remplit d'entrées inutiles. |
| Limite max-prefix | Fuites de routes, surcharge de session | Un pair laisse fuiter une table complète (1M+ préfixes) dans votre session. Votre routeur manque de mémoire. |
| GTSM (sécurité TTL) | Paquets BGP usurpés depuis des hôtes distants | Un attaquant à plusieurs sauts de distance injecte des paquets BGP OPEN ou UPDATE dans votre session. |
| Validation d'origine RPKI | Détournements d'origine | Quelqu'un origine votre préfixe depuis son AS. Déjà couvert dans RPKI ROA pour BGP : créer des ROAs, valider les routes dans BIRD2 et FRR. |
Des incidents réels montrent pourquoi chaque couche compte. En 2008, Pakistan Telecom a annoncé des routes plus-spécifiques pour les préfixes de YouTube afin d'appliquer un ordre de censure domestique. Ces routes ont fuité vers des fournisseurs de transit internationaux et ont mis YouTube en black hole globalement pendant des heures. Un filtre bogon ou petits-préfixes chez les fournisseurs de transit aurait écarté ces annonces. En juin 2019, un petit FAI en Pennsylvanie (AS396531) a accidentellement fait fuiter des routes pour Cloudflare, Amazon et Linode vers Verizon, qui les a propagées globalement. Une limite max-prefix aurait terminé la session avant que la fuite ne se propage.
Comment filtrer les préfixes bogons dans BIRD2 et FRR ?
Les préfixes bogons sont des plages d'adresses qui ne doivent jamais apparaître dans la table de routage globale. Ils incluent l'espace privé RFC 1918, les adresses link-local, les plages de documentation et les blocs réservés. Les accepter signifie que votre routeur va tenter d'acheminer du trafic vers des adresses qui n'ont pas de destination globale légitime, créant des black holes.
Préfixes bogons IPv4
| Préfixe | Référence | Objet |
|---|---|---|
| 0.0.0.0/8 | RFC 1122 | Réseau « This » |
| 10.0.0.0/8 | RFC 1918 | Espace privé |
| 100.64.0.0/10 | RFC 6598 | NAT de niveau opérateur |
| 127.0.0.0/8 | RFC 1122 | Loopback |
| 169.254.0.0/16 | RFC 3927 | Link-local |
| 172.16.0.0/12 | RFC 1918 | Espace privé |
| 192.0.2.0/24 | RFC 5737 | TEST-NET-1 |
| 192.88.99.0/24 | RFC 7526 | Relais 6to4 déprécié |
| 192.168.0.0/16 | RFC 1918 | Espace privé |
| 198.18.0.0/15 | RFC 2544 | Benchmarking |
| 198.51.100.0/24 | RFC 5737 | TEST-NET-2 |
| 203.0.113.0/24 | RFC 5737 | TEST-NET-3 |
| 224.0.0.0/4 | RFC 5771 | Multicast |
| 240.0.0.0/4 | RFC 1112 | Réservé pour usage futur |
Préfixes bogons IPv6
| Préfixe | Référence | Objet |
|---|---|---|
| ::/8 | Divers | Compatible IPv4, loopback, mappé |
| 100::/64 | RFC 6666 | Discard-only |
| 2001:2::/48 | RFC 5180 | Benchmarking BMWG |
| 2001:10::/28 | RFC 4843 | ORCHID |
| 2001:db8::/32 | RFC 3849 | Documentation |
| 3fff::/20 | RFC 9637 | Documentation |
| 2002::/16 | RFC 7526 | 6to4 déprécié |
| 3ffe::/16 | RFC 3701 | Ancien 6bone |
| 5f00::/16 | RFC 9602 | SRv6 SIDs |
| fc00::/7 | RFC 4193 | Unicast local unique |
| fe80::/10 | RFC 4291 | Unicast link-local |
| fec0::/10 | RFC 3879 | Site-local déprécié |
| ff00::/8 | RFC 4291 | Multicast |
Ces listes changent quand l'IANA alloue de nouveaux blocs ou déprécie d'anciens. La référence bogon de Team Cymru fournit un flux BGP de fullbogons (espace non alloué + réservé) qui se met à jour automatiquement. Pour les listes statiques, consultez le NLNOG BGP Filter Guide périodiquement.
Filtre bogon BIRD2
# /etc/bird/bogons.conf - include this from your main bird.conf
define BOGON_PREFIXES_V4 = [
0.0.0.0/8+,
10.0.0.0/8+,
100.64.0.0/10+,
127.0.0.0/8+,
169.254.0.0/16+,
172.16.0.0/12+,
192.0.2.0/24+,
192.88.99.0/24+,
192.168.0.0/16+,
198.18.0.0/15+,
198.51.100.0/24+,
203.0.113.0/24+,
224.0.0.0/4+,
240.0.0.0/4+
];
define BOGON_PREFIXES_V6 = [
::/8+,
0100::/64+,
2001:2::/48+,
2001:10::/28+,
2001:db8::/32+,
3fff::/20+,
2002::/16+,
3ffe::/16+,
5f00::/16+,
fc00::/7+,
fe80::/10+,
fec0::/10+,
ff00::/8+
];
function reject_bogon_prefixes_v4() {
if (net ~ BOGON_PREFIXES_V4) then {
print "REJECTED bogon prefix: ", net, " path: ", bgp_path;
reject;
}
}
function reject_bogon_prefixes_v6() {
if (net ~ BOGON_PREFIXES_V6) then {
print "REJECTED bogon prefix: ", net, " path: ", bgp_path;
reject;
}
}
Le + après chaque préfixe signifie « ce préfixe et tous ses plus-spécifiques ». 10.0.0.0/8+ correspond à 10.0.0.0/8, 10.0.0.0/9, 10.1.0.0/16, etc. Cela attrape un attaquant annonçant un /24 dans l'espace RFC 1918.
Appelez ces fonctions dans votre filtre d'import :
filter import_from_upstream_v4 {
reject_bogon_prefixes_v4();
# ... other filters ...
accept;
}
protocol bgp upstream_v4 {
local as 64500;
neighbor 198.51.100.1 as 64501;
ipv4 {
import filter import_from_upstream_v4;
export none;
};
}
Filtre bogon FRR
! IPv4 bogon prefix-list
ip prefix-list BOGONS_v4 seq 10 deny 0.0.0.0/8 le 32
ip prefix-list BOGONS_v4 seq 20 deny 10.0.0.0/8 le 32
ip prefix-list BOGONS_v4 seq 30 deny 100.64.0.0/10 le 32
ip prefix-list BOGONS_v4 seq 40 deny 127.0.0.0/8 le 32
ip prefix-list BOGONS_v4 seq 50 deny 169.254.0.0/16 le 32
ip prefix-list BOGONS_v4 seq 60 deny 172.16.0.0/12 le 32
ip prefix-list BOGONS_v4 seq 70 deny 192.0.2.0/24 le 32
ip prefix-list BOGONS_v4 seq 80 deny 192.88.99.0/24 le 32
ip prefix-list BOGONS_v4 seq 90 deny 192.168.0.0/16 le 32
ip prefix-list BOGONS_v4 seq 100 deny 198.18.0.0/15 le 32
ip prefix-list BOGONS_v4 seq 110 deny 198.51.100.0/24 le 32
ip prefix-list BOGONS_v4 seq 120 deny 203.0.113.0/24 le 32
ip prefix-list BOGONS_v4 seq 130 deny 224.0.0.0/4 le 32
ip prefix-list BOGONS_v4 seq 140 deny 240.0.0.0/4 le 32
ip prefix-list BOGONS_v4 seq 999 permit 0.0.0.0/0 le 32
! IPv6 bogon prefix-list
ipv6 prefix-list BOGONS_v6 seq 10 deny ::/8 le 128
ipv6 prefix-list BOGONS_v6 seq 20 deny 100::/64 le 128
ipv6 prefix-list BOGONS_v6 seq 30 deny 2001:2::/48 le 128
ipv6 prefix-list BOGONS_v6 seq 40 deny 2001:10::/28 le 128
ipv6 prefix-list BOGONS_v6 seq 50 deny 2001:db8::/32 le 128
ipv6 prefix-list BOGONS_v6 seq 60 deny 3fff::/20 le 128
ipv6 prefix-list BOGONS_v6 seq 70 deny 2002::/16 le 128
ipv6 prefix-list BOGONS_v6 seq 80 deny 3ffe::/16 le 128
ipv6 prefix-list BOGONS_v6 seq 90 deny 5f00::/16 le 128
ipv6 prefix-list BOGONS_v6 seq 100 deny fc00::/7 le 128
ipv6 prefix-list BOGONS_v6 seq 110 deny fe80::/10 le 128
ipv6 prefix-list BOGONS_v6 seq 120 deny fec0::/10 le 128
ipv6 prefix-list BOGONS_v6 seq 130 deny ff00::/8 le 128
ipv6 prefix-list BOGONS_v6 seq 999 permit ::/0 le 128
Les clauses le 32 (IPv4) et le 128 (IPv6) correspondent au préfixe et à tous ses plus-spécifiques, comme l'opérateur + dans BIRD2. La dernière ligne permit à seq 999 autorise tout ce qui n'a pas été refusé.
Appliquez la prefix-list à votre voisin :
router bgp 64500
neighbor 198.51.100.1 remote-as 64501
address-family ipv4 unicast
neighbor 198.51.100.1 prefix-list BOGONS_v4 in
address-family ipv6 unicast
neighbor 2001:db8::1 prefix-list BOGONS_v6 in
Attention. Cette entrée 2001:db8::/32 est dans la liste bogon. N'utilisez pas des adresses de documentation en production. Remplacez les adresses de voisin ci-dessus par vos vraies IPs de pairs.
Rejet des préfixes trop petits
Les routes plus petites que /24 (IPv4) ou /48 (IPv6) ne se propagent pas de façon fiable dans le DFZ global. Plus important, les accepter vous expose à des attaques par détournement plus-spécifique. Filtrez-les en entrée.
BIRD2 :
function reject_small_prefixes_v4() {
if (net.len > 24) then {
print "REJECTED too-small prefix: ", net, " path: ", bgp_path;
reject;
}
}
function reject_small_prefixes_v6() {
if (net.len > 48) then {
print "REJECTED too-small prefix: ", net, " path: ", bgp_path;
reject;
}
}
FRR :
! Add to the same prefix-lists, before the final permit
ip prefix-list BOGONS_v4 seq 150 deny 0.0.0.0/0 ge 25 le 32
ipv6 prefix-list BOGONS_v6 seq 140 deny ::/0 ge 49 le 128
Cela attrape tout préfixe plus spécifique que /24 (IPv4) ou /48 (IPv6). Placez ces lignes avant les entrées seq 999 permit.
Comment les filtres AS-path empêchent-ils les fuites de routes ?
Les filtres AS-path inspectent la séquence des systèmes autonomes qu'une route a traversés. Ils détectent trois problèmes : les ASNs bogons qui ne doivent jamais apparaître dans un chemin, les chemins excessivement longs qui indiquent des fuites ou des manipulations, et les ASNs privés qui n'ont pas été supprimés avant l'annonce.
Filtrage des ASNs bogons
Les ASNs bogons sont des numéros réservés qui ne doivent jamais apparaître dans un chemin BGP sur l'internet public :
| Plage ASN | Référence | Objet |
|---|---|---|
| 0 | RFC 7607 | Réservé |
| 23456 | RFC 4893 | AS_TRANS (transition AS 4 octets) |
| 64496-64511 | RFC 5398 | Documentation/exemples |
| 64512-65534 | RFC 6996 | Usage privé (16 bits) |
| 65535 | RFC 7300 | Dernier ASN 16 bits |
| 65536-65551 | RFC 5398 | Documentation/exemples (32 bits) |
| 65552-131071 | IANA | Réservé |
| 4200000000-4294967294 | RFC 6996 | Usage privé (32 bits) |
| 4294967295 | RFC 7300 | Dernier ASN 32 bits |
BIRD2 :
define BOGON_ASNS = [
0,
23456,
64496..64511,
64512..65534,
65535,
65536..65551,
65552..131071,
4200000000..4294967294,
4294967295
];
function reject_bogon_asns()
int set bogon_asns;
{
bogon_asns = BOGON_ASNS;
if (bgp_path ~ bogon_asns) then {
print "REJECTED bogon ASN in path: ", net, " path: ", bgp_path;
reject;
}
}
L'opérateur bgp_path ~ bogon_asns vérifie si un ASN du chemin est membre de l'ensemble. Un seul ASN bogon n'importe où dans le chemin déclenche le rejet.
FRR :
bgp as-path access-list BOGON_ASNS deny _0_
bgp as-path access-list BOGON_ASNS deny _23456_
bgp as-path access-list BOGON_ASNS deny _6449[6-9]_
bgp as-path access-list BOGON_ASNS deny _6450[0-9]_
bgp as-path access-list BOGON_ASNS deny _6451[01]_
bgp as-path access-list BOGON_ASNS deny _64[5-9][1-9][2-9]_
bgp as-path access-list BOGON_ASNS deny _6[5-9][0-9][0-9][0-9]_
bgp as-path access-list BOGON_ASNS deny _[1-9][0-9][0-9][0-9][0-9]_
bgp as-path access-list BOGON_ASNS deny _[1-3][0-9][0-9][0-9][0-9][0-9]_
bgp as-path access-list BOGON_ASNS permit .*
FRR utilise la correspondance regex sur la chaîne AS-path. Les underscores _ correspondent aux délimiteurs AS-path (espace, début, fin). Cette approche regex est moins précise que la correspondance par ensemble d'entiers de BIRD2. Pour une approche plus simple mais moins granulaire, utilisez une route-map avec l'as-path access-list :
route-map IMPORT_FILTER deny 10
match as-path BOGON_ASNS
route-map IMPORT_FILTER permit 100
router bgp 64500
address-family ipv4 unicast
neighbor 198.51.100.1 route-map IMPORT_FILTER in
Note : les patterns regex ci-dessus sont simplifiés. Faire correspondre la plage complète des ASNs privés 32 bits (4200000000-4294967294) avec regex est source d'erreurs. Pour les déploiements en production, utilisez bgpq4 pour générer des prefix-lists et des filtres AS-path depuis les données IRR, ce qui est plus précis et automatisable.
Limitation de la longueur AS-path
Un chemin BGP légitime dépasse rarement 10-15 ASNs. Les chemins plus longs indiquent généralement une fuite de route, une manipulation de chemin, ou un prepending mal configuré. Fixez une limite stricte.
BIRD2 :
function reject_long_paths() {
if (bgp_path.len > 25) then {
print "REJECTED long AS-path (", bgp_path.len, "): ", net, " path: ", bgp_path;
reject;
}
}
FRR :
bgp as-path access-list LONG_PATHS deny ^([0-9]+_){25,}
bgp as-path access-list LONG_PATHS permit .*
route-map IMPORT_FILTER deny 20
match as-path LONG_PATHS
Une limite de 25 est conservative. La plupart des routes légitimes ont des chemins inférieurs à 10. Si vous recevez une table complète, inspectez les chemins les plus longs dans votre RIB avant de choisir un seuil :
# BIRD2
birdc 'show route where bgp_path.len > 15' | head -20
# FRR
vtysh -c "show ip bgp regexp ^([0-9]+_){15,}"
Suppression des ASNs privés en sortie
Si vous utilisez iBGP avec des ASNs privés en interne, assurez-vous qu'ils ne fuitent pas vers vos upstreams.
BIRD2 :
filter export_to_upstream_v4 {
# Strip private ASNs before advertising
bgp_path.delete([64512..65534, 4200000000..4294967294]);
# ... your export policy ...
accept;
}
FRR :
router bgp 64500
address-family ipv4 unicast
neighbor 198.51.100.1 remove-private-AS all
Le mot-clé all supprime chaque ASN privé même lorsque des ASNs publics sont présents dans le chemin. Sans all, FRR ne supprime les ASNs privés que si le chemin entier ne contient que des ASNs privés.
Quelle est la limite max-prefix correcte pour une session BGP ?
Une limite max-prefix est une soupape de sécurité qui ferme une session BGP si un pair annonce plus de préfixes que le seuil configuré. Elle empêche l'explosion de la table de routage quand un pair laisse accidentellement fuiter une table complète ou est compromis. Sans elle, un seul pair mal configuré peut pousser votre routeur hors mémoire.
Fixez la limite en fonction de ce que vous attendez de chaque pair :
| Type de pair | Préfixes attendus (IPv4) | Limite suggérée | Limite suggérée (IPv6) |
|---|---|---|---|
| Upstream table complète | ~1 200 000 (mars 2026) | 1 500 000 | 300 000 |
| Table partielle / pair IXP | Variable | 1,5x le nombre actuel | 1,5x le nombre actuel |
| Client single-homed | 1-10 | 50 | 50 |
| Client multi-homed | 10-100 | 200 | 200 |
Vérifiez la taille actuelle de la table complète sur bgp.potaroo.net avant de fixer les limites upstream. Fixez la limite à environ 1,2x le nombre attendu pour absorber la croissance normale sans faux déclenchements.
BIRD2 :
protocol bgp upstream_v4 {
local as 64500;
neighbor 198.51.100.1 as 64501;
ipv4 {
import limit 1500000 action restart;
import filter import_from_upstream_v4;
export none;
};
}
protocol bgp customer_v4 {
local as 64500;
neighbor 203.0.113.10 as 64502;
ipv4 {
import limit 50 action disable;
import filter import_from_customer_v4;
export filter export_to_customer_v4;
};
}
BIRD2 propose trois actions quand la limite est atteinte :
action restart- ferme la session et redémarre après un délai. Idéal pour les upstreams.action disable- ferme et désactive le protocole. Nécessite unbirdc enablemanuel pour restaurer. Idéal pour les clients où atteindre la limite indique un problème sérieux.action block- stoppe l'import de nouvelles routes mais maintient la session. Utile si vous souhaitez garder les routes existantes pendant l'investigation.
FRR :
router bgp 64500
neighbor 198.51.100.1 remote-as 64501
address-family ipv4 unicast
neighbor 198.51.100.1 maximum-prefix 1500000 90 restart 5
neighbor 203.0.113.10 remote-as 64502
address-family ipv4 unicast
neighbor 203.0.113.10 maximum-prefix 50 80
Dans FRR, maximum-prefix 1500000 90 restart 5 signifie : avertir à 90% (1 350 000 préfixes), fermer à 1 500 000, et redémarrer la session après 5 minutes. Sans le mot-clé restart, FRR ferme la session et nécessite un clear bgp neighbor manuel pour la restaurer.
Vérifier la configuration max-prefix
# BIRD2 - check current prefix count and limit
birdc show protocols all upstream_v4 | grep -E "Routes|Limit"
# FRR - check prefix count per neighbor
vtysh -c "show ip bgp summary"
La sortie affiche le nombre actuel de préfixes à côté de la limite configurée. Si le nombre est proche de la limite, augmentez le seuil avant qu'elle se déclenche.
Comment GTSM protège-t-il les sessions BGP contre les paquets usurpés ?
GTSM (Generalized TTL Security Mechanism, RFC 5082) restreint les paquets BGP acceptés aux pairs directement connectés en vérifiant le champ TTL/Hop Limit. Quand il est activé, les paquets BGP sont envoyés avec TTL 255. Le récepteur rejette tout paquet BGP avec un TTL inférieur à 254 (pour un pair directement connecté). Comme les routeurs décrémentent le TTL à chaque saut, un attaquant à plus d'un saut ne peut pas envoyer des paquets qui arrivent avec TTL 255.
Cela bloque l'injection distante de TCP RST, les SYN floods ciblant le port BGP 179, et les paquets BGP OPEN/UPDATE forgés depuis des attaquants non adjacents. GTSM est mutuellement exclusif avec eBGP multihop sur la même session. Les deux pairs doivent l'activer.
BIRD2 :
protocol bgp upstream_v4 {
local as 64500;
neighbor 198.51.100.1 as 64501;
ttl security yes;
ipv4 {
import limit 1500000 action restart;
import filter import_from_upstream_v4;
export none;
};
}
FRR :
router bgp 64500
neighbor 198.51.100.1 remote-as 64501
neighbor 198.51.100.1 ttl-security hops 1
hops 1 signifie que le pair doit être exactement à 1 saut (directement connecté). Fixez cette valeur pour correspondre au nombre de sauts réels. Pour les pairs eBGP sur un fabric de commutation IXP, hops 1 est correct. Pour les sessions multihop (par exemple BGP sur un tunnel GRE), vous ne pouvez pas utiliser GTSM. Utilisez plutôt l'authentification MD5 :
Alternative MD5 BIRD2 :
protocol bgp multihop_peer {
local as 64500;
neighbor 198.51.100.5 as 64503;
multihop 2;
password "your-md5-secret";
# ...
}
Alternative MD5 FRR :
router bgp 64500
neighbor 198.51.100.5 remote-as 64503
neighbor 198.51.100.5 ebgp-multihop 2
neighbor 198.51.100.5 password your-md5-secret
Stockez le mot de passe MD5 dans un fichier avec permissions restreintes (chmod 600) plutôt que dans la configuration principale. Pour FRR, référencez-le depuis /etc/frr/frr.conf qui doit déjà être en 640 appartenant à frr:frr. Pour BIRD2, gardez /etc/bird/bird.conf en 640 appartenant à bird:bird.
Quels filtres BGP MANRS exige-t-il ?
MANRS (Mutually Agreed Norms for Routing Security) définit des actions de référence pour les opérateurs réseau. Les actions 1, 3 et 4 sont requises pour devenir participant MANRS. Voici comment les filtres de cet article correspondent aux actions MANRS.
Action 1 : Empêcher la propagation d'informations de routage incorrectes.
C'est l'action de filtrage principale. Elle exige des filtres explicites au niveau des préfixes sur les connexions clients et recommande des filtres AS-path pour prévenir les fuites de routes.
| Filtre de cet article | Couverture MANRS Action 1 |
|---|---|
| Filtrage prefix-list (bogons) | Empêche d'annoncer/accepter l'espace réservé |
| Rejet des petits préfixes | Bloque les routes plus-spécifiques qui indiquent des détournements |
| Filtrage bogon AS-path | Rejette les routes avec des ASNs privés/réservés |
| Limites max-prefix | Stoppe la propagation de tables complètes fuitées |
| Filtres de préfixes clients | Pas dans cet article. Construisez-les par client depuis IRR avec bgpq4. |
Action 2 (recommandée) : Empêcher le trafic avec des adresses source usurpées.
Ce n'est pas un filtre BGP. Il s'agit de la validation d'adresse source BCP 38/84 (uRPF). Hors du périmètre de cet article mais tout aussi important.
Action 3 : Faciliter la communication opérationnelle globale.
Maintenez vos coordonnées à jour dans PeeringDB et votre base de données RIR. Ce n'est pas un filtre, mais les opérateurs qui utilisent des filtres corrects tendent aussi à maintenir leurs informations de contact.
Action 4 : Faciliter l'information de routage à l'échelle globale.
Publiez votre politique de routage dans IRR (RIPE, RADB) avec des objets RPSL. Créez des ROAs pour RPKI. Cela permet à vos pairs de construire des filtres de préfixes précis pour vos annonces.
La combinaison filtrage bogon (préfixes + ASNs) + rejet petits préfixes + limites max-prefix + prefix-lists clients couvre l'Action 1 MANRS. Ajoutez RPKI (RPKI ROA pour BGP : créer des ROAs, valider les routes dans BIRD2 et FRR) et l'enregistrement IRR pour l'Action 4.
Tout assembler : un filtre d'import complet
Voici un filtre d'import combiné utilisant toutes les techniques ci-dessus.
Filtre d'import complet BIRD2
# /etc/bird/filters.conf
include "/etc/bird/bogons.conf"; # BOGON_PREFIXES_V4, BOGON_PREFIXES_V6, BOGON_ASNS
function import_checks_v4() {
# 1. Reject bogon prefixes
if (net ~ BOGON_PREFIXES_V4) then {
print "REJECT bogon prefix: ", net, " ", bgp_path;
reject;
}
# 2. Reject too-small prefixes
if (net.len > 24) then {
print "REJECT small prefix: ", net, " ", bgp_path;
reject;
}
# 3. Reject bogon ASNs in path
if (bgp_path ~ [0, 23456, 64496..64511, 64512..65534, 65535,
65536..65551, 65552..131071,
4200000000..4294967294, 4294967295]) then {
print "REJECT bogon ASN: ", net, " ", bgp_path;
reject;
}
# 4. Reject excessively long paths
if (bgp_path.len > 25) then {
print "REJECT long path: ", net, " ", bgp_path;
reject;
}
# 5. Reject RPKI invalid (if RPKI is configured)
if (roa_check(rpki4, net, bgp_path.last) = ROA_INVALID) then {
print "REJECT RPKI invalid: ", net, " ", bgp_path;
reject;
}
}
filter import_upstream_v4 {
import_checks_v4();
accept;
}
protocol bgp upstream_v4 {
local as 64500;
neighbor 198.51.100.1 as 64501;
ttl security yes;
ipv4 {
import limit 1500000 action restart;
import filter import_upstream_v4;
export none;
};
}
Filtre d'import complet FRR
! /etc/frr/frr.conf
! --- Prefix lists (bogons + small prefix rejection) ---
ip prefix-list IMPORT_V4 seq 10 deny 0.0.0.0/8 le 32
ip prefix-list IMPORT_V4 seq 20 deny 10.0.0.0/8 le 32
ip prefix-list IMPORT_V4 seq 30 deny 100.64.0.0/10 le 32
ip prefix-list IMPORT_V4 seq 40 deny 127.0.0.0/8 le 32
ip prefix-list IMPORT_V4 seq 50 deny 169.254.0.0/16 le 32
ip prefix-list IMPORT_V4 seq 60 deny 172.16.0.0/12 le 32
ip prefix-list IMPORT_V4 seq 70 deny 192.0.2.0/24 le 32
ip prefix-list IMPORT_V4 seq 80 deny 192.88.99.0/24 le 32
ip prefix-list IMPORT_V4 seq 90 deny 192.168.0.0/16 le 32
ip prefix-list IMPORT_V4 seq 100 deny 198.18.0.0/15 le 32
ip prefix-list IMPORT_V4 seq 110 deny 198.51.100.0/24 le 32
ip prefix-list IMPORT_V4 seq 120 deny 203.0.113.0/24 le 32
ip prefix-list IMPORT_V4 seq 130 deny 224.0.0.0/4 le 32
ip prefix-list IMPORT_V4 seq 140 deny 240.0.0.0/4 le 32
ip prefix-list IMPORT_V4 seq 150 deny 0.0.0.0/0 ge 25 le 32
ip prefix-list IMPORT_V4 seq 999 permit 0.0.0.0/0 le 32
! --- AS-path filters (bogon ASNs + path length) ---
bgp as-path access-list BOGON_ASNS deny _0_
bgp as-path access-list BOGON_ASNS deny _23456_
bgp as-path access-list BOGON_ASNS deny _6449[6-9]_
bgp as-path access-list BOGON_ASNS deny _6450[0-9]_
bgp as-path access-list BOGON_ASNS deny _6451[01]_
bgp as-path access-list BOGON_ASNS permit .*
bgp as-path access-list LONG_PATHS deny ^([0-9]+_){25,}
bgp as-path access-list LONG_PATHS permit .*
! --- Route-map combining all checks ---
route-map IMPORT_UPSTREAM deny 10
match as-path BOGON_ASNS
route-map IMPORT_UPSTREAM deny 20
match as-path LONG_PATHS
route-map IMPORT_UPSTREAM permit 100
! --- BGP neighbor configuration ---
router bgp 64500
neighbor 198.51.100.1 remote-as 64501
neighbor 198.51.100.1 ttl-security hops 1
address-family ipv4 unicast
neighbor 198.51.100.1 prefix-list IMPORT_V4 in
neighbor 198.51.100.1 route-map IMPORT_UPSTREAM in
neighbor 198.51.100.1 maximum-prefix 1500000 90 restart 5
Dans FRR, la prefix-list et la route-map sont toutes les deux évaluées. La prefix-list s'exécute en premier et rejette les préfixes bogons et les petits préfixes. Les routes qui passent la prefix-list arrivent ensuite à la route-map, qui vérifie les filtres AS-path. Les deux doivent autoriser la route pour qu'elle soit acceptée.
Comment vérifier que les filtres de routes BGP fonctionnent ?
Les filtres ne sont utiles que s'ils rejettent vraiment ce qu'ils doivent. Vérifiez après chaque modification.
Vérification BIRD2
# Check what routes were rejected (requires print statements in filters)
grep "REJECT" /var/log/bird.log | tail -20
# Show the routing table with filter details
birdc show route filtered
# Show routes from a specific protocol
birdc show route protocol upstream_v4
# Count accepted routes per protocol
birdc show protocols all upstream_v4 | grep "Routes:"
# Test a specific prefix against your import filter
birdc show route for 10.0.0.0/8 all
La commande show route filtered affiche les routes qui ont été reçues mais rejetées par le filtre d'import. Si votre filtre bogon fonctionne, vous devriez voir zéro préfixe bogon dans la table acceptée et les bogons reçus dans la table filtrée.
Vérification FRR
# Show accepted routes from a neighbor
vtysh -c "show ip bgp neighbors 198.51.100.1 received-routes"
# Show routes filtered by inbound policy
vtysh -c "show ip bgp neighbors 198.51.100.1 filtered-routes"
# Check the prefix count per neighbor
vtysh -c "show ip bgp summary"
# Test if a specific prefix is accepted
vtysh -c "show ip bgp 10.0.0.0/8"
# Check max-prefix status
vtysh -c "show ip bgp neighbors 198.51.100.1" | grep -A2 "Maximum prefix"
Pour que received-routes et filtered-routes fonctionnent, vous devez activer la soft-reconfiguration inbound sur le voisin :
router bgp 64500
address-family ipv4 unicast
neighbor 198.51.100.1 soft-reconfiguration inbound
Cela utilise de la mémoire supplémentaire (stocke toutes les routes reçues avant filtrage). Sur une session table complète, c'est environ 2x la mémoire pour le RIB. Sur des routeurs en production avec peu de RAM, utilisez-le sélectivement.
Vérification externe
Vos filtres protègent votre propre RIB. Pour vérifier ce que vous annoncez aux autres, utilisez des looking glasses externes :
- bgp.tools - recherchez votre ASN pour voir quels préfixes vous annoncez globalement
- RIPE RIS - service d'information de routage BGP, affiche la visibilité des routes sur les collecteurs
- Hurricane Electric BGP Toolkit - recherche de préfixes et d'ASN
Vérifiez après des changements de filtres pour confirmer que vous ne filtrez pas accidentellement des routes légitimes ou que vous ne fuitez pas des routes que vous ne devriez pas annoncer.
Pour la surveillance automatisée, voir Surveiller les annonces BGP avec BGPalerter sur Linux.
Comparaison de syntaxe BIRD2 vs FRR
Référence rapide pour passer d'un daemon à l'autre :
| Type de filtre | BIRD2 | FRR |
|---|---|---|
| Préfixe bogon | if (net ~ BOGON_PREFIXES) then reject |
ip prefix-list BOGONS deny 10.0.0.0/8 le 32 |
| Petit préfixe | if (net.len > 24) then reject |
ip prefix-list X deny 0.0.0.0/0 ge 25 le 32 |
| ASN bogon | if (bgp_path ~ [64512..65534]) then reject |
bgp as-path access-list X deny _64[5-9][1-9][2-9]_ |
| Longueur de chemin | if (bgp_path.len > 25) then reject |
bgp as-path access-list X deny ^([0-9]+_){25,} |
| Max-prefix | import limit 50 action disable |
neighbor X maximum-prefix 50 |
| GTSM | ttl security yes |
neighbor X ttl-security hops 1 |
| Auth MD5 | password "secret" |
neighbor X password secret |
| Suppression AS privé | bgp_path.delete([64512..65534]) |
neighbor X remove-private-AS all |
| Appliquer le filtre | import filter name |
neighbor X prefix-list/route-map name in |
BIRD2 utilise une seule fonction de filtre qui combine toutes les vérifications. FRR répartit les vérifications entre prefix-lists (correspondance de préfixes), as-path access-lists (correspondance de chemins) et route-maps (combinant plusieurs conditions de correspondance). Les deux approches fonctionnent. L'approche BIRD2 est plus lisible pour des politiques complexes. L'approche FRR est plus familière aux opérateurs Cisco.
Quelque chose s'est mal passé ?
Session fermée par max-prefix : Vérifiez journalctl -u bird ou journalctl -u frr pour le message d'atteinte de limite. Augmentez la limite si le pair a légitimement grandi, ou investiguez s'il s'agit d'une fuite. Dans BIRD2, réactivez avec birdc enable upstream_v4. Dans FRR, effacez avec vtysh -c "clear bgp 198.51.100.1".
Routes légitimes filtrées : Vérifiez birdc show route filtered ou vtysh -c "show ip bgp neighbors X filtered-routes" pour voir ce qui a été rejeté. Cause fréquente : votre liste bogon est trop agressive, ou votre seuil de petits préfixes rejette des /25 légitimes d'un client. Ajustez le filtre et rechargez : birdc configure ou vtysh -c "write memory" puis systemctl reload frr.
GTSM rejetant un pair valide : Les deux côtés doivent activer GTSM. Si un côté l'a activé et l'autre non, les paquets arrivent avec TTL 1 et sont rejetés par le côté avec GTSM activé. Vérifiez avec tcpdump -i eth0 port 179 -v et regardez la valeur TTL.
Filtres sans effet après modification : Dans BIRD2, lancez birdc configure pour recharger. Dans FRR, si vous modifiez une prefix-list ou une route-map, déclenchez une réinitialisation douce : vtysh -c "clear bgp 198.51.100.1 in". Sans cela, les routes existantes dans le RIB ne sont pas réévaluées contre le nouveau filtre.
Logs : Les deux daemons journalisent via systemd journal par défaut.
# BIRD2
journalctl -u bird -f
# FRR
journalctl -u frr -f
Les instructions print dans les fonctions de filtre BIRD2 écrivent dans le log bird. Dans FRR, activez la journalisation debug avec debug bgp updates dans vtysh pour un dépannage temporaire. Désactivez-la quand vous avez terminé car elle génère de grandes quantités de logs.
Cet article fait partie de la série BGP et Bring Your Own IP sur un VPS : le guide complet.