Introduction à BGP
C’est la première fois que je parle de BGP, ça me semble donc être une
bonne idée de dire ce que c’est. Il s’agit d’un protocole de niveau 7 se
basant sur TCP et permettant un échange dynamique de routes entre des
entités sur Internet possédant un ASN (Autonomous System Number). Son nom
complet est Border Gateway Protocol.
À la différence d’autres protocoles de routage dynamique, BGP n’a pas de
métrique simple mais tout un tas de critères que l’on évalue
séquentiellement et on s’arrête dès qu’il n’y a plus égalité. Voici ce que
donne la doc de bird :
- Préférer les routes avec la plus grande préférence locale
- Préférer les routes avec le chemin d’AS le plus court
- Préférer l’origine IGP par rapport à EGP et incomplète
- Préférer la plus faible valeur du discriminant des sorties multiples
- Préférer les routes reçues en eBGP à celles reçues en iBGP
- Préférer les routes avec la plus petite distance interne
- Préférer les routes du routeur avec le plus petit identifiant
Notre cas
Chez grifon on a deux fournisseurs de transit : cogent et quantic télécom.
On a donc une session BGP entre chacun de nos routeurs vers leurs
routeurs.
Cogent étant un opérateur bien plus gros que quantic, ils gagnaient très
souvent en raison de leur capacité à se brancher directement avec beaucoup
de monde, ce qui leur permet donc d’avoir un AS path plus court. Nous nous
retrouvions alors avec 20651 routes pour quantic contre 608776 pour cogent.
Quantic a un très gros avantage, on peut facilement boire des bières avec eux. De plus, ils sont normands alors que cogent est américain. Ça m’a donc semblé logique de les favoriser, en plus de pouvoir apprendre comment faire.
Par contre, je ne voulais pas favoriser quantic dans tous les cas afin de ne pas amputer sur la qualité du réseau.
La solution
Nos différents pairs BGP sont définis par rapport à des templates :
Et ensuite, nous les déclarons depuis ce template, avec un filtre pour
chaqun :
template bgp UPSTREAM
{
local as myasn;
# Be able to see filtered routes with "sh route filtered" command
import keep filtered;
# Protect ourselves from massive routes leaks
receive limit 640000 action block;
# Announce only our IP allocations
export where proto = "static_grifon_allocations";
export limit 1 action disable;
}
Avec cette configuration, tous les critères de choix de BGP était égaux en
cas de longueur d’AS égale sauf le dernier (router-id) qui faisait gagner
cogent.
filter bgp_filter_quantic_in
{
if (check_import(198507, 169.254.1.1)) then
{
# Here we can set localpref or remove a prefix, for example
accept;
}
else
{
reject "Prefix filtered IN quantic";
}
}
protocol bgp bgp_quantic from UPSTREAM
{
description "quantic";
neighbor 169.254.1.1 as 198507;
# Local address we use to establish the BGP session
source address 169.254.1.3;
# We cannot use TCP-MD5 auth because we use a poorly designed OS ;)
# password=''
# Accept all routes from Cogent except bogons and other bad stuff
import filter bgp_filter_quantic_in;
}
Nous sommes ici dans un cas où on peut faire gagner quantic sans perdre en
latence. Mais comme dit plus haut, je ne veux faire gagner quantic que dans
ce cas, il n’est donc pas possible d’utiliser la localpref. Il faut donc
chercher dans les critère suivants :
- Les deux routes sont d’origine IGP, on ne peut rien y faire,
- les deux routes ont la même MED, ça on peut le changer.
Jouer sur la MED
Pour faire varier ce paramètre, il faut commencer par le définir dans le
filtre BGP correspondant à quantic :
Et si nous rechargeons la configuration de bird, rien ne se passe…
Pourquoi ? Parce que par défaut bird ne prend pas ce paramètre en compte
dans le cas de routes reçues d’ASes différents, c’est écrit dans la
documentation :
filter bgp_filter_quantic_in
{
if (check_import(198507, 169.254.1.1)) then
{
# Here we can set localpref or remove a prefix, for example
bgp_med = 50;
accept;
}
else
{
reject "Prefix filtered IN quantic";
}
}
med metric switchIl faut alors, en plus de cela, ajouter la gestion de la MED dans notre template de configuration :
Enable comparison of MED attributes (during best route selection) even between routes received from different ASes. This may be useful if all MED attributes contain some consistent metric, perhaps enforced in import filters of AS boundary routers. If this option is disabled, MED attributes are compared only if routes are received from the same AS (which is the standard behavior).
Default: off.
template bgp UPSTREAM
{
local as myasn;
# Be able to see filtered routes with "sh route filtered" command
import keep filtered;
# Protect ourselves from massive routes leaks
receive limit 640000 action block;
# Announce only our IP allocations
export where proto = "static_grifon_allocations";
export limit 1 action disable;
med metric on;
}
Et là, une fois la configuration rechargée, nous passons bien par quantic
lorsque l’AS path est égal, tout en gardant le mécanisme de sélection
normal autrement :
root@budic:~ # birdc show route all for 37.187.103.228
BIRD 1.6.0 ready.
37.187.0.0/16 via 169.254.1.1 on re0.21 [bgp_quantic 14:53:28] * (100) [AS16276i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 198507 16276
BGP.next_hop: 169.254.1.1
BGP.med: 50
BGP.local_pref: 100
via 149.6.72.97 on re0.20 [bgp_cogent 14:51:07] (100) [AS16276i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 16276
BGP.next_hop: 149.6.72.97
BGP.med: 15051
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
unreachable [ibgp_nominoe 2017-02-09 from 89.234.186.7] (100/-) [AS16276i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 16276
BGP.next_hop: 89.234.186.1
BGP.med: 15051
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
root@budic:~ # birdc show route all for 89.234.141.1
BIRD 1.6.0 ready.
89.234.141.0/24 via 149.6.72.97 on re0.20 [bgp_cogent 14:50:16] * (100) [AS60630i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 60630
BGP.next_hop: 149.6.72.97
BGP.med: 21051
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
via 169.254.1.1 on re0.21 [bgp_quantic 14:49:45] (100) [AS60630i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 198507 174 60630
BGP.next_hop: 169.254.1.1
BGP.med: 50
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
unreachable [ibgp_nominoe 2017-02-09 from 89.234.186.7] (100/-) [AS60630i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 60630
BGP.next_hop: 89.234.186.1
BGP.med: 21051
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
root@budic:~ # birdc show route all for 216.66.84.42
BIRD 1.6.0 ready.
216.66.80.0/20 via 169.254.1.1 on re0.21 [bgp_quantic 14:50:27] * (100) [AS6939i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 198507 6939
BGP.next_hop: 169.254.1.1
BGP.med: 50
BGP.local_pref: 100
BGP.community: (24115,6939)
via 149.6.72.97 on re0.20 [bgp_cogent 14:50:56] (100) [AS6939i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 1299 6939 6939
BGP.next_hop: 149.6.72.97
BGP.med: 14040
BGP.local_pref: 100
BGP.community: (174,21100) (174,22008)
unreachable [ibgp_nominoe 2017-03-08 from 89.234.186.7] (100/-) [AS6939i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 198507 6939
BGP.next_hop: 89.234.186.1
BGP.local_pref: 100
BGP.community: (24115,6939)
.
Conclusion
Nous nous retrouvons maintenant avec 49576 routes pour quantic (contre
20651 précédemment) et 579833 pour cogent (contre 608776 précédemment).
Et cela se voit très bien sur le graph :