WikiMiNET

La documentation technique et administrative

Outils pour utilisateurs

Outils du site


wiki:divers:ha:firewall

Firewall redondant

Présentation de l'architecture

Voici l'architecture que nous allons réaliser :

Nous allons donc partager deux ips entre nos deux firewalls redondants (une de chaque coté), et synchroniser les deux conntracks entre elles.

Mise en place des interfaces CARP

Pour obtenir deux IP virtuelles communes aux deux firewalls, nous aurions pu utiliser KeepAlived , mais j'ai préféré choisir une autre solution d'IP virtuelle non basée 1) sur LVS.

CARP est une réponse de BSD au protocole VRRP, propriétaire.

Pour l'utiliser sous LiNUX, nous allons utiliser ucarp :

  apt-get install ucarp iputils-arping

Toute la config est ensuite effectuée dans /etc/network/interfaces.

Voici ce fichier pour le master :

allow-hotplug eth0
iface eth0 inet static
        address 192.168.103.208
        netmask 255.255.255.0
        ucarp-vid 3
        ucarp-vip 192.168.103.210
        ucarp-password toto
        ucarp-advskew 0
        ucarp-advbase 1
        ucarp-master yes
iface eth0:ucarp inet static
        address 192.168.103.210
        netmask 255.255.255.0
 
allow-hotplug eth1
iface eth1 inet static
        address 157.159.40.137
        netmask 255.255.255.192
        ucarp-vid 4
        ucarp-vip 157.159.40.139
        ucarp-password toto
        ucarp-advskew 0
        ucarp-advbase 1
        ucarp-master yes
iface eth1:ucarp inet static
        address 157.159.40.139
        netmask 255.255.255.192
        gateway 157.159.40.129

Pour expliquer, on commence par spécifier une interface de management ( 192.168.103.208 ), à laquelle on attache une ip virtuelle supplémentaire. Cette ip supplémentaire fait appel à un numéro de session CARP ( ici 3 ) ainsi qu'un mot de passe histoire de sécuriser un peu tout ça… On spécifie cette ip virtuelle.

On fait la même chose pour eth1. On rajoute cepandant une gateway sur l'ip virtuelle.

Voici maintenant la conf du slave :

allow-hotplug eth0
iface eth0 inet static
        address 192.168.103.209
        netmask 255.255.255.0
        ucarp-vid 3
        ucarp-vip 192.168.103.210
        ucarp-password toto
        ucarp-advskew 0
        ucarp-advbase 1
        ucarp-master no
iface eth0:ucarp inet static
        address 192.168.103.210
        netmask 255.255.255.0
 
allow-hotplug eth1
iface eth1 inet static
        address 157.159.40.138
        netmask 255.255.255.192
        ucarp-vid 4
        ucarp-vip 157.159.40.139
        ucarp-password toto
        ucarp-advskew 0
        ucarp-advbase 1
        ucarp-master no
iface eth1:ucarp inet static
        address 157.159.40.139
        netmask 255.255.255.192
        gateway 157.159.40.129

Ici les seules choses qui changent c'est les adresses IP propres à la machine, ainsi que l'on est ce coup ci en mode slave.

Voilà c'est aussi simple que ça et très robuste !

Note pour les OpenVZ : il faut désactiver le filtrage mac sur les instances utilisant uCarp. Ceci se fait avec la commande suivante avec l'instance ÉTEINTE :

  vzctl set <CTID> --mac_filter=off --ifname=eth0 --save

Synchronisation des conntracks des deux firewalls

Ce que nous cherchons à redonder, c'est un parefeu statefull. Il nous faut donc synchroniser les conntracks entre le slave et le master. Pour ce faire, nous allons utiliser l'outil qui permet de controller la conntrack de netfilter depuis l'espace utilisateur : conntrackd.

Pour l'installer, rien de plus simple :

  apt-get install conntrackd

