Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 915 minIntermédiaire

Reverse proxy et répartition de charge : HAProxy sur pfSense

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • distinguer un proxy d'un reverse proxy et un reverse proxy d'un répartiteur ;
  • expliquer frontend, backend, ACL, terminaison TLS et contrôle de santé ;
  • publier un site avec HAProxy et ACME sur pfSense ;
  • configurer un reverse proxy Nginx ou HAProxy sous Debian.

4 exercices corrigés1 schéma

Un reverse proxy (proxy inverse) est un serveur placé devant un ou plusieurs serveurs web : il reçoit les requêtes des clients à leur place, les transmet au bon serveur, puis renvoie la réponse. Quand il répartit les requêtes entre plusieurs serveurs identiques, en vérifiant qu'ils sont en état de répondre, on l'appelle répartiteur de charge (load balancer). Ce chapitre explique à quoi sert un reverse proxy, ses notions (frontend, backend, terminaison TLS, contrôles de santé), sa mise en place avec le paquet HAProxy de pfSense pour publier le site de suivi de Sorbier, et l'équivalent avec Nginx. Les règles et la DMZ qui l'entourent sont dans le cours pfSense : DMZ et proxy inverse HAProxy.

Proxy ou reverse proxy ?

Proxy (direct, forward proxy)Reverse proxy
PlacéDevant les clientsDevant les serveurs
Il agit pour le compte deL'utilisateur qui navigueLe site qui est publié
Il sert àFiltrer et journaliser la navigation des salariés, mettre en cachePublier plusieurs sites sur une adresse, centraliser TLS, protéger et répartir
Le client sait-il qu'il existe ?Souvent oui (proxy configuré dans le navigateur, ou transparent)Non : pour le client, le reverse proxy est le site
ExemplesSquid, proxy d'un pare-feu nouvelle générationHAProxy, Nginx, Apache (mod_proxy), Traefik

Le proxy de filtrage de la navigation est traité dans Cybersécurité des infrastructures ; ce chapitre ne parle que du reverse proxy.

Ce qu'un reverse proxy apporte

Jusqu'ici, Sorbier publiait son site de suivi par une simple redirection de port (NAT) : le pare-feu envoyait tout le TCP 443 reçu sur 203.0.113.17 vers srv-web (192.168.10.225). Ça marche pour un site. Les limites arrivent vite :

  • Une seule adresse publique, un seul site par port. Avec du NAT, tout le TCP 443 va vers une seule machine. Un reverse proxy lit le nom demandé (en-tête Host, ou SNI en TLS) et envoie suivi.sorbier.example vers un serveur, portail.sorbier.example vers un autre, sur la même adresse et le même port.
  • Les certificats sont éparpillés. Le reverse proxy fait la terminaison TLS (SSL offloading) : il détient les certificats publics et les renouvelle (ACME) à un seul endroit.
  • Les serveurs sont exposés. Le client ne parle jamais directement à srv-web ; le reverse proxy peut rejeter les requêtes mal formées, limiter le débit, ajouter les en-têtes de sécurité, et, avec un module de pare-feu applicatif (WAF), bloquer des attaques web connues.
  • Une panne de serveur est une panne du site. Avec deux serveurs derrière lui, le reverse proxy répartit les requêtes et retire automatiquement celui qui ne répond plus.
Clientssur InternetHTTPS, port 443pfSense · paquet HAProxyFrontend ft-public203.0.113.17:443TLS déchiffré : certificat Let's EncryptACL : Host = suivi.sorbier.exampleautre nom : requête refuséeBackend bk-suivirépartition en tourniquetcontrôle de santé toutes les 2 sen-tête X-Forwarded-For ajoutéDMZ (VLAN 60)srv-web.225, HTTP 80srv-web2.227, plus tard
Le frontend reçoit et déchiffre, les règles choisissent le backend, le backend répartit entre les serveurs en bonne santé

Le vocabulaire de HAProxy

Les mêmes notions existent dans tous les reverse proxys, sous des noms proches.

