Table des matières

CARP

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.

Notes concernant la topologie d'ARN

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

Installation

Ucarp est packagé dans Debian GNU/Linux stable donc :

apt-get install ucarp

Lancement au boot

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 à :

Scripts

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 ».

Subtilité 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 :

À faire lors de l'installation d'une machine d'un-e abonné-e dans notre baie

  sudo kill -USR2 `pidof ucarp`