Il y a 389 articles et 19 utilisateurs inscrits (ce bandeau est défini dans MediaWiki:Sitenotice)

Préparation de l'infrastructure OPNsense / HAProxy pour l'intégration d'une nouvelle VM

De AJLSM
Aller à la navigation Aller à la recherche

Cas d'application : préparation de la future VM MERCURE3

Cette documentation décrit les opérations à effectuer avant la création d'une nouvelle VM afin de préparer son intégration dans l'architecture redondante AJLSM.

Le cas documenté ici est celui de la future VM MERCURE3.

La préparation comprend :

  • l'attribution des adresses IP ;
  • la création du DNS public ;
  • la création du VIP CARP sur OPNsense ;
  • la création du Destination NAT vers le VIP HAProxy ;
  • la synchronisation des deux OPNsense ;
  • la préparation des frontends et backends HAProxy ;
  • la création et le déploiement du certificat Let's Encrypt sur les deux HAProxy ;
  • le déploiement et la validation de la configuration HAProxy avec Ansible.

À l'issue de cette procédure, toute l'infrastructure située en amont de la nouvelle VM est opérationnelle.

La VM peut alors être créée et configurée avec les adresses qui lui ont été réservées.

2. Adressage retenu

[modifier | modifier le wikicode]

Les adresses attribuées à MERCURE3 sont :

Élément Adresse Remarque
DNS public mercure3.ajlsm.com Nom public
IP publique 51.83.117.113 Portée par OPNsense en CARP
IP backend 10.0.0.43 Adresse utilisée par HAProxy pour joindre MERCURE3
IP réseau / vRack 192.168.123.27 Adresse de la VM sur ce réseau
Passerelle réseau privé 10.0.0.4 Passerelle prévue pour la VM

L'adresse publique 51.83.117.113 appartient au bloc public utilisé sur cette infrastructure.

Elle ne doit pas être configurée directement sur une carte réseau de MERCURE3.

Le chemin réseau retenu est :

Internet
   |
   | mercure3.ajlsm.com
   | 51.83.117.113
   v
OPNsense FW1 / FW2
CARP 51.83.117.113
   |
   | Destination NAT
   v
10.0.0.32
VIP HAProxy
   |
   +---- HTTP  ----> 10.0.0.43:80
   |
   +---- HTTPS ----> 10.0.0.43:443
                         |
                         v
                     MERCURE3

3. Création du DNS

[modifier | modifier le wikicode]

Le DNS suivant a été créé :

mercure3.ajlsm.com -> 51.83.117.113

Vérification depuis un poste extérieur :

dig +short mercure3.ajlsm.com

Résultat attendu :

51.83.117.113

4. Configuration OPNsense : VIP CARP

[modifier | modifier le wikicode]

Sur OPNsense FW1, un nouveau Virtual IP CARP a été créé sur l'interface VRACK.

Paramètres principaux :

Paramètre Valeur
Type CARP
Interface VRACK
Adresse 51.83.117.113/32
VHID 8

Après application de la configuration :

  • FW1 doit être MASTER pour ce CARP ;
  • FW2 doit être BACKUP.

Le fait que FW2 affiche ses CARP en BACKUP est donc le comportement normal lorsque FW1 est actif.

5. Configuration OPNsense : Destination NAT

[modifier | modifier le wikicode]

Une règle de Destination NAT a été créée pour MERCURE3.

Paramètres principaux :

Paramètre Valeur
Interface VRACK
Version IP IPv4
Protocole any
Destination 51.83.117.113
Port destination any
Redirect target IP 10.0.0.32
Redirect target port any
Description VM MERCURE3

Point important :

Le NAT ne pointe pas directement vers MERCURE3 (10.0.0.43).

Il pointe vers :

10.0.0.32

qui est le VIP des deux HAProxy.

Le routage vers 10.0.0.43 est ensuite effectué par HAProxy en fonction du nom HTTP demandé.