NotionDéfinitionChez Sorbier
FrontendCe que voient les clients : une adresse, un port, éventuellement un certificat203.0.113.17:443, certificat Let's Encrypt de suivi.sorbier.example
BackendUn groupe de serveurs qui rendent le même service, et la façon de répartir entre euxbk-suivi : srv-web (et srv-web2 plus tard)
ACLUne condition testée sur la requête« le Host est suivi.sorbier.example »
ActionCe qu'on fait si la condition est vraie« utiliser le backend bk-suivi »
Contrôle de santé (health check)Une requête envoyée régulièrement à chaque serveur pour vérifier qu'il répondGET / toutes les 2 secondes, code 2xx ou 3xx attendu
Terminaison TLS (SSL offloading)Le proxy déchiffre TLS et parle au serveur en HTTPLe cas de Sorbier
Passage TLS (SSL passthrough)Le proxy transmet le flux chiffré sans le déchiffrer, d'après le SNIQuand le serveur doit garder lui-même son certificat
RechiffrementLe proxy déchiffre, inspecte, puis rechiffre vers le serveurQuand le réseau entre le proxy et le serveur n'est pas de confiance

Les algorithmes de répartition

Algorithme (nom HAProxy)FonctionnementQuand le choisir
Tourniquet (roundrobin)Chacun son tour, éventuellement selon un poidsServeurs identiques, requêtes courtes : le défaut
Moins de connexions (leastconn)Le serveur qui a le moins de connexions en coursConnexions longues (bases de données, bureaux à distance, WebSocket)
Adresse source (source)Un hachage de l'adresse du client : un client va toujours sur le même serveurApplication qui garde la session en mémoire, sans cookie possible
Affinité par cookieLe proxy pose un cookie qui renvoie le client vers le même serveurApplication à session locale, cas le plus courant

Avec des poids, un serveur de poids 3 reçoit trois fois plus de requêtes qu'un serveur de poids 1 : sur 100 requêtes, 75 et 25. La redondance complète d'un service (répartition, basculement, cluster) est traitée dans le cours Haute disponibilité.

Publier le site de suivi avec HAProxy sur pfSense

HAProxy est un paquet de pfSense. Le paquet acme obtient et renouvelle les certificats Let's Encrypt. Les étapes, avec les noms des menus de pfSense CE 2.8 :

1. Installer les paquets. System > Package Manager > Available Packages : installe acme, puis haproxy.

2. Libérer le port 443. L'interface d'administration de pfSense (webConfigurator) écoute par défaut sur le 443 de toutes les interfaces : HAProxy ne pourrait pas s'y installer. Dans System > Advanced > Admin Access, change le TCP port (par exemple 8443). L'interface d'administration ne doit, de toute façon, jamais être joignable depuis le WAN : les règles du pare-feu la réservent au VLAN d'administration.

