Chez ARN, FAI associatif en Alsace, nous avons deux transitaires : Cogent et Interoute.
Un transitaire, pour faire à la truelle, c'est une entité (société commerciale ou pas) qui est censée être présente dans tous les datacenters du monde afin de rendre accessibles tous les réseaux qui constituent Internet. L'intérêt ? Imaginons deux opérateurs : ARN dont l'infrastructure est physiquement présente à Strasbourg, France et un opérateur B dont l'infrastructure est présente à Tokyo, Japon. On sent bien que ces deux entités ne vont pas pouvoir interconnecter leurs réseaux à cause d'un coût prohibitif de la liaison et auront donc recours à un intermédiaire : c'est le transitaire.
Quel est l'intérêt d'avoir plusieurs transitaires ? Limiter l'impact des pannes / erreurs de configuration, augmenter la qualité du réseau et donc le confort de ses utilisateurs : certains transitaires ont un excellent réseau (capacité, latence,...) en Amérique du Nord et un mauvais en Europe ou inversement), limiter l'impact des guéguerres commerciales (exemple : Cogent et Hurricane Electric (HE) sont en guéguerre et il est donc impossible de joindre une adresse HE en étant client unique de Cogent et ce depuis plus de 5 ans...).
Comme exemple concret : le débit depuis Youtube est bien meilleur avec Interoute (qui peere avec Google là où Cogent a recours à des intermédiaires). Même chose avec Akamai (CDN qui a beaucoup de clients dont Allociné, par exemple).
Extrême inverse, Interoute est très mauvais pour joindre Free en IPv6. C'est ce cas que nous allons étudier ici.
Commençons par exposer le problème :
$ ping6 -c5 free.fr
PING free.fr(www.free.fr) 56 data bytes
64 bytes from www.free.fr: icmp_seq=1 ttl=53 time=296 ms
64 bytes from www.free.fr: icmp_seq=2 ttl=53 time=299 ms
64 bytes from www.free.fr: icmp_seq=3 ttl=53 time=297 ms
64 bytes from www.free.fr: icmp_seq=4 ttl=53 time=296 ms
64 bytes from www.free.fr: icmp_seq=5 ttl=53 time=297 ms
--- free.fr ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 296.036/297.222/299.210/1.265 ms
$ traceroute6 free.fr
traceroute to free.fr (2a01:e0c:1::1)
1 2001:1478:15:6::1 (2001:1478:15:6::1) 6.954 ms 6.940 ms 9.527 ms
2 2001:1478:0:8::1 (2001:1478:0:8::1) 15.376 ms 15.373 ms 15.339 ms
3 2001:1478:0:4::1 (2001:1478:0:4::1) 15.517 ms 15.497 ms 15.384 ms
4 2001:1478:0:67::2 (2001:1478:0:67::2) 179.371 ms 179.323 ms 179.700 ms
5 2001:cb0:1109:2:11::1 (2001:cb0:1109:2:11::1) 205.926 ms 206.277 ms 206.062 ms
6 2001:cb0:1109:1:4::1 (2001:cb0:1109:1:4::1) 206.829 ms 207.823 ms 208.358 ms
7 2001:cb0:1f1:1:1::1 (2001:cb0:1f1:1:1::1) 245.869 ms 243.807 ms 244.353 ms
8 2001:cb0:1f1:1:11::2 (2001:cb0:1f1:1:11::2) 358.374 ms 363.532 ms 366.210 ms
9 2001:504:d::c5 (2001:504:d::c5) 320.077 ms * 338.526 ms
10 newyork-6k-1-po3.intf.routers.proxad.net (2a01:e08:2:2::1) 251.944 ms 252.441 ms 251.939 ms
11 londres-6k-1-po103.intf.routers.proxad.net (2a01:e04:1:1::1) 252.410 ms 252.803 ms 259.481 ms
12 2a01:e00:1b::d (2a01:e00:1b::d) 258.806 ms 258.700 ms 258.655 ms
13 * * *
14 2a01:e00:17::e (2a01:e00:17::e) 259.637 ms 259.520 ms 262.087 ms
15 2a01:e00:1c::a (2a01:e00:1c::a) 259.546 ms 259.653 ms *
16 www.free.fr (2a01:e0c:1::1) 258.926 ms * 258.839 ms
Wow wow wow. Pour faire le chemin ARN -> Free, soit Strasbourg -> Paris, nous faisons en réalité Strasbourg -> Paris -> Asie -> New York -> Londres -> Paris ! Toi aussi fais le tour du monde avec ton FAI. \o/ Évidemment, on se retrouve avec une latence absolument hallucinante en accord avec le chemin physique parcouru (on ne peut pas aller plus vite que la vitesse de la lumière dans les fibres optiques).
Commençons par regarder ce que voient les routeurs BGP d'ARN :
« bird> sh route all for 2a01:e00::/26
2a01:e00::/26 via 2001:1478:15:6::1 on interoute [bgp_interoute 17:20:38] * (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 8928 10026 12322
BGP.next_hop: 2001:1478:15:6::1 fe80::21d:b501:c228:2ec4
BGP.med: 10
BGP.local_pref: 100
BGP.community: (8928,10311) (8928,10901) (8928,10903) (8928,11024) (10026,1230) (10026,31840) (10026,40904)
via 2001:978:2:57::7:1 on cogent [bgp_cogent 2016-02-02] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 12322 12322 12322
BGP.next_hop: 2001:978:2:57::7:1 fe80::e2ac:f1ff:fe18:cffb
BGP.med: 102010
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
via fe80::69:2 on eth1 [ibgp 17:20:39] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 8928 10026 12322
BGP.next_hop: ::
BGP.med: 10
BGP.local_pref: 100
BGP.community: (8928,10311) (8928,10901) (8928,10903) (8928,11024) (10026,1230) (10026,31840) (10026,40904)
via 2001:470:12:74::1 on he-ipv6 [bgp_hurricane_electric 2016-02-02] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 6939 12322
BGP.next_hop: 2001:470:12:74::1 fe80::d842:5436
BGP.local_pref: 90 »
Si l'on suit l'algorithme de sélection (
https://fr.wikipedia.org/wiki/Border_Gateway_Protocol#Choix_de_la_meilleure_route) :
Osef du weight puisque spécifique à Cisco.
Local preference : c'est ce qui fait perdre Hurricane Electric qui a pourtant un chemin plus court (1 seul saut de réseau dans l'AS_PATH). C'est un choix de notre part : cette interconnexion est un tunnel 6in4, nous préférons donc l'éviter, non pas qu'elle ne soit pas performante mais surtout car ça constitue une concentration inacceptable du réseau chez un seul acteur. Ce tunnel nous permettait de contourner l'embrouille entre HE et Cogent quand nous n'avions pas encore Interoute.
Self-Originated : non, ce n'est pas nous qui annonçons le préfixe de Free donc cela n'a aucun impact.
AS_PATH : à ce stade, il reste l'annonce d'Interoute, celle de Cogent et celle obtenue en iBGP (qui est celle d'Interoute, l'autre routeur d'ARN ayant suivi le même algorithme de sélection et un routeur BGP réannonce uniquement la meilleure route qu'il a sélectionnée). Free utilise la méthode de l'AS prepending (qui consiste à rallonger artificiellement le chemin d'AS en répétant ton numéro d'AS) pour indiquer qu'il ne veut pas que Cogent utilise l'interconnexion directe qu'ils ont entre eux sauf si Cogent n'a pas d'autre chemin (on notera que Cogent peut contourner ça grâce à l'attribut local preference qui est prioritaire ;) ). Donc l'annonce de Cogent est disqualifiée. Il reste l'annonce d'Interoute et celle en iBGP.
Origin : IGP dans les deux cas. Nos deux annonces restent donc en compétition.
MED : 10 dans les deux cas. Nos deux annonces restent donc en compétition.
eBGP > iBGP : ha... C'est ici que l'annonce iBGP perd et que l'annonce Interoute gagne définitivement. Notons que c'est l'une des caractéristiques majeures de BGP : faire du routage en patate chaude c'est-à-dire de sortir le paquet le plus vite de son réseau. La raison est simple : si tu fais du routage en patate froide pour livrer un paquet IP d'un de tes clients, que donc tu transportes le paquet IP sur ton réseau pour le livrer au plus près de la destination (qui est chez un autre opérateur), tu n'es pas sûr que cet opérateur agisse de la même manière au retour (une communication c'est forcément une question et une réponse et des acquittements de la réponse). Dans ce cas de figure, tu te retrouverais à transporter l'aller et le retour et donc à supporter le coût de l'intégralité de la communication, ce qui n'est pas équitable. En utilisant le mécanisme de la patate chaude, il devient impossible d'être trahi (ça ne résoud cependant pas toute la question de l'équité du financement de l'acheminement d'une communication, pensons à une vidéo dans un sens et des acquittements dans l'autre. Pour obtenir cette équité, il faut acentrer le réseau afin que celui qui consulte du contenu en diffuse aussi.).
Ce qui est bien avec cet algorithme, c'est qu'il est déterministe (à l'exception de quelques cas de figure, voir
https://www.ietf.org/rfc/rfc4264.txt ) et donc on peut le dérouler pour comprendre le choix d'un routeur BGP.
Que faire ici pour tricher et faire gagner l'annonce Cogent malgré tout ? Elle perd sur le nombre d'AS dans le chemin d'AS. On ne peut pas raccourcir ce chemin. Donc il faut jouer en amont... On ne peut pas jouer sur le fait d'être à l'origine ou non du préfixe... Donc il faut jouer en amont... On peut jouer sur la local preference.
Pour ce faire, avec BIRD, il faut utiliser un filtre avec le contenu suivant :
« filter bgp_filter_interoute_in
{
if bgp_path.last = 12322 then bgp_local_pref = 80;
accept;
}
protocol bgp bgp_interoute
{
import keep filtered; # Permet de voir les routes filtrées avec « sh route filtered protocol bgp_interoute » ;)
import filter bgp_filter_interoute_in;
}
»
+ « sudo birdc6 configure check » et, si c'est OK « sudo birdc6 configure ».
Pour ce faire, avec Quagga, il faut utiliser une route-map en utilisant les commandes suivantes :
« en
conf t
ip as-path access-list free-asn permit _12322$
route-map disgrace-free permit 5
match as-path free-asn
set local-preference 80
route-map disgrace-free permit 10
router bgp 60630
address-family ipv6
neighbor 2001:1478:15:6::1 route-map disgrace-free in
ctrl+z
clear ip bgp 2001:1478:15:6::1
copy r s »
Notons qu'une route-map peut être parfaitement cumulée à une prefix-list. Ceci est parfaitement valide :
« neighbor 2001:1478:15:6::1 prefix-list ipv6-invalid in
neighbor 2001:1478:15:6::1 route-map disgrace-free in »
On se sert de la prefix-list pour nettoyer les martians c'est-à-dire les plages d'adresses IP qui n'ont rien à faire sur Internet : documentation, RFC1918, benchmark, link-local,...), les bogons (les blocs d'adresses qui n'ont pas été allouées), la route par défaut, notre allocation (même si elle serait automatiquement éliminée à la phase 3 de l'algorithme se sélection ;) ), tout ce qui est > /19 et tout ce qui est < /48 (bonnes pratiques).
On regarde ensuite le résultat :
« bird> sh route all for 2a01:e00::/26
2a01:e00::/26 via 2001:978:2:57::7:1 on cogent [bgp_cogent 2016-02-02] * (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 12322 12322 12322
BGP.next_hop: 2001:978:2:57::7:1 fe80::e2ac:f1ff:fe18:cffb
BGP.med: 102010
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
via fe80::69:2 on eth1 [ibgp 22:09:15] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 12322 12322 12322
BGP.next_hop: ::
BGP.med: 102010
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
via 2001:1478:15:6::1 on interoute [bgp_interoute 22:09:14] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 8928 10026 12322
BGP.next_hop: 2001:1478:15:6::1 fe80::21d:b501:c228:2ec4
BGP.med: 10
BGP.local_pref: 80
BGP.community: (8928,10311) (8928,10901) (8928,10903) (8928,11024) (10026,1230) (10026,31840) (10026,40904)
via 2001:470:12:74::1 on he-ipv6 [bgp_hurricane_electric 2016-02-02] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 6939 12322
BGP.next_hop: 2001:470:12:74::1 fe80::d842:5436
BGP.local_pref: 90 »
Maintenant, l'annonce via Interoute est éliminée à la phase 2 (local preference) de l'algorithme de sélection, en même temps que celle via HE. Notons que si Cogent tombe, nous passerons par HE et si HE tombe en même temps que Cogent, nous utiliserons Interoute. Notons que nous aurions pu attribuer une local pref de 90 à Interoute, la longueur de l'AS_PATH ferait qu'HE gagnerait quand même si Cogent tombait. ;)
On pourrait adopter une autre stratégie : supprimer purement et simplement l'annonce BGP pour ne pas avoir à la prendre en compte dans l'algoirthme de sélection.
* Pour ce faire, avec BIRD, on mettrait ceci dans notre filtre BGP :
« if bgp_path.last = 12322 then reject; »
* Avec Quagga, on utiliserait ces commandes :
« en
conf t
ip as-path access-list free-asn deny _12322$
ip as-path access-list free-asn permit .*
route-map drop-free permit 5
match as-path free-asn
router bgp 60630
address-family ipv6
neighbor 2001:1478:15:6::1 route-map drop-free in
ctrl+z
clear ip bgp 2001:1478:15:6::1
copy r s »
Notons que cette manière de faire est moins optimale car en cas de panne de Cogent et d'HE, on ne pourra plus joindre Free en IPv6. Cette manière de faire nuit donc à la résilience du réseau.
Évidement, tout cela constitue une solution temporaire : la vraie solution est d'informer Interoute de ce problème de routage afin qu'il soit résolu de leur côté (ou que l'on sache pourquoi il ne le sera pas) et que ça profite à d'autres clients / utilisateurs. Internet est avant tout une construction humaine qui se debug en communiquant entre êtres humains. Le signalement a été effectué, en tout cas.
ÉDIT DU 09/02/2016 : problème corrigé depuis hier par Interoute qui a choisi de forcer le chemin en passant par NTT @ Paris :
bird> sh route all for 2a01:e00::/26
2a01:e00::/26 via 2001:978:2:57::7:1 on cogent [bgp_cogent 22:34:47] * (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 12322 12322 12322
BGP.next_hop: 2001:978:2:57::7:1 fe80::e2ac:f1ff:fe18:cffb
BGP.med: 102010
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
via fe80::69:2 on eth1 [ibgp 22:53:07] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 174 12322 12322 12322
BGP.next_hop: ::
BGP.med: 102010
BGP.local_pref: 100
BGP.community: (174,21101) (174,22008)
via 2001:470:12:74::1 on he-ipv6 [bgp_hurricane_electric 22:35:19] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 6939 12322
BGP.next_hop: 2001:470:12:74::1 fe80::d842:5436
BGP.local_pref: 90
via 2001:1478:15:6::1 on interoute [bgp_interoute 22:34:47] (100) [AS12322i]
Type: BGP unicast univ
BGP.origin: IGP
BGP.as_path: 8928 2914 174 12322 12322 12322
BGP.next_hop: 2001:1478:15:6::1 fe80::21d:b501:c228:2ec4
BGP.med: 10
BGP.local_pref: 100
BGP.community: (2914,420) (2914,1205) (2914,2204) (2914,3200) (8928,10310) (8928,10901) (8928,11004)
Comme NTT fait le choix de passer par Cogent et que nous sommes déjà client Cogent, l'annonce via Interoute perd à l'étape 4 (longueur du chemin d'AS aka nombre de sauts de réseaux aka nombre de réseaux traversés). Tous les clients Interoute qui ne sont pas également clients Cogent gagnent en qualité de service puisque les paquets ne sont plus acheminés en passant par l'Asie et les USA, ce qui évite latence donc débit moindre. FIN DE L'ÉDIT.
Merci à Alarig (
https://www.swordarmor.fr/ ) pour son coup de patte sur la syntaxe des « ip as-path access-list ». :)