6. Synchronisation FW1 vers FW2

[modifier | modifier le wikicode]

La synchronisation de la configuration OPNsense entre FW1 et FW2 est effectuée manuellement.

Après création du CARP et du Destination NAT sur FW1, la configuration a été synchronisée vers FW2.

La synchronisation peut prendre un certain temps.

Après synchronisation, vérifier sur FW2 :

  • présence du nouveau CARP 51.83.117.113 ;
  • état BACKUP ;
  • présence de la règle NAT MERCURE3.

Accès à FW2 depuis le Mac

[modifier | modifier le wikicode]

Lorsque l'accès direct à FW2 est nécessaire, utiliser le tunnel SSH via HAProxy1 :

ssh -L 8453:10.0.0.3:453 hpr@10.0.0.30

Conserver la session SSH ouverte puis accéder avec le navigateur à :

https://127.0.0.1:8453/

Le chemin est alors :

Mac
 |
 | VPN + SSH
 v
10.0.0.30:22
HAProxy1
 |
 | tunnel SSH
 v
10.0.0.3:453
FW2 / OPNsense

7. Premier test avant configuration HAProxy

[modifier | modifier le wikicode]

Après création du DNS, du CARP et du NAT, un test HTTP a été effectué :

curl -I http://mercure3.ajlsm.com/

Le résultat obtenu était :

HTTP/1.0 503 Service Unavailable

À ce stade, ce résultat était cohérent.

Il montrait que le chemin :

DNS
 -> IP publique
 -> CARP
 -> OPNsense
 -> DNAT
 -> VIP HAProxy

était fonctionnel.

Le backend MERCURE3 n'existant pas encore, HAProxy ne pouvait évidemment pas transmettre la requête à la VM.

8. Configuration HAProxy

[modifier | modifier le wikicode]

La configuration HAProxy est gérée avec Ansible depuis :

/Users/jlarvers/__SVN__/ansible-ajlsm/

MERCURE3 doit être gérée dans le frontend Web existant.

Le frontend écoute notamment sur :

10.0.0.32:80
10.0.0.32:443

Le certificat TLS public est donc présenté par HAProxy.

Le frontend utilise également le filtre Coraza/SPOE déjà présent dans l'architecture.

MERCURE3 étant une VM AJLSM de travail / recette, l'accès au nom :

mercure3.ajlsm.com

est limité aux adresses autorisées par :

allowed_ajlsm

Cette restriction concerne le hostname mercure3.ajlsm.com.

D'autres noms de recette hébergés ultérieurement sur la même VM pourront disposer de leurs propres ACL et règles d'accès.

9. ACL HAProxy MERCURE3

[modifier | modifier le wikicode]

La configuration retenue est :

# MERCURE3 - VM AJLSM DE TRAVAIL / RECETTE
acl host_ssl_mercure3 hdr(host)                         -i          mercure3.ajlsm.com
acl host_mercure3 hdr(host)                             -i          mercure3.ajlsm.com

use_backend back_ssl_mercure3                           if          host_ssl_mercure3
http-request redirect scheme https                      if          { hdr(Host) -i mercure3.ajlsm.com } !{ ssl_fc }
http-request deny                                       if          host_mercure3 !allowed_ajlsm

use_backend back_mercure3                               if          host_mercure3

Important : les deux ACL doivent être déclarées avant leur utilisation.

En particulier :

acl host_mercure3 ...

doit être déclaré avant :

http-request deny if host_mercure3 !allowed_ajlsm

Ce point a été détecté lors d'une première validation Ansible.

10. Backends MERCURE3

[modifier | modifier le wikicode]

Les backends ajoutés sont :

backend back_ssl_mercure3
        server SSLMERCURE3                     10.0.0.43:443 check ssl verify none

backend back_mercure3
        server MERCURE3                        10.0.0.43:80 check

On dispose donc de deux chemins vers la VM :

