CVE Watch
Cybersécuritédevsecops7 min de lecture

HAProxy en pratique : load balancing et haute disponibilité sur Ubuntu

MB
Massioudath Bankole
17 mai 2026 · 94 vues

1. Qu'est-ce que HAProxy ?

HAProxy (High Availability Proxy) est un load balancer et reverse proxy open source haute performance. Il est utilisé dans la majorité des grandes infrastructures web pour répartir le trafic entre plusieurs serveurs et garantir la disponibilité des services.

HAProxy vs Nginx

FonctionnalitéHAProxyNginx
Load balancingSpécialisé, très avancéBasique
Reverse proxyOuiOui (principale fonction)
Serveur de fichiers statiquesNonOui
Health checksTrès avancésBasiques
Dashboard de statsIntégréNon (module externe)
PerformanceExtrême (millions de connexions)Très bonne

Règle simple : Nginx pour servir du contenu, HAProxy pour distribuer le trafic.

Architecture type en production

Internet
    ↓
HAProxy (point d'entrée unique)
    ↓           ↓           ↓
Serveur 1   Serveur 2   Serveur 3

2. Concepts clés

Frontend

Point d'entrée du trafic. HAProxy écoute sur un port et attend les connexions entrantes.

Backend

Groupe de serveurs qui vont répondre aux requêtes. HAProxy choisit quel serveur utiliser selon l'algorithme de load balancing configuré.

Health Check

Vérification régulière de l'état de chaque serveur backend. Si un serveur ne répond plus, HAProxy l'exclut automatiquement de la rotation et y renvoie le trafic dès qu'il revient.

Load Balancing

Répartition du trafic entre plusieurs serveurs selon un algorithme défini.


3. Architecture du Lab

Infrastructure mise en place

┌─────────────────────────────────────────────────────┐
│                    VMware Workstation                │
│                                                     │
│  ┌──────────────────┐                               │
│  │   haproxy-lb     │                               │
│  │ 192.168.145.134  │ ← Point d'entrée unique       │
│  │   HAProxy 2.8    │                               │
│  └────────┬─────────┘                               │
│           │ Round Robin                             │
│     ┌─────┴──────┐                                  │
│     ↓            ↓                                  │
│  ┌──────────┐  ┌──────────┐                         │
│  │backend-  │  │backend-  │                         │
│  │web       │  │web2      │                         │
│  │.135:8080 │  │.136:8080 │                         │
│  │Nginx     │  │Nginx     │                         │
│  └──────────┘  └──────────┘                         │
└─────────────────────────────────────────────────────┘

4. Installation

sudo apt update
sudo apt install haproxy -y
sudo systemctl status haproxy

Fichiers importants

FichierRôle
/etc/haproxy/haproxy.cfgFichier de configuration principal
/var/log/haproxy.logLogs HAProxy
/run/haproxy/haproxy.pidPID du processus

5. Configuration complète commentée

global
    log /dev/log local0
    # Envoie les logs vers syslog
    # local0 = facilité syslog utilisée par HAProxy
    
    maxconn 2000
    # Nombre maximum de connexions simultanées
    
    daemon
    # HAProxy tourne en arrière-plan comme un daemon système

defaults
    log global
    # Hérite de la configuration de logs définie dans "global"
    
    mode http
    # Mode HTTP : analyse et comprend le protocole HTTP (layer 7)
    # mode tcp : passe le trafic sans l'analyser (layer 4, plus rapide)
    
    option httplog
    # Active les logs détaillés HTTP
    
    timeout connect 5s
    # Délai maximum pour établir la connexion avec un backend
    
    timeout client 30s
    # Délai maximum d'inactivité côté client
    
    timeout server 30s
    # Délai maximum d'inactivité côté serveur backend

frontend web_frontend
    bind *:80
    # Écoute sur toutes les interfaces sur le port 80
    
    default_backend web_backend
    # Envoie tout le trafic vers le groupe "web_backend"

backend web_backend
    balance roundrobin
    # Algorithme de répartition : chaque serveur à son tour
    
    server backend1 192.168.145.135:8080 check
    # nom : backend1 | ip:port | check = health check activé
    
    server backend2 192.168.145.136:8080 check

listen stats
    bind *:8404
    # Dashboard accessible sur le port 8404
    
    stats enable
    stats uri /stats
    # URL : http://IP:8404/stats
    
    stats refresh 10s
    # Rafraîchissement automatique toutes les 10 secondes

6. Dashboard de monitoring

Le dashboard HAProxy accessible sur http://192.168.145.134:8404/stats affiche en temps réel l'état de tous les serveurs.

up.png

Colonnes importantes

ColonneSignification
StatusÉtat du serveur (UP/DOWN)
LastChkRésultat du dernier health check
Sessions TotalNombre total de connexions traitées
Bytes In/OutVolume de données transférées
DwntmeTemps total passé en état DOWN

7. Load Balancing Round Robin en action

La commande suivante envoie 6 requêtes successives à HAProxy et montre la répartition entre les deux backends :

for i in {1..6}; do curl http://192.168.145.134; echo; done

cap2.png

Le résultat montre que les requêtes alternent parfaitement entre backend-web et backend-web2 - c'est le Round Robin en action.


8. Health Check - Détection automatique de panne

Quand un backend tombe, HAProxy le détecte en quelques secondes et redirige tout le trafic vers les serveurs disponibles.

Simulation de panne

# Sur backend-web : désactiver le service
sudo rm /etc/nginx/sites-enabled/backend-lab
sudo systemctl reload nginx

cap3.png

Ce qu'on observe

  • backend1 passe en rouge avec le statut DOWN
  • backend2 continue en vert avec le statut UP
  • HAProxy redirige automatiquement tout le trafic vers backend2
  • Aucune interruption de service pour l'utilisateur

Réintégration automatique

Quand le serveur revient :

# Sur backend-web : réactiver le service
sudo ln -s /etc/nginx/sites-available/backend-lab /etc/nginx/sites-enabled/
sudo systemctl reload nginx

HAProxy détecte que backend1 est de nouveau disponible et le réintègre dans la rotation sans intervention manuelle.


9. Algorithmes de load balancing

Round Robin (défaut)

balance roundrobin

Distribue les requêtes à tour de rôle. Idéal pour : serveurs avec des capacités identiques.

Least Connections

balance leastconn

Envoie la requête au serveur qui a le moins de connexions actives. Idéal pour : requêtes de durée variable (sessions longues).

Source (IP Hash)

balance source

Le même client est toujours envoyé vers le même serveur. Idéal pour : applications avec sessions sans mécanisme de session partagée.

Weighted Round Robin

server backend1 192.168.145.135:8080 check weight 3
server backend2 192.168.145.136:8080 check weight 1

backend1 reçoit 3x plus de trafic que backend2. Idéal pour : serveurs avec des capacités différentes.


10. Health Check avancé

# Health check TCP (par défaut)
server backend1 192.168.145.135:8080 check

# Health check HTTP
option httpchk GET /health
server backend1 192.168.145.135:8080 check

# Paramètres avancés
server backend1 192.168.145.135:8080 check inter 2s fall 3 rise 2
# inter 2s  : vérification toutes les 2 secondes
# fall 3    : 3 échecs consécutifs → serveur DOWN
# rise 2    : 2 succès consécutifs → serveur UP

États possibles

CouleurÉtatSignification
VertUPServeur opérationnel
RougeDOWNServeur hors service
Jaunegoing downServeur en train de tomber
Orangegoing upServeur en train de revenir

11. Serveur Backup

Un serveur backup ne reçoit du trafic que si tous les serveurs actifs sont down.

backend web_backend
    balance roundrobin
    server backend1 192.168.145.135:8080 check
    server backend2 192.168.145.136:8080 check
    server backup1  192.168.145.137:8080 check backup

12. ACL - Routage conditionnel

Les ACL (Access Control Lists) permettent de router le trafic selon des règles précises : URL, domaine, headers, IP du client...

Principe

Requête arrive sur HAProxy
        ↓
HAProxy évalue les ACL
        ↓
/api/* → api_backend (backend1)
/web/* → web_backend (backend2)
autre  → api_backend (défaut)

Configuration utilisée dans le lab

frontend web_frontend
    bind *:80
    
    # Définition des ACL
    acl is_api path_beg /api/
    # path_beg = "path begins with" (l'URL commence par)
    
    acl is_web path_beg /web/
    
    # Routage selon les ACL
    use_backend api_backend if is_api
    use_backend web_backend if is_web
    default_backend api_backend
    # Si aucune ACL ne correspond → api_backend par défaut

backend api_backend
    balance roundrobin
    server backend1 192.168.145.135:8080 check

backend web_backend
    balance roundrobin
    server backend2 192.168.145.136:8080 check

Test des ACL

# Doit aller vers backend1 (api_backend)
curl http://192.168.145.134/api/test

# Doit aller vers backend2 (web_backend)
curl http://192.168.145.134/web/test

acl.png

Résultat observé

/api/test → Backend Web (backend1) ← api_backend
/web/test → Backend Web 2 (backend2) ← web_backend

Autres types d'ACL

# Router selon le domaine
acl is_api hdr(host) -i api.monsite.com
acl is_blog hdr(host) -i blog.monsite.com

# Router selon un header HTTP
acl is_mobile hdr(User-Agent) -i -m sub Mobile

# Router selon l'IP source
acl is_internal src 192.168.0.0/16

# Router selon la méthode HTTP
acl is_post method POST

13. Rate Limiting - Protection contre les abus

Le rate limiting permet de limiter le nombre de requêtes par IP sur une période donnée. C'est une protection essentielle contre les attaques DDoS et le brute force.

Configuration

frontend web_frontend
    bind *:80
    
    # Créer une table pour compter les requêtes par IP
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    # type ip       : indexé par adresse IP
    # size 100k     : jusqu'à 100 000 IPs suivies simultanément
    # expire 30s    : entrée supprimée après 30s d'inactivité
    # http_req_rate(10s) : compteur de requêtes sur 10 secondes
    
    # Suivre l'IP du client
    http-request track-sc0 src
    # track-sc0 : utilise le compteur 0 (sticky counter 0)
    # src       : indexé par IP source du client
    
    # Bloquer si plus de 10 requêtes en 10 secondes
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 10 }
    # deny_status 429 : retourne HTTP 429 Too Many Requests
    # sc_http_req_rate(0) gt 10 : si le compteur dépasse 10
    
    acl is_api path_beg /api/
    acl is_web path_beg /web/
    use_backend api_backend if is_api
    use_backend web_backend if is_web
    default_backend api_backend

Test du rate limiting

for i in {1..15}; do curl -s -o /dev/null -w "%{http_code}\n" http://192.168.145.134/api/test; done

Capture d'écran 2026-05-17 163837.png

Résultat observé

200  ← requête 1
200  ← requête 2
...
200  ← requête 10
429  ← requête 11 (bloquée)
429  ← requête 12 (bloquée)
429  ← requête 13 (bloquée)
429  ← requête 14 (bloquée)
429  ← requête 15 (bloquée)

Après 10 requêtes en 10 secondes depuis la même IP, HAProxy retourne automatiquement 429 Too Many Requests sans même contacter les backends.

Pourquoi c'est important

En production, le rate limiting protège contre :

  • Les attaques par force brute sur les endpoints d'authentification
  • Les attaques DDoS par flood de requêtes
  • Le scraping abusif
  • Les bots malveillants

14. SSL/TLS - Terminaison HTTPS

La terminaison SSL dans HAProxy signifie que HAProxy gère tout le chiffrement HTTPS côté client et communique en HTTP simple avec les backends en interne.

Client → HTTPS → HAProxy (déchiffre SSL) → HTTP → Backend

Avantages

  • Les backends n'ont pas besoin de certificat SSL
  • Gestion centralisée des certificats
  • Moins de charge CPU sur les backends
  • Configuration SSL en un seul endroit

Générer un certificat auto-signé (lab)

sudo mkdir -p /etc/haproxy/certs

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/haproxy/certs/haproxy.key \
  -out /etc/haproxy/certs/haproxy.crt \
  -subj "/C=FR/ST=IDF/L=Paris/O=TJEH/CN=haproxy-lab.local"

HAProxy a besoin d'un fichier unique combinant certificat et clé :

sudo cat /etc/haproxy/certs/haproxy.crt /etc/haproxy/certs/haproxy.key \
  | sudo tee /etc/haproxy/certs/haproxy.pem

sudo chmod 600 /etc/haproxy/certs/haproxy.pem

Configuration HAProxy avec SSL

frontend web_frontend_http
    bind *:80
    # Redirection automatique HTTP → HTTPS
    http-request redirect scheme https unless { ssl_fc }
    # ssl_fc = "SSL/TLS front connection"
    # unless = sauf si la connexion est déjà en HTTPS

frontend web_frontend_https
    bind *:443 ssl crt /etc/haproxy/certs/haproxy.pem
    # ssl    = active SSL/TLS
    # crt    = chemin vers le fichier .pem (cert + clé)
    
    # Rate limiting
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 10 }
    
    # ACL
    acl is_api path_beg /api/
    acl is_web path_beg /web/
    use_backend api_backend if is_api
    use_backend web_backend if is_web
    default_backend api_backend

Vérification du certificat

# Vérifier que le port 443 écoute
sudo ss -tlnp | grep :443

# Inspecter le certificat
echo | openssl s_client -connect 192.168.145.134:443 2>/dev/null \
  | openssl x509 -noout -dates

Résultat observé dans le lab :

notBefore=May 17 14:46:36 2026 GMT
notAfter=May 17 14:46:36 2027 GMT
Protocole : TLSv1.3
Cipher    : TLS_AES_256_GCM_SHA384
Clé RSA   : 2048 bits

Test de la redirection HTTP → HTTPS

# Doit retourner 302 Found (redirection vers HTTPS)
curl -v http://192.168.145.134/api/test 2>&1 | grep -E "Location|HTTP/"

# Test HTTPS (-k pour ignorer l'avertissement du certificat auto-signé)
curl -k https://192.168.145.134/api/test

En production avec Let's Encrypt

En production on remplace le certificat auto-signé par un certificat Let's Encrypt gratuit et reconnu par tous les navigateurs :

# Installer Certbot
sudo apt install certbot -y

# Générer le certificat
sudo certbot certonly --standalone -d mondomaine.com

# Combiner pour HAProxy
sudo cat /etc/letsencrypt/live/mondomaine.com/fullchain.pem \
         /etc/letsencrypt/live/mondomaine.com/privkey.pem \
         | sudo tee /etc/haproxy/certs/mondomaine.pem

# Renouvellement automatique (cron)
echo "0 0 * * * certbot renew --quiet && systemctl reload haproxy" \
  | sudo tee -a /etc/crontab

15. Sécuriser le Dashboard

En production, le dashboard ne doit jamais être accessible sans authentification.

listen stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s
    stats auth admin:motdepasse_fort
    stats hide-version
    stats show-node

16. Commandes utiles

# Vérifier la syntaxe de la config
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

# Recharger sans interruption de service
sudo systemctl reload haproxy

# Redémarrer
sudo systemctl restart haproxy

# Logs en temps réel
sudo tail -f /var/log/haproxy.log

# Sauvegarder la config
sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak

17. Cas d'usage en production

Haute disponibilité web

Internet → HAProxy → [Nginx 1, Nginx 2, Nginx 3]

Si un serveur tombe, les autres continuent - aucune interruption de service.

Séparation API / Frontend

Internet → HAProxy
    /api/* → Backend FastAPI [API 1, API 2]
    /*     → Frontend Next.js [Web 1, Web 2]

Déploiement sans interruption (Blue/Green)

1. Déployer la nouvelle version sur backend2
2. Retirer backend1 de la rotation
3. Tester backend2 en production
4. Remettre backend1 avec la nouvelle version
5. Résultat : zéro downtime

Sources

devsecopslinux
Partager cet article

Commentaires (0)

Sois le premier à commenter !

Articles similaires