Bon passons maintenant à la réplication de la conntrack. Différents modes de synchronisations existent :

  1. notrack qui consiste à faire au plus simple : on bombarde en face et on se fout de si ça arrive ou pas…
  2. ft-fw qui repose sur un protocole fiable (réordonne, détecte les corruptions et les pertes )
  3. alarm qui est le plus coûteux en terme de bande passante, mais résout rapidement les problèmes de synchronisations ( c'est pour lui que le failover indura le moins de pertes ). À MiNET, comme on est des fous, c'est ce mode que nous choisirons.

Ensuite, il nous faut ensuite choisir un protocole pour le transport de ces options. On a le choix entre UDP et du multicast. J'ai choisit de l'UDP car on a que deux noeuds 2). Si on avait plus de firewall en parallèle j'aurais plus misé sur le multicast.

Enfin avant d'aller plus loin, il faut se rendre compte que les infos de la conntrack sont sensibles, et qu'il fat pas quelles se ballades n'importe où… Ainsi c'est mieux de faire du binding entre deux interfaces qui utilisent un lien dédié…

Sans plus vous faire attendre, voici mon fichier de configuration :

Sync {
        Mode ALARM {
                RefreshTime 5
                CacheTimeout 600
        }
         UDP {
                IPv4_address 192.168.103.208
                IPv4_Destination_Address 192.168.103.209
                Port 3780
                Interface eth0
                Checksum on
         }
}
 
General {
        Nice -20
        HashSize 32768
        HashLimit 131072
        LogFile on
        LockFile /var/lock/conntrack.lock
        UNIX {
                Path /var/run/conntrackd.ctl
                Backlog 20
        }
        NetlinkBufferSize 2097152
        NetlinkBufferSizeMaxGrowth 8388608
        Filter From Userspace {
                Protocol Accept {
                        TCP
                        ICMP
                }
                Address Ignore {
                        IPv4_address 127.0.0.1
                        IPv4_address 192.168.103.210
                        IPv4_address 157.159.40.139
                        IPv4_address 157.159.40.137
                        IPv4_address 192.168.103.209
                        IPv4_address 192.168.103.208
                }
        }
}

Revenons un peu sur cette conf' :

Paramètres de synchronisation :

  • RefreshTime : On envoie des notifications toutes les x secondes pour les entrées non modifiées de la conntrack sur le master. Ce mécanisme permet de mettre à jour les nouveaux slaves. Dans cet exemple, il faut 5 secondes pour que la conntrack du slave fraîchement rallumé soit consistante.
  • cacheTimeout : En cas de non notification pour une entrée de la conntrack sur le master pendant x secondes, on la supprime sur le slave. Typiquement, on se débrouille pour que cette valeur soit égale au time out de notre conntrack.
  • Je ne reviendrais pas sur les paramètres de UDP, c'est explicite. En revanche, vous noterez que j'ai activé les check sums pour un maximum de sécurité.

Paramètres généraux :

  • Nice permet de régler la fréquence de sheduling du daemon. Plus la valeur est basse, moins le failover sera coûteux en terme connections perdues.
  • Filter permet de synchroniser la conntrack que sur les protocoles qui nous intéressent (TCP et ICMP disons), et d'ignorer les entrées de la conntrack propres au firewall utilisé (typiquement celles de ces adresses ips virtuelles ou réelles).

Note : Je n'arrive pas à redémarrer conntrackd par le script d'init. Il me faut killer le processus, et virer le lock et le socket… Un petit défaut ! Il suffit juste de réécrire un script d'init plus bourrin sur le stop…

Néanmoins, mes sessions SSH établies à travers les ips virtuelles survivent à l'arrêt de chacune des deux machines. Ça marche, et même bien ;-)

Conclusions

Ma première conclusion concerne CARP et ucarp. ucarp est simple à mettre en place, et à mon sens potentiellement plus efficace que keepalived. J'ai été surpris à l'extinction de la vm master de constater une indisponibilité de l'IP partagée de moins d'une demie seconde ( !!! ) alors que je n'ai fais aucune optimisation.

Seul point : je n'ai pas encore testé ucarp sous OpenVZ…

Ma deuxième conclusion est qu'on a ici en libre ce que des appliances proposent à des prix hallucinants. Avec un peu d'huile de coude et quelques optimisations, je suis sûr que ça marche aussi bien ;-)

Liens utiles

Benoit Tellier 2014/01/26 22:12

1)
du moins il me semble
2)
et que je pouvais facilement voir ce qui se passe
wiki/divers/ha/firewall.txt · Dernière modification: 2020/06/27 18:16 (modification externe)