Backend Destination Protocole
back_mercure3 10.0.0.43:80 HTTP
back_ssl_mercure3 10.0.0.43:443 HTTPS

Pour le premier déploiement, aucun SNI explicite n'a été ajouté au serveur HTTPS.

Si nécessaire, notamment en présence de plusieurs VirtualHosts HTTPS sur MERCURE3, la ligne pourra être modifiée ultérieurement en :

server SSLMERCURE3 10.0.0.43:443 check ssl verify none sni str(mercure3.ajlsm.com)

Ce besoin a déjà été rencontré sur des configurations récentes, notamment AD64.

Il est préférable de ne l'ajouter que si le test du backend montre qu'il est nécessaire.

11. Certificat Let's Encrypt sur HAProxy1

[modifier | modifier le wikicode]

Le certificat public de :

mercure3.ajlsm.com

est géré directement sur les HAProxy avec acme.sh.

Les commandes sont exécutées depuis un shell root, mais acme.sh est lancé sous l'utilisateur acme.

sudo -u acme /usr/local/share/acme.sh/acme.sh \
  --home /var/lib/acme/.acme.sh \
  --issue \
  --stateless \
  --server letsencrypt \
  --keylength ec-256 \
  -d mercure3.ajlsm.com

Le challenge ACME peut fonctionner alors que MERCURE3 n'existe pas encore, car le chemin :

/.well-known/acme-challenge/

est traité directement par HAProxy.

Déploiement dans HAProxy

[modifier | modifier le wikicode]
sudo -u acme env \
  DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy/certs \
  DEPLOY_HAPROXY_HOT_UPDATE=yes \
  /usr/local/share/acme.sh/acme.sh \
  --home /var/lib/acme/.acme.sh \
  --deploy \
  --ecc \
  -d mercure3.ajlsm.com \
  --deploy-hook haproxy

Le fichier résultant est :

/etc/haproxy/certs/mercure3.ajlsm.com.pem

Le certificat obtenu sur HAProxy1 a notamment été contrôlé avec openssl.

Il correspond bien à :

CN = mercure3.ajlsm.com
Let's Encrypt

12. Certificat Let's Encrypt sur HAProxy2

[modifier | modifier le wikicode]

Le certificat n'est pas copié depuis HAProxy1 avec SCP.

Chaque HAProxy possède son environnement ACME et le certificat est émis puis déployé indépendamment sur chaque nœud.

Sur HAProxy2, effectuer à nouveau :

sudo -u acme /usr/local/share/acme.sh/acme.sh \
  --home /var/lib/acme/.acme.sh \
  --issue \
  --stateless \
  --server letsencrypt \
  --keylength ec-256 \
  -d mercure3.ajlsm.com

Puis :

sudo -u acme env \
  DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy/certs \
  DEPLOY_HAPROXY_HOT_UPDATE=yes \
  /usr/local/share/acme.sh/acme.sh \
  --home /var/lib/acme/.acme.sh \
  --deploy \
  --ecc \
  -d mercure3.ajlsm.com \
  --deploy-hook haproxy

Le déploiement a été effectué à chaud via le socket HAProxy.

Vérification :

ls -l /etc/haproxy/certs/mercure3.ajlsm.com.pem

Résultat observé sur HAProxy2 :

-rw-rw-r-- 1 acme acme 5048 Oct 7 09:56 /etc/haproxy/certs/mercure3.ajlsm.com.pem

À ce stade, le certificat mercure3.ajlsm.com est donc présent sur les deux HAProxy.

13. Validation Ansible avant déploiement

[modifier | modifier le wikicode]

Depuis le Mac :

cd /Users/jlarvers/__SVN__/ansible-ajlsm/

ansible-playbook ./plays/deploy.haproxy.yml \
  -l ajlsm_loadbalancer \
  --check \
  --diff

Cette étape est importante car le rôle Ansible valide la configuration HAProxy avant de la mettre en service.

14. Première erreur détectée par la validation

[modifier | modifier le wikicode]

