Howto CARP sous OpenBSD
- Documentation : https://www.openbsd.org/faq/pf/carp.html
CARP (Common Address Redundancy Protocol) est une alternative libre et sécurisée aux protocoles VRRP et HSRP. Il permet à plusieurs équipements, sur un même segment réseau, de partager une même adresse IP. L’objectif principal du protocole est de permettre une bascule réseau sur un équipement secondaire en cas d’incident.
Principe : Une interface réseau d’un des équipements est configurée pour être dans un état MASTER ou BACKUP. L’interface MASTER émet régulièrement des paquets à destination de l’interface BACKUP pour prouver son bon fonctionnement. Le choix MASTER/BACKUP est effectué grâce à des priorités configurables. Si le BACKUP ne reçoit pas un paquet dans les temps (ou si il reçoit un paquet inférieur à sa priorité), il passera en MASTER.
Configuration
Une interface CARP dépend de plusieurs paramètres :
carpdev
: interface physique à laquelle l’interface CARP sera liépass
: mot de passe d’authentification pour communiquer entre les différentes machines membres de l’interface CARPvhid
: identifiant pour communiquer entre les différentes machines membres de l’interface CARP et se distinguer des autres interfaces CARP ; il doit être unique sur un même segment réseauadvbase
: intervalle en seconde à laquelle le membre s’annoncera aux autres membresadvskew
: poids permettant de définir quel membre sera MASTER ; le plus faible est MASTER
Attention : si advbase
n’a pas la même
valeur sur tous les membres CARP, c’est celle ayant advbase
le plus bas qui sera MASTER, même si advskew
est plus haut
sur celle-ci.
Manuelle
Sur le MASTER :
# ifconfig carp0 create
# ifconfig carp0 vhid 1 pass PASSWORD carpdev bnx0 advbase 5 advskew 1 192.0.2.30 netmask 255.255.255.224
Sur le BACKUP :
# ifconfig carp0 create
# ifconfig carp0 vhid 1 pass PASSWORD carpdev bnx0 advbase 5 advskew 128 192.0.2.30 netmask 255.255.255.224
Persistante
Sur le MASTER :
# cat /etc/hostname.carp0
192.0.2.30/27 carpdev bnx0 pass PASSWORD vhid 1 advbase 5 advskew 1
# sh /etc/netstart carp0
Sur le BACKUP :
# cat /etc/hostname.carp0
192.0.2.30/27 carpdev bnx0 pass PASSWORD vhid 1 advbase 5 advskew 128
# sh /etc/netstart carp0
Création d’une interface CARP dans un VLAN
On peut attacher une interface CARP à une interface VLAN. L’interface CARP sera alors isolée dans le VLAN auquel elle est attachée.
Pour la création d’un VLAN, voir VLAN
# cat /etc/hostname.bnx0
up
# cat /etc/hostname.vlan42
vnetid 42 parent bnx0
up
description "VLAN42"
inet 192.0.2.1 255.255.255.224
# cat /etc/hostname.carp0
192.0.2.30/27 carpdev vlan42 pass PASSWORD vhid 1 advbase 5 advskew 128
Failover d’un groupe d’interfaces
Par défaut, toutes les interfaces CARP sont dans le même groupe
carp
. Chaque groupe a un compteur carpdemote
qui lui est propre et affectant toutes les interfaces membres du groupe.
Si une interface physique sur laquelle une interface CARP est configurée
passe down, alors le compteur carpdemote
du ou des groupes
auquel appartient l’interface CARP sera incrémenté de 1, et toutes les
interfaces CARP membres des mêmes groupes basculeront en même temps.
S’il n’est pas souhaité que toutes les interfaces CARP de la machine
basculent en même temps, il peut être souhaité de créer des groupes
distincts, et de les lever du groupe par défaut carp
. Par
exemple, sur 2 firewalls ayant 3 interfaces CARP, on peut vouloir que
carp0
et carp1
basculent ensemble en cas
d’erreur d’une seule des 2 interfaces, mais que carp2
soit
indépendante :
# ifconfig carp0 -group carp
# ifconfig carp1 -group carp
# ifconfig carp2 -group carp
# ifconfig carp0 group <group>
# ifconfig carp0 group <group>
Le droit de préemption
Le paramètre preempt
permet à une machine membre d’une
interface CARP de préempter l’état MASTER, c’est-à-dire
d’automatiquement basculer MASTER, si ses paramètres
advbase
et advskew
sont meilleurs.
# sysctl net.inet.carp.preempt=1
# echo 'net.inet.carp.preempt=1' >> /etc/sysctl.conf
Si ce paramètre n’est pas activé et que celui qui a les meilleurs
paramètres advbase
et advskew
est backup,
alors il le restera tant qu’aucune bascule manuelle n’est effectuée.
Informations utiles
Bascule CARP
Pour des raisons de maintenance ou suite à un incident, on peut
vouloir forcer une bascule CARP. ATTENTION, cela bascule
toutes les interfaces du groupe carp, c’est-à-dire par
défaut toutes les interfaces carp. Il faut, sur le MASTER, augmenter la
valeur carpdemote
:
# ifconfig -g carp carpdemote 50
Important : Si le compteur carpdemote
n’a pas la même valeur sur tous les membres CARP, alors le membre ayant
la valeur carpdemote
la plus faible (re)passera
automatiquement master.
Important : Si advbase
n’a pas la même
valeur sur tous les membres CARP, c’est celle ayant advbase
le plus bas qui sera MASTER, peu importe la valeur de
advskew
. Il faut donc s’assurer que advbase
ait la même valeur sur tous les membres avec
ifconfig carp | grep -Eo "advbase [0-9]+ "
, puis si besoin
le modifier avec ifconfig carpX advbase Y
, en remplaçant X
par le numéro de l’interface et Y par la valeur à configurer.
Important : Si advbase
et
carpdemote
sont tous les 2 différents entre plusieurs
membres CARP, il y aura un conflit.
Le MASTER va générer un paquet CARP avec la valeur du demote et le
BACKUP va ainsi immédiatemment passer MASTER. Ce paquet peut être
observé avec tcpdump proto carp
:
20:58:59.490207 CARPv2-advertise 36: vhid=1 advbase=5 advskew=12 demote=0 (DF) [tos 0x10]
20:58:59.809967 CARPv2-advertise 36: vhid=1 advbase=5 advskew=12 demote=50 (DF) [tos 0x10]
Pour avoir l’état actuel du compteur :
# ifconfig -g carp
carp: carp demote count 50
Pour revenir à l’état initial :
# ifconfig -g carp -carpdemote 50
À noter que l’on peut également faire
ifconfig carp0 down
sur le MASTER, suite à quoi il
s’annoncera avec des valeurs advbase
et
advskew
“infinies”. Le BACKUP recevra le paquet et passera
immédiatement MASTER. En repassant l’interface up avec
ifconfig carp0 up
sur l’ancien MASTER, il repassera à
nouveau directement MASTER en s’annonçant à l’autre machine, qui
repassera directement BACKUP.
Remonter une interface CARP
Si on a coupé une interface carp en faisant
ifconfig carpX down
et qu’on souhaite la remettre en place
sans qu’elle repasse MASTER, on vérifie que le advskew
est
bien supérieur à celui où le master est actuellement. Si ce n’est pas le
cas, on peut corriger avec ifconfig carpX advskew xxx
.
Lorsque c’est OK, il reste juste à faire
ifconfig carpX up
.
Cas pratique de bascule
Dans cet exemple, nous avons deux pare-feux configurés avec CARP.
Sur fw00 :
$ ifconfig carp
carp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:00:42:00:00:01
index 12 priority 15 llprio 3
carp: MASTER carpdev em0 vhid 1 advbase 5 advskew 1
groups: carp
status: master
inet 192.0.2.30 netmask 0xffffffe0 broadcast 192.0.2.31
carp1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:00:42:00:00:02
index 13 priority 15 llprio 3
carp: MASTER carpdev em1 vhid 2 advbase 5 advskew 1
groups: carp
status: master
inet 192.0.2.60 netmask 0xffffffe0 broadcast 192.0.2.61
Sur fw01 :
$ ifconfig carp
carp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:00:42:00:00:01
description: CARP DMZ
index 16 priority 15 llprio 3
carp: BACKUP carpdev em0 vhid 1 advbase 5 advskew 42
groups: carp
status: backup
inet 192.0.2.30 netmask 0xffffffe0 broadcast 192.0.2.31
carp1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:00:42:00:00:02
description: CARP LAN
index 17 priority 15 llprio 3
carp: BACKUP carpdev em1 vhid 2 advbase 5 advskew 42
groups: carp
status: backup
inet 192.0.2.60 netmask 0xffffffe0 broadcast 192.0.2.61
Nous souhaiterons mettre à jour fw00 et donc passer fw01 en master.
Sur fw00 :
# ifconfig -g carp carpdemote 50
# sed -i 's/advskew 1/advskew 142/g' /etc/hostname.carp*
# mv /etc/hostname.carp* /root/
Le master va alors immédiatement passer en backup. On modifie le paramètre advskew pour qu’il soit plus élevé que sur fw01, pour s’assurer que fw00 reste backup à la réactivation des interfaces. Le déplacement des fichiers de configuration CARP évite que les interfaces ne remontent lors de redémarrages. On peut désormais lancer la mise à jour et effectuer notre redémarrage.
Une fois fw00 prêt à être réintégré en production, on remet en place nos fichiers de configuration CARP.
Sur fw00 :
# mv /root/hostname.carp* /etc/
Les interfaces CARP peuvent alors être manuellement redémarrés :
# sh /etc/netstart carp0 carp1
Nous avons désormais nos interfaces CARP en BACKUP sur fw00. Le failover est donc d’ores et déjà fonctionnel.
On bascule ensuite les interfaces CARP depuis fw01 pour les repasser en BACKUP sur ce dernier et en MASTER sur fw00.
Sur fw01 :
# ifconfig -g carp carpdemote 50
Le pare-feu fw00 doit être repassé en MASTER maintenant.
On remet les valeurs de advskew à leur valeur d’origine sur notre MASTER.
Sur fw00 :
# ifconfig carp0 advskew 1
# ifconfig carp1 advskew 1
# sed -i 's/advskew 142/advskew 1/g' /etc/hostname.carp*
Enfin nous reconfigurons le carpdemote à 0 sur fw01.
Sur fw01 :
# ifconfig -g carp -carpdemote 50
Et c’est terminé !
Optimisation CARP au (re)boot d’un BACKUP
Lorsque que l’on a un firewall en BACKUP, il est important de pouvoir
le redémarrer sans que cela n’impacte le MASTER. Pour cela, il faut bien
comprendre le comportement de CARP au démarrage : pendant un certain
temps, il va toujours rester en BACKUP pour voir s’il ne reçoit pas
d’annonce d’un MASTER. Ce comportement est aussi présent lors de sa
(re)configuration même si le CARP était MASTER initialement. S’il n’a
rien reçu, il passe en MASTER. Ce temps est d’attente correspond à 3
fois la valeur du paramètre advbase
(par défaut à 1
seconde).
Conséquences de cela :
Si on reconfigure une interface CARP MASTER, elle va passer en BACKUP pendant
3*advbase
secondes ! Il est donc judicieux après être intervenu sur une machine qui est CARP MASTER de forcer le retour à l’état master avecifconfig carp0 state master
. À noter que si l’autre firewall a eu le temps de passer MASTER, cette commande ne le refera pas passer backup.Si on redémarre une machine avec des CARP BACKUP, il est probable que son réseau ne soit pas opérationnel immédiatement (synchronisation Spanning Tree qui prend 30 secondes par défaut par exemple). L’interface va donc se déclarer en MASTER après son temps d’attente
3*advbase
, et lorsque le réseau sera activé il y aura donc un conflit entre les deux MASTER. Il faut donc bien ajusteradvbase
pour qu’il soit bien supérieur au temps d’arrivée du réseau. Une manière de faire est d’avoir une configuration en dur avecadvbase
à 60 secondes par exemple, ce qui permet d’avoir des reboots transparents, puis on reconfigure manuellementadvbase
à 10 secondes par exemple quand tout est redémarré.
Dans ce deuxième cas, il est important de ne pas augmenter la valeur
carpdemote
du firewall ayant la valeur advbase
la plus basse. En effet, si fw01 est master avec advbase à 10 et que
fw00 est backup avec advbase à 60, et que l’on veut (re)passer fw00
master en augmentant la valeur carpdemote de fw01, alors il y aura un
conflit : toutes les 10 secondes, fw00 recevra un paquet de fw01 lui
disant que le carpdemote de fw01 est plus élevé que le sien ; fw00
passera alors master, et fw01 passera backup. Cependant, après
3*advbase
secondes, soit 3*10 secondes, fw01 passera de
nouveau master puisqu’il n’aura reçu aucun paquet de fw00 lui indiquant
que c’est lui le master, étant donné que fw00 n’envoie ses paquets que
toutes les 60 secondes. Après ces 60 secondes, fw01 aura reçu un nouveau
paquet de fw00 et repassera backup, mais pendant seulement 3*10 secondes
après lesquelles il passera de nouveau master, et ainsi de suite.
Note : Lors d’un reboot planifié on peut également décider de commenter l’ensemble des lignes présentes dans le(s) fichier(s)
/etc/hostname.carpX
: une fois la machine de nouveau disponible, il suffira de décommenter la configuration et recréer les interfaces viash /etc/netstart carp0 carp1
.
Services et CARP
Sous OpenBSD, plusieurs services sont capables de s’activer en fonction du statut d’une interface CARP : si l’interface est en BACKUP, une partie du service ne s’active pas, mais il s’active automatiquement si l’interface passe en MASTER. On peut notamment citer OpenBGPD, relayd, OSPFD ou encore sasyncd
Statistiques
On peut avoir des statistiques en utilisant netstat
$ netstat -sp carp
carp:
1816636 packets received (IPv4)
684123 packets received (IPv6)
0 packets discarded for bad interface
0 packets discarded for wrong TTL
0 packets shorter than header
0 discarded for bad checksums
0 discarded packets with a bad version
1293450 discarded because packet too short
2 discarded for bad authentication
482883 discarded for unknown vhid
0 discarded because of a bad address list
9667 packets sent (IPv4)
5792 packets sent (IPv6)
0 send failed due to mbuf memory error
35 transitions to master
Logs
Les changements d’états des interfaces sont notés dans
/var/log/messages
. On peut augmenter la valeur du paramètre
kernel net.inet.carp.log
(par défaut à 2) afin d’avoir des
traces plus parlantes.
# sysctl net.inet.carp.log=X (valeur X comprise entre 0 et 7)
Utiliser CARP sur VMWare
Le mode promiscuité doit être activé pour que CARP puisse fonctionner, à cause de l’adresse MAC créée spécialement pour l’interface CARP. Dans VMWare (notamment chez OVH), ce mode est désactivé par défaut.
La procédure pour activer ce mode dépend du réseau pour lequel on souhaite l’activer. Voici la documentation OVH : https://help.ovhcloud.com/csm/fr-vmware-promiscuous-mode?id=kb_article_view&sysparm_article=KB0058192
Activer le mode promiscuité sur un DVS public (WAN)
L’activation se fait depuis l’API OVH :
- Aller sur https://eu.api.ovh.com/console/#/dedicatedCloud/{serviceName}/datacenter/{datacenterId}/vm/{vmId}/enableCarp~POST. Il faut être connecté pour pouvoir utiliser l’API.
- Renseigner les informations :
serviceName
: nom du PCC, sous la forme “pcc-X-XXX-XXX-XXX”vmId
: ID de la VM, obtenu en séléctionnant la VM depuis vSphere, puis en regardant dans l’URL « VirtualMachine:vm-YYYY:ZZZ » ; l’ID est “YYYY”datacenterId
: ID du datacenter, obtenu depuis vShpere “pcc-X-XXX-XXX-XXX_datacenterYYYY” ; l’ID est “YYYY”- On peut également obtenir la liste des
datacenterId
à partir duserviceName
via https://eu.api.ovh.com/console/#/dedicatedCloud/%7BserviceName%7D/datacenter~GET
- On peut également obtenir la liste des
macAddress
: adresse MAC de l’interface sur laquelle le mode promiscuité doit être activé
- Cliquer sur Execute
On peut vérifier que le mode promiscuité est bien activé :
- Dans le DVS public, cliquer sur le réseau “VM Network”, et aller dans l’onglet “Ports”
- Cliquer sur le port de la VM concernée
- En dessous, dans l’onglet “Stratégies”, vérifier que “Mode Promiscuité” est bien sur “Accepter”
Activer le mode promiscuité sur un DVS vRack (LAN)
L’activation se fait directement depuis vSphere :
- Dans le vRack, clic droit sur le réseau concerné, puis cliquer sur “Modifier les paramètres”
- Aller dans l’onglet “Sécurité”, puis pour “Mode Promiscuité” sélectionner “Accepter”
- Cliquer sur OK pour valider
On peut vérifier que le mode promiscuité est bien activé :
- Dans le vRack, cliquer sur le réseau concerné, aller dans l’onglet “Configurer”
- Sous “Paramètres”, cliquer sur “Stratégies”
- À droite sous “Sécurité”, vérifier que “Mode Promiscuité” est bien sur “Accepter”