Nous avons deux routeurs pour aller et venir vers/depuis le reste des Internets. Une machine (Brique Internet, NUC, serveur) ne peut avoir qu'un et un seul routeur de sortie configuré à un instant T. Donc un seul des routeurs de l'association. Et si l'on a besoin d'interrompre l'un des routeurs de l'association pour une maintenance ? Et si une panne survient (crash matériel ou logiciel) ? La redondance permise par les deux routeurs ne profitera pas aux machines des abonné-e-s hébergées dans notre baie : la machine perdra son accès Internet. C'est dommage.
Pour éviter cela, on peut utiliser CARP. Il s'agit d'un protocole réseau libre qui autorise plusieurs machines à partager une ou plusieurs adresses IP dites virtuelles. À un instant T, une seule machine du groupe possède l'adresse IP sur une de ses interfaces réseau et rend un service défini (ici le rôle de transférer les paquets IP entre une machine hébergée et Internet). Toutes les machines du groupe se surveillent entre elles et, si la machine qui possède l'IP virtuelle tombe (panne, maintenance), une élection a lieu et la machine gagnante s'attribue l'adresse IP en moins d'une seconde et assure le service par intérim. Cela permet la haute disponibilité : pour que le service ne soit plus rendu, il faut que l'intégralité des machines du groupe devienne hors service.
Niveau terminologie CARP, une machine qui possède l'adresse IP est nommée « master », toutes les autres sont nommées « backup ». Un « backup » peut devenir « master » et inversement.
Ucarp est une implémentation du protocole CARP tournant sous GNU/Linux. Nous l'utilisons sur l'infra.
Par défaut, ucarp a deux défauts :
Mais, ucarp a aussi un mode dans lequel il effectue toute la partie émission et réception des battements de cœur et exécute un script quand l'état change (script “up” - exécuté quand un backup devient master et devient donc la machine qui possède l'IP virtuelle, script “down” - quand le master perd l'adresse IP). Dans ce mode-là, l'émission d'ARP (IPv4) et de Neighbor Advertisements (IPv6) pour indiquer que les adresses IP (v4 et v6) virtuelles ont changé de machine physique sont à la charge des scripts. C'est ce mode-là que nous utilisons chez ARN.
Pour ceux et celles qui s'interrogent : les émissions sauvages (ne faisant pas suite à une demande explicite d'une machine) d'ARP et de Neighbor Advertisements sont ignorées par les systèmes d'exploitation sauf si l'adresse IP sur laquelle portent ces messages est déjà dans les tables ARP/NA (qui stockent, temporairement, la relation entre une adresse IP (v4 pour ARP, v6 pour NA ;) ) et une adresse MAC. Autrement dit :
Sur ce point, voir la description de « arp_accept » sur https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt :
Both replies and requests type gratuitous arp will trigger the ARP table to be updated, if this setting is on. If the ARP table already contains the IP address of the gratuitous arp frame, the arp table will be updated regardless if this setting is on or off.
Une dernière chose : il faut bien comprendre que le transfert des paquets d'Internet vers la machine hébergée n'est pas du ressort de CARP. CARP s'occupe uniquement de redonder la sortie du réseau. :) Le paquet arrivera depuis le reste des Internets sur l'un ou l'autre des routeurs de l'association qui le transférera directement à la machine hébergée.
Ce que nous faisons :
auto eth0 iface eth0 inet static pre-up /sbin/ip link set $IFACE up pre-up /sbin/ip route add 169.254.43.1 dev $IFACE address <adresse_publique_attribuée_à_l'abonné>/32 gateway 169.254.43.1 iface eth0 inet6 static address <IPv6_dans_le_subnet_attribué_à_l'abonné>/56 gateway fe80::43:1 accept_ra 0 autoconf 0 dad-attempts 0
Ucarp est packagé dans Debian GNU/Linux stable donc :
apt-get install ucarp
Ucarp est livré brut de fonderie, sans iniscript sysvinit ni unit systemd. Le plus simple est d'utiliser une unit systemd.
Créons l'unit dans /etc/systemd/system/ucarp.service. Son contenu est disponible sur notre dépôt git.
Explications des paramètres que nous passons à ucarp :
Activons l'unit au boot :
sudo systemctl daemon-reload sudo systemctl enable ucarp
Ça, c'était sur notre premier routeur. Il sera toujours « master » donc il possédera toujours les adresses IP virtuelles donc ça sera lui qui rendra le service de transférer les paquets IP entre la machine d'un abonné et Internet. Sur les routeurs supplémentaires, on utilise la même unit systemd mais on pense à :
Voici les scripts que nous utilisons sur l'infra.
Ces scripts nécessitent les packages suivants : iproute2, iputils-arping (permet l'envoi de réponses ARP non sollicitées) et thc-ipv6 (permet l'envoi de Neighbor Advertisements non sollicités).
Concernant la variable « IFLIST » :
Ces scripts sont disponibles sur notre dépôt git :
Le script up nécessite les logiciels arping et atk6-fake_advertise6. Avec Debian, ils sont dans les paquets « iputils-arping » et « thc-ipv6 ».
En IPv4, la détection d'une adresse IP dupliquée sur le réseau est laissée à la charge d'un script (que l'on n'a pas dans Debian, d'ailleurs). En IPv6, cette détection est implémentée directement dans le noyau. Conclusion : lors d'un changement de machine physique, l'IPv6 virtuelle est flaggée « dadfailed » et est inutilisable pendant de longues minutes. On perd donc tout l'intérêt de CARP !
Il faut donc désactiver cette détection de collisions en passant la valeur de /proc/sys/net/ipv6/conf/<nom_interface>/accept_dad à 0. Côté routeur ARN et côté machine hébergée !
Pour le côté machine hébergée, voir « Notes concernant la topologie d'ARN » ci-dessus
Côté ARN, nous faisons ça dans /etc/network/interfaces, en même temps que la désactivation du traitement des Router Advertisements IPv6 (nos routeurs n'ont pas à prendre en compte ces paquets puisque les seuls routeurs légitimes de l'association sont… eux-mêmes). Exemple :
auto h-carpcontrol iface h-carpcontrol inet manual pre-up /sbin/ip l a link eth0 name $IFACE type vlan id 500 post-up /sbin/ip l s up dev $IFACE post-up /sbin/ip a a 169.254.43.253/24 scope link dev $IFACE post-up /sbin/ip r r <IP_attribué_à_l'abonné> dev $IFACE src 89.234.141.131 proto housing iface h-carpcontrol inet6 manual post-up /sbin/sysctl -w net.ipv6.conf.$IFACE.accept_ra=0 post-up /sbin/sysctl -w net.ipv6.conf.$IFACE.autoconf=0 post-up /sbin/sysctl -w net.ipv6.conf.$IFACE.accept_dad=0 post-up /sbin/ip -6 a a fe80::43:253/112 scope link dev $IFACE post-up /sbin/ip -6 r r <subnet_attribué_à_l'abonné> dev $IFACE src 2a00:5881:8100::131 proto housing post-down /sbin/ip l d $IFACE
Notes :
sudo kill -USR2 `pidof ucarp`