Une première tentative a échoué avec :

error detected while parsing an 'http-request deny' condition :
no such ACL : 'host_mercure3'

La cause était l'utilisation de :

host_mercure3

dans la règle :

http-request deny if host_mercure3 !allowed_ajlsm

avant la déclaration de l'ACL.

La configuration a donc été corrigée pour déclarer :

acl host_ssl_mercure3 hdr(host) -i mercure3.ajlsm.com
acl host_mercure3 hdr(host) -i mercure3.ajlsm.com

avant les règles qui les utilisent.

Cette erreur illustre l'intérêt du contrôle systématique de la configuration avant déploiement.

15. Deuxième contrôle --check --diff

[modifier | modifier le wikicode]

Après correction, le contrôle a été relancé :

ansible-playbook ./plays/deploy.haproxy.yml \
  -l ajlsm_loadbalancer \
  --check \
  --diff

Le diff a alors correctement montré l'ajout de MERCURE3 :

# MERCURE3 - VM AJLSM DE TRAVAIL / RECETTE
acl host_ssl_mercure3 hdr(host)                         -i          mercure3.ajlsm.com
acl host_mercure3 hdr(host)                             -i          mercure3.ajlsm.com

use_backend back_ssl_mercure3                           if          host_ssl_mercure3
http-request redirect scheme https                      if          { hdr(Host) -i mercure3.ajlsm.com } !{ ssl_fc }
http-request deny                                       if          host_mercure3 !allowed_ajlsm

use_backend back_mercure3                               if          host_mercure3

ainsi que :

backend back_ssl_mercure3
        server SSLMERCURE3                     10.0.0.43:443 check ssl verify none

backend back_mercure3
        server MERCURE3                        10.0.0.43:80 check

Le résultat final était :

haproxy01.ajlsm.lan : failed=0
haproxy02.ajlsm.lan : failed=0

Le diff comportait également quelques changements d'alignement/espaces sur la section SENTINEL et back_ad64_matomo.

Ces modifications étaient uniquement des changements de présentation du template et non des modifications fonctionnelles liées à MERCURE3.

16. Déploiement de la configuration

[modifier | modifier le wikicode]

Une fois le --check --diff validé, la configuration est déployée depuis le Mac avec :

cd /Users/jlarvers/__SVN__/ansible-ajlsm/

ansible-playbook ./plays/deploy.haproxy.yml \
  -l ajlsm_loadbalancer

Le déploiement concerne les deux nœuds :

haproxy01.ajlsm.lan
haproxy02.ajlsm.lan

17. Validation de la configuration HAProxy déployée

[modifier | modifier le wikicode]

La validation globale est effectuée depuis le Mac, où Ansible est installé :

ansible ajlsm_loadbalancer -b -m shell -a \
'haproxy -c -f /etc/haproxy/haproxy.cfg'

Il ne faut pas exécuter la commande ansible directement sur HAProxy1 ou HAProxy2 : Ansible n'y est pas installé.

La validation a donné sur les deux machines :

Configuration file is valid

HAProxy est en version :

HAProxy 2.8.16-0ubuntu0.24.04.3

La validation produit également de nombreux avertissements de la forme :

a 'http-request' rule placed after a 'use_backend' rule
will still be processed before

Ces avertissements concernent plusieurs règles préexistantes de la configuration HAProxy.

Ils ne bloquent pas le chargement :

rc=0
Configuration file is valid

Ils pourront faire l'objet d'un nettoyage séparé de la configuration HAProxy.

18. État des backends avant création de MERCURE3

[modifier | modifier le wikicode]

Après activation de la configuration, HAProxy signale logiquement :

backend back_ssl_mercure3 has no server available!
backend back_mercure3 has no server available!

Ce comportement est normal.

Les health checks essaient désormais de joindre :

10.0.0.43:80
10.0.0.43:443

mais MERCURE3 n'existe pas encore.

