Pivert's Blog

6. Shorewall : Haute disponibilité avec `keepalived`


Reading Time: 6 minutes

Introduction

Que ce soit pour les mise à jour du serveur Shorewall ou pour le «fail-over», configurez votre Shorewall en HA (haute disponibilité).

Ce 6è post cloture la série d’articles dédiés à Shorewall:

Le firewall est un élément essentiel du réseau, il doit démarrer avant tout autre service (même avant les serveurs DNS en cas de DR – Disaster Recovery.
Quand vous remettez le jus sur votre infrastructure, s’il y a bien deux choses que vous voulez, c’est un firewall-routeur opérationnel et un service DNS.
Comme pour le service DNS, le firewall doit avoir un strict minimum de dépendances; par exemple ne pas dépendre de stockages répliqués. (Sinon c’est l’œuf et la poule) – Donc si les serveurs Shorewall sont virtualisés, ils doivent idéalement ne consommer que des stockage locaux aux hyperviseurs.

Shorewall ne fournit pas de mécanisme de HA. Et c’est là que des services comme Keepalived et CSync2 vienent à la rescousse pour gérer les IPs virtuelles flotantes et la réplication de la configuration.

Principe

Shorewall étant «state-less», il vous suffit de deux serveurs. Dans le chapitre précédent, nous avons vu comment déclencher une action à chaque mise à jour. Nous allons étendre cette configuration avec l’ajout de csync2

  • Keepalived se charge de
    • créer les IPs virtuelles
    • monitorer les interfaces à l’aide de VRRP et éventuellement de scripts personnalisés
    • basculer les IP virtuelles d’un firewall à l’autre en un seul groupe. En effet, il ne faudrait pas par exemple que l’IP internet soit active sur le premier nœud, et l’IP interne sur le second nœud
    • envoyer un «gratuitous arp» afin de notifier le réseau et les switches du basculement, pour un basculement rapide
    • déclencher des actions lors de basculement, par exemple pour démarrer le firewall et un haproxy
    • Optionellement configurer les Linux IPVS pour des basculements sans interruptions. Cette utilisation ne sera pas vue dans les exemples ci-dessous. IPVS peut synchroniser les tables de NAT IPVS pour qu’il n’y ait pas d’interruption TCP lors du basculement pour les services exposés en externe.
  • CSync2 est un outil simple et efficace de synchronisation bidirectionnelle de fichiers. Souvent utilisé pour synchroniser des configurations dans les clusters.

Nous terminerons par un exemple de configuration de serveur DHCP en HA sur les 2 Serveurs Shorewall.

Mise en œuvre

1. Installez un second serveur Shorewall

Le plus simple, c’est de faire un clone de l’existant sur un autre serveur et de modifier les IPs avant le boot.

S’ils sont virtualisés :

  • Assurez-vous que les adresses MAC soient différentes.
  • Utilisez le stockage local pour ne pas dépendre de stockages distants ou répliqués
  • Utilisez une virtualisation complète de type KVM ou VMWare. Pas de LXC ou OpenVZ ici.

2. Installez keepalived et csync2

apt install keepalived csync2

3. Libérez les IPs de routage

Reconfigurez le réseau des 2 firewalls pour qu’ils n’utilisent plus les IPs de routage, mais uniquement des IPs de management. Par convention, je garde les .1 pour les IPs de routage (ou la première IP du subnet). Les IPs de routage seront gérées par Keepalived. Sous Debian/Ubuntu, vous devrez reconfigurer netplan. Exemple de /etc/netplan/50-cloud-init.yaml

network:
    version: 2
    ethernets:
        ens18:
            addresses: [ "227.51.67.12/24" ]
            mtu: 1492
    vlans:
      vlan10:
        id: 10
        link: ens18
        addresses: [ "227.51.67.2/24" ]
        routes:
          - to: 227.51.67.0/24
            via: 227.51.67.40
            metric: 100
          - to: 227.51.67.0/24
            via: 227.51.67.40
            metric: 100


      vlan66:
        id: 66
        link: ens18
        addresses: [ "227.51.67.2/24" ]

      vlan67:
        id: 67
        link: ens18
        addresses: [ "227.51.67.182/26" ]

      internet:
        id: 130
        link: ens18
        addresses: [ "227.51.67.12/24" ]
        mtu: 1492
        nameservers:
            addresses:
            - 227.51.67.9
        routes:
          - { to: default, via: 227.51.67.1 }
          - { to: 227.51.67.0/18, via: 227.51.67.1, metric: 100 }
          - { to: 227.51.67.0/19, via: 227.51.67.1, metric: 100 }
          - to: 227.51.67.84/32
            via: 227.51.67.1
            metric: 50
          - to: 227.51.67.94/31
            via: 227.51.67.1
            metric: 100

      vlan232:
        id: 232
        link: ens18
        addresses: [ "227.51.67.42/25" ]

Ne faites pas trop attention aux IPs, elles sont aléatoires, c’est juste un exemple pour vous montrer :

  • Les noms d’interface sont libres, pourvu qu’ils soient facilement identifiables.
  • Les noms d’interface doivent être identiques sur les 2 firewall routeurs, mais les IPs différentes, et différentes des IPs de routage.
  • Pour les interfaces de VLANs (802.1q), link: identifie l’interface sous-jacente, id: le numéro de VLAN (le tag).
  • Vous trouverez 2 syntaxes YAML équivalentes pour définir les routes statiques
  • Définissez et respectez des conventions. Par exemple, les IPs se terminant par 2 sont pour le premier routeur, se terminant par 3 pour le second routeur. L’ip de routage (.1) sera gérée par Keepalived.

Configurez Keepalived

Configurez les IP de routage, la priorité et le fail-over dans /etc/keepalived/

Voici un exemple de /etc/keepalived/keepalived.conf

global_defs {
   process_names
   enable_script_security
   lvs_sync_daemon ens18 loc id 50 port 45678
}

vrrp_instance loc {
    state MASTER
    interface vlan232
    virtual_router_id 15
    priority 110
    advert_int 4
    authentication {
        auth_type PASS
        auth_pass cuwa3GahP@ssW0rd
    }
    unicast_peer {
        154.99.91.43
    }
    virtual_ipaddress {
        154.99.91.1 dev vlan232 label local:vip    
    }
}
vrrp_instance dmz10 {
    state MASTER
    interface vlan10
    virtual_router_id 10
    priority 110
    advert_int 4
    authentication {
        auth_type PASS
        auth_pass cuwa3GahP@ssW0rd
    }
    unicast_peer {
        154.99.91.3
    }
    virtual_ipaddress {
        154.99.91.1 dev vlan10 label dmz10:vip
    }
}

vrrp_instance dmz {
    state MASTER
    interface vlan66
    virtual_router_id 66
    priority 110
    advert_int 4
    authentication {
        auth_type PASS
        auth_pass cuwa3GahP@ssW0rd
    }
    unicast_peer {
        154.99.91.3
    }
    virtual_ipaddress {
        154.99.91.1 dev vlan66 label dmz:vip
        154.99.91.69 dev vlan66 label dmz:vip2
    }
}

vrrp_instance dmzblu {
    state MASTER
    interface vlan67
    virtual_router_id 67
    priority 110
    advert_int 4
    authentication {
        auth_type PASS
        auth_pass cuwa3GahP@ssW0rd
    }
    unicast_peer {
        154.99.91.253
    }
    virtual_ipaddress {
        154.99.91.129 dev vlan67 label vlan67:vip    
    }
}

vrrp_instance netdmz {
    state MASTER
    interface ens18
    virtual_router_id 129
    priority 110
    advert_int 4
    authentication {
        auth_type PASS
        auth_pass cuwa3GahP@ssW0rd
    }
    unicast_peer {
        154.99.91.13
    }
    virtual_ipaddress {
        154.99.91.11 dev ens18 label netdmz:vip    
    }
}

vrrp_instance internet {
    state MASTER
    interface internet
    virtual_router_id 130
    priority 110
    advert_int 4
    authentication {
        auth_type PASS
        auth_pass cuwa3GahP@ssW0rd
    }
    unicast_peer {
        154.99.91.13
    }
    virtual_ipaddress {
        154.99.91.11 dev internet label internet:vip
    }
}

vrrp_sync_group VG1 {
           group {
                loc
                dmz
                dmz10
                dmzblu
                internet
                netdmz
           }
           notify_master /etc/keepalived/scripts/notify_start.sh root
           notify_backup /etc/keepalived/scripts/notify_stop.sh root
           notify_fault /etc/keepalived/scripts/notify_stop.sh root
           notify_stop /etc/keepalived/scripts/notify_stop.sh root
}

include virtual_servers.conf

Les choses importantes sont :

  • Définissez le state MASTER sur le premier firewall, et BACKUP sur le second.
  • Les priorités doivent être inférieures sur le nœud de BACKUP. (Exemple : 90 sur le BACKUP, 110 sur le MASTER)
  • Les virtual_router_id doivent être identiques sur chaque routeur, mais différents pour chaque réseau / VLAN.
  • Le vrrp_sync_group permet de synchroniser le basculement de toutes les interfaces et de définir les scripts à exécuter pour chaque changement d’état.
  • Le fichier est différent sur chaque nœud et ne peut être synchronisé avec CSync2. En revanche, on peut inclure un fichier commun. En dernière ligne par exemple l’inclusion de la configuration des IPVS qui est identique sur les 2 nœuds.

Exemple des scripts notify

/etc/keepalived/scripts/notify_start.sh

#!/bin/sh
/usr/sbin/shorewall start
/usr/bin/systemctl restart haproxy

/etc/keepalived/scripts/notify_stop.sh

#!/bin/sh
/usr/sbin/shorewall stop
/usr/bin/systemctl stop haproxy

Ces scripts gèrent entre autre le démarrage de Shorewall, car Shorewall ne peut démarrer qu’une fois que les interfaces et les IPs de routage sont disponibles.
Idem si vous utilisez également un haproxy au lieu de IPVS pour exposer des services externes clusterisés.
Haproxy est plus simple et peut travailler en layer 4 ou 7.
IPVS est plus performant, limité au layer 4, intégré à Keepalived et permet un switch-over sans perte de session TCP avec la synchronisation des sessions TCP par l’envoi de notifications UDP au nœud passif (ligne lvs_sync_daemon dans le fichier keepalived.conf)

CSync2

Nous n’allons pas voir la configuration complète de CSync2 et des certificats OpenSSL, mais uniquement son fichier principal qui régit son fonctionnement.

CSync2 est exécuté pour chaque modification par vim d’un fichier dans un des répertoires à synchroniser.

/etc/vim/vimrc.local

:autocmd BufWritePost /etc/shorewall/* !shorewall check && /usr/sbin/csync2 -x
:autocmd BufWritePost /etc/keepalived/* !/usr/sbin/csync2 -x
:autocmd BufWritePost /etc/dhcp/* !/usr/sbin/csync2 -x

/etc/csync2.cfg

group burns
{
        host burns2 burns3;
        key /etc/csync2.key_burns;
        include /etc/shorewall/;
        include /etc/keepalived/virtual_servers.conf;
        include /etc/dhcp/dhcpd.shared;
        include /etc/dhcp/dhcpd.hosts;
        include /etc/haproxy/haproxy.cfg;
        exclude *~ .*;
        action
        {
                pattern /etc/dhcp/dhcpd.hosts;
                exec "dhcpd -t -cf /etc/dhcp/dhcpd.conf";
                logfile "/var/log/csync2_dhcpd.log";
        }
        action
        {
                pattern /etc/shorewall/*;
                exec "/usr/sbin/shorewall reload";
                logfile "/var/log/csync2_shorewall.log";
        }
        action
        {
                pattern /etc/shorewall/*;
                exec "cd /etc/shorewall && /usr/bin/git commit -a -m 'AutoCommit from csync2'";
                do-local;
                logfile "/var/log/csync2_git_action.log";
        }
        action
        {
                pattern /etc/keepalived/*;
                exec "keepalived -C && echo Config OK && /usr/bin/git commit -a -m 'AutoCommit from csync2'";
                logfile "/var/log/csync2_git_action.log";
        }
}
  • Remarquez que dans cette configuration, ce n’est pas vim qui déclenche le git commit, mais csync2.
  • Les 2 fichiers sont identiques sur les deux nœuds firewall-router, même la ligne «host» car l’ordre des hosts n’a pas d’importance.
  • Le fichier d’exemple fait aussi référence au démon dhcp en cluster synchronisé «fail-over». Je mettrai sa configuration dans la section suivante.

DHCP

On sort du cadre de Shorewall, mais il peut être intéressant de faire tourner un démon DHCP sur le firewall-routeur. Et comme on est dans la section HA, la configuration doit permettre la réplication des leases.

/etc/dhcp/dhcpd.conf

failover peer "dhcp-failover" {
     primary;                         # Declared Primary DHCP Server
     address 192.168.232.42;          # Primary DHCP Server IP
     port 647;
     peer address 192.168.232.43;     # Secondary DHCP Server IP
     peer port 647;
     max-response-delay 60;
     max-unacked-updates 10;
     mclt 900;
     split 255;
     load balance max seconds 5;
}

include "/etc/dhcp/dhcpd.shared";     # Configuration commune aux 2 nœuds
include "/etc/dhcp/dhcpd.hosts";      # Réservations DHCP, commune aux 2 nœuds

Shorewall est gratuit

Ce n’est pas une nouvelle, mais c’est un fameux atout.
Cela signifie que vous pouvez le multiplier sans coût pour augmenter la disponibilité de votre réseau.

Par exemple:

  • Une paire de Shorewall «Internet Facing»
  • Une paire de Shorewall sur chaque site, pour les réseaux propres au site
  • Une paire de Shorewall sur 2 sites pour les VLANs «trunkés» ou «spread VLANs» qui sont une réelle menace pour la disponibilité du réseau. Ces «spread-vlans» entre sites sount souvent nécessaires si vous avez de vielles applications qui ne supportent pas de haute-disponibilité ou des applications coûteuses en licenses qui vous obligent à garder la possibilité de « live-migration » entre les sites. Vous gagnerez à dédier un cluster Shorewall pour ces réseaux plus fragiles en attendant de pouvoir vous en passer.

Like it ?

Get notified on new posts (max 1 / month)
Soyez informés lors des prochains articles

Leave a Reply

Your email address will not be published. Required fields are marked *