3. Obtenir le certificat. Dans Services > Acme Certificates : onglet Account Keys, crée une clé de compte pour l'ACME Server « Let's Encrypt Production ACME v2 » et enregistre-la ; onglet Certificates, crée le certificat de suivi.sorbier.example avec une méthode de validation (défi DNS chez l'hébergeur de la zone, ou défi HTTP), puis Issue. Dans General Settings, active la tâche planifiée (Cron Entry) qui renouvelle les certificats.

4. Créer le backend. Services > HAProxy, onglet Backend, Add :

ChampValeur
Namebk-suivi
Server listMode active, Name srv-web, Address 192.168.10.225, Port 80, Encrypt (SSL) décoché
Loadbalancing OptionsRound robin
Health checking > Health check methodHTTP

5. Créer le frontend. Onglet Frontend, Add :

ChampValeur
Name et Statusft-public, Active
External addressListen address WAN address (IPv4), Port 443, SSL Offloading coché
Typehttp / https (offloading)
Access Control listsName acl-suivi, Expression Host matches:, Value suivi.sorbier.example
ActionsAction Use Backend, Condition acl names acl-suivi, backend bk-suivi
Default BackendAucun : une requête pour un autre nom est refusée
Use forwardfor optionCoché : ajoute l'en-tête X-Forwarded-For
SSL Offloading > CertificateLe certificat Let's Encrypt de l'étape 3

6. Activer HAProxy. Onglet Settings : coche Enable HAProxy, règle Maximum connections, puis Save et Apply Changes.

7. Adapter les règles du pare-feu. Supprime l'ancienne redirection de port 443 vers srv-web (Firewall > NAT). Dans Firewall > Rules > WAN, autorise TCP 443 à destination de WAN address (le pare-feu lui-même, où écoute HAProxy). Aucune règle n'est nécessaire sur la DMZ : les règles de pfSense filtrent le trafic qui entre par une interface, et le trafic émis par le pare-feu lui-même (HAProxy vers srv-web) est autorisé par défaut ; vérifie seulement que le pare-feu local de srv-web accepte TCP 80 depuis 192.168.10.238. Pour la redirection HTTP vers HTTPS, ajoute un second frontend sur le port 80 dont l'action redirige vers https, ou laisse srv-web renvoyer un 301.

L'adresse du vrai client

Derrière un reverse proxy, srv-web voit toutes les connexions venir du pare-feu (192.168.10.238), pas des clients. Ses journaux, ses statistiques et ses éventuelles protections par adresse deviennent inutiles. L'en-tête X-Forwarded-For, ajouté par le proxy (case Use forwardfor option), contient l'adresse du vrai client. Il faut dire au serveur web de la croire, mais seulement quand la requête vient du proxy :

nginx
# Sur srv-web, dans le bloc http ou server de Nginx
set_real_ip_from  192.168.10.238;
real_ip_header    X-Forwarded-For;

La même chose avec Nginx ou HAProxy sous Debian

Sans pfSense, le reverse proxy est un serveur Debian dans la DMZ. Avec Nginx :

nginx
upstream suivi {
    server 192.168.10.225:80 max_fails=3 fail_timeout=30s;
    server 192.168.10.227:80 max_fails=3 fail_timeout=30s;
}

server {
    listen 443 ssl;
    http2 on;
    server_name suivi.sorbier.example;
    ssl_certificate     /etc/letsencrypt/live/suivi.sorbier.example/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/suivi.sorbier.example/privkey.pem;

    location / {
        proxy_pass http://suivi;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Nginx libre ne fait que des contrôles de santé passifs : il retire un serveur après 3 échecs (max_fails) sur des requêtes réelles, pendant 30 secondes (fail_timeout). Les contrôles actifs, qui interrogent les serveurs en permanence, sont réservés à sa version commerciale. HAProxy (version 3.0 dans Debian 13) les fait en standard :

text
# /etc/haproxy/haproxy.cfg (extrait)
frontend ft-public
    bind :80
    bind :443 ssl crt /etc/haproxy/certs/
    mode http
    option forwardfor
    http-request redirect scheme https unless { ssl_fc }
    acl acl-suivi hdr(host) -i suivi.sorbier.example
    use_backend bk-suivi if acl-suivi

backend bk-suivi
    mode http
    balance roundrobin
    option httpchk GET /
    server srv-web  192.168.10.225:80 check inter 2s fall 3 rise 2
    server srv-web2 192.168.10.227:80 check inter 2s fall 3 rise 2

check inter 2s fall 3 rise 2 : un contrôle toutes les 2 secondes, un serveur déclaré hors service après 3 échecs consécutifs, et de retour après 2 succès. Vérifie la configuration avec haproxy -c -f /etc/haproxy/haproxy.cfg avant systemctl reload haproxy. La répartition de charge avec HAProxy et keepalived est déroulée pas à pas dans le cours Haute disponibilité.

Exercices

Exercice 1 sur 4 NAT ou reverse proxy ? Réussi À revoir

Sorbier veut publier sur sa seule adresse publique 203.0.113.17 : le site de suivi (srv-web, .225), un portail client sur un futur serveur srv-portail, et l'accès SSH de son prestataire à srv-web, sur un port non standard.

  1. Pourquoi une redirection de port (NAT) ne suffit-elle pas pour les deux sites ?
  2. Quel service publies-tu par HAProxy, lequel par une redirection de port ?
  3. Comment HAProxy sait-il vers quel serveur envoyer une requête HTTPS ?
Voir la réponseMasquer la réponse de l'exercice 1
  1. Une redirection de port envoie tout le TCP 443 de l'adresse publique vers une seule machine : impossible de servir deux sites différents sur le même port avec du NAT seul.
  2. Les deux sites web passent par HAProxy, qui les distingue par leur nom. L'accès SSH n'est pas du HTTP : une redirection de port dédiée (par exemple TCP 2222 vers .225:22), limitée à l'adresse publique du prestataire, ou mieux un VPN.
  3. Il déchiffre TLS avec le bon certificat (choisi grâce au SNI), puis lit l'en-tête Host de la requête et applique ses ACL (« Host est suivi.sorbier.example » → backend bk-suivi).

Tu avais trouvé ?

Exercice 2 sur 4 Le site répond 503 Réussi À revoir

Après une mise à jour de srv-web, le site de suivi répond 503 Service Unavailable à tous les clients. Depuis srv-web lui-même, curl -I http://127.0.0.1/ renvoie HTTP/1.1 302 Found vers /connexion. Le contrôle de santé de HAProxy est configuré avec la méthode HTTP, et le statut attendu « 200 ».

  1. Pourquoi HAProxy répond-il 503 ?
  2. Propose deux corrections.
Voir la réponseMasquer la réponse de l'exercice 2
  1. Le contrôle de santé reçoit un 302 au lieu du 200 attendu : HAProxy déclare srv-web hors service (DOWN). Le backend n'a plus aucun serveur disponible, d'où le 503. Le site fonctionne, c'est le contrôle qui est mal réglé après le changement de l'application.
  2. Faire porter le contrôle sur une page qui répond 200 sans authentification (une page de santé dédiée, /sante), ou accepter les codes 2xx et 3xx. Dans l'onglet Stats, vérifier ensuite que le serveur repasse en vert (UP).

Tu avais trouvé ?

Exercice 3 sur 4 Les poids Réussi À revoir

Le backend contient srv-web (poids 2) et srv-web2 (poids 1), en tourniquet.

  1. Sur 900 requêtes, combien chaque serveur en reçoit-il ?
  2. srv-web2 tombe. Que deviennent les requêtes ? Et les utilisateurs qui avaient une session sur srv-web2, si l'application garde les sessions en mémoire ?
  3. Quel réglage évite de perdre les sessions lors d'une maintenance planifiée de srv-web2 ?
Voir la réponseMasquer la réponse de l'exercice 3
  1. Poids total 3 : srv-web reçoit 2/3, soit 600 requêtes ; srv-web2 1/3, soit 300.
  2. Après l'échec des contrôles de santé, HAProxy envoie tout à srv-web. Les utilisateurs de srv-web2 perdent leur session (ils sont déconnectés) : la session était dans la mémoire du serveur tombé. La vraie parade est de stocker les sessions hors des serveurs web (base de données, cache partagé).
  3. Passer srv-web2 en mode drain (ou maintenance) dans HAProxy avant l'intervention : il ne reçoit plus de nouveaux clients, et les sessions en cours se terminent normalement. Avec une affinité par cookie, les clients restent sur leur serveur tant qu'il est disponible.

Tu avais trouvé ?

Exercice 4 sur 4 Les journaux de srv-web Réussi À revoir

Depuis la mise en place de HAProxy, le journal d'accès de srv-web ne contient plus qu'une seule adresse cliente : 192.168.10.238.

  1. Pourquoi ?
  2. Que configures-tu sur le pare-feu et sur srv-web pour retrouver les vraies adresses ?
  3. Quel risque y a-t-il à accepter l'en-tête X-Forwarded-For de n'importe quelle source ?
Voir la réponseMasquer la réponse de l'exercice 4
  1. C'est HAProxy, sur le pare-feu, qui ouvre les connexions vers srv-web, depuis son adresse dans la DMZ : srv-web ne voit plus les clients.
  2. Sur HAProxy, cocher Use forwardfor option dans le frontend. Sur srv-web (Nginx), set_real_ip_from 192.168.10.238; et real_ip_header X-Forwarded-For;, puis recharger Nginx.
  3. N'importe quel client pourrait usurper une adresse en écrivant lui-même l'en-tête, et fausser les journaux ou contourner une restriction par adresse. On ne l'accepte que s'il vient du proxy.

Tu avais trouvé ?

Chapitre terminé !

Fais les 4 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Messagerie : SMTP, IMAP, MX, SPF, DKIM et DMARCRevoir le sommaire du cours