Ces messages confirment par ailleurs que les nouveaux backends sont bien chargés et surveillés par HAProxy.

19. État de l'installation à ce stade

[modifier | modifier le wikicode]

La partie infrastructure située en amont de MERCURE3 est terminée.

Élément État
DNS mercure3.ajlsm.com OK
IP publique 51.83.117.113 OK
CARP OPNsense OK
Synchronisation FW1 / FW2 OK
Destination NAT vers 10.0.0.32 OK
HAProxy1 OK
HAProxy2 OK
Certificat Let's Encrypt HAProxy1 OK
Certificat Let's Encrypt HAProxy2 OK
ACL mercure3.ajlsm.com OK
Restriction allowed_ajlsm OK
Backend HTTP 10.0.0.43:80 configuré / DOWN en attente de la VM
Backend HTTPS 10.0.0.43:443 configuré / DOWN en attente de la VM
MERCURE3 à créer

20. Informations nécessaires pour la création de la VM

[modifier | modifier le wikicode]

Lors de la création de la VM, les adresses prévues sont :

Backend / réseau privé : 10.0.0.43
vRack / LAN            : 192.168.123.27
Passerelle              : 10.0.0.4

L'adresse :

51.83.117.113

ne doit pas être affectée à une interface de MERCURE3.

Elle est portée par le CARP OPNsense.

Le certificat Let's Encrypt public de :

mercure3.ajlsm.com

est déjà présent sur les deux HAProxy.

21. Contrôles à effectuer après création de MERCURE3

[modifier | modifier le wikicode]

Lorsque la VM sera disponible, contrôler tout d'abord que les services répondent sur :

10.0.0.43:80
10.0.0.43:443

Les health checks HAProxy doivent alors passer de DOWN à UP.

Les tests extérieurs pourront ensuite être effectués :

curl -I http://mercure3.ajlsm.com/

puis :

curl -vkI https://mercure3.ajlsm.com/

Le premier doit normalement provoquer la redirection vers HTTPS.

Le second permettra notamment de vérifier :

  • la présentation du certificat Let's Encrypt ;
  • le passage par HAProxy ;
  • la sélection du backend MERCURE3 ;
  • la réponse du serveur Web de la VM.

Si le backend HTTPS ne sélectionne pas correctement le VirtualHost de MERCURE3, tester l'ajout du SNI dans le backend :

server SSLMERCURE3 10.0.0.43:443 check ssl verify none sni str(mercure3.ajlsm.com)

Après modification, toujours reprendre la séquence :

ansible-playbook ./plays/deploy.haproxy.yml \
  -l ajlsm_loadbalancer \
  --check \
  --diff

puis, si le contrôle est correct :

ansible-playbook ./plays/deploy.haproxy.yml \
  -l ajlsm_loadbalancer

et enfin :

ansible ajlsm_loadbalancer -b -m shell -a \
'haproxy -c -f /etc/haproxy/haproxy.cfg'

22. Résumé de l'architecture finale

[modifier | modifier le wikicode]
                    Internet
                       |
                       |
              mercure3.ajlsm.com
                51.83.117.113
                       |
                       v
              +----------------+
              | OPNsense FW1/2 |
              |      CARP      |
              +----------------+
                       |
                       | DNAT
                       v
                  10.0.0.32
                  VIP HAProxy
                       |
              +--------+--------+
              |                 |
              v                 v
         HAProxy1           HAProxy2
         10.0.0.30          10.0.0.31
              \                 /
               \               /
                \             /
                 v           v
                  10.0.0.43
                   MERCURE3
                 /          \
              :80            :443
             HTTP            HTTPS

Le certificat TLS public mercure3.ajlsm.com est présent sur chacun des deux HAProxy.

L'architecture permet ainsi de conserver l'adresse publique sur les firewalls, de centraliser le routage HTTP/HTTPS et les certificats sur les HAProxy, et de ne présenter à MERCURE3 que son adressage réseau interne.