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
Cas d'application : préparation de la future VM MERCURE3
1. Objet
[modifier | modifier le wikicode]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.
Émission
[modifier | modifier le wikicode]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.