Publié le : 06/12/2024 à 10:00 Mis à jour le : 10/06/2026 à 17:56 Vues : 548

Guide complet sur les ACLs HAProxy : apprenez à configurer le routage intelligent, le contrôle d'accès par IP, la géolocalisation, et l'analyse des Headers et User-Agent pour sécuriser et optimiser vos flux.

1. Le concept d'ACL

Les Access Control Lists (ACL) sont le cœur de l'intelligence de HAProxy. Elles permettent de définir des conditions logiques basées sur presque n'importe quel aspect d'une requête HTTP ou d'une connexion TCP. Une fois qu'une ACL est définie, elle peut être utilisée pour prendre des décisions de routage, bloquer du trafic, ou modifier des headers.

Syntaxe de base

La syntaxe standard d'une ACL suit ce schéma : acl <nom> <critère> [flags] <valeurs>. Elle renvoie un résultat booléen (vrai/faux).

# Définition : le chemin se termine par une extension d'image
acl est_image path_end .jpg .png .gif

# Utilisation : router vers le backend statique si l'ACL est vraie
use_backend static_servers if est_image

Dans cet exemple, path_end analyse la fin de l'URL. Si l'URL se termine par l'une des extensions listées, l'ACL devient 'vraie'. La directive use_backend n'est exécutée que si cette condition est remplie.

1.2 Configuration détaillée de l'ACL

Chaque élément de la syntaxe d'une ACL joue un rôle précis dans la définition de la condition.

<nom>

C'est un identifiant unique et descriptif pour votre ACL. Il est recommandé d'utiliser des noms clairs qui reflètent la condition testée (ex: is_mobile, host_api, network_interne). Ce nom sera ensuite utilisé dans les règles if ou unless.

<critère> (Fetch Method)

Le critère, ou 'fetch method', indique à HAProxy quelle partie de la requête ou de la connexion il doit analyser. Voici une liste de 50 critères incontournables classés par usage :

1. Couche 4 (Réseau et Transport) :
  • src : Adresse IP source du client.
  • src_port : Port TCP source du client.
  • dst : Adresse IP de destination (IP de l'interface HAProxy).
  • dst_port : Port TCP de destination.
  • fe_ip : Adresse IP d'écoute du frontend.
  • fe_port : Port d'écoute du frontend.
  • be_id : Identifiant interne du backend traité.
  • fc_err : Détecte si une erreur de connexion est survenue.
2. Couche 7 (HTTP - URI, Chemin et Méthode) :
  • method : Méthode HTTP (GET, POST, PUT, DELETE, etc.).
  • path : Chemin complet de l'URI (ex: /index.html).
  • path_beg : Vérifie si le chemin commence par une chaîne spécifique.
  • path_end : Vérifie si le chemin se termine par une chaîne.
  • path_sub : Vérifie si une chaîne est contenue dans le chemin.
  • path_dir : Vérifie si une chaîne correspond à un répertoire dans le chemin.
  • path_len : Nombre de caractères composant le chemin.
  • path_reg : Correspondance par expression régulière sur le chemin.
  • url : L'URL complète de la requête (incluant les paramètres).
  • url_beg : Début de l'URL.
  • url_sub : Sous-chaîne présente dans l'URL.
  • base : Concaténation du Host et du Path (ex: example.com/api).
3. En-têtes (Headers) et Cookies :
  • hdr(<nom>) : Valeur exacte d'un en-tête (ex: Host, User-Agent).
  • hdr_beg(<nom>) : L'en-tête commence par...
  • hdr_end(<nom>) : L'en-tête se termine par...
  • hdr_sub(<nom>) : L'en-tête contient la sous-chaîne...
  • hdr_cnt(<nom>) : Nombre d'occurrences d'un en-tête spécifique.
  • hdr_found(<nom>) : Vrai si l'en-tête est présent, quelle que soit sa valeur.
  • hdr_val(<nom>) : Extrait la valeur entière d'un en-tête.
  • res.hdr(<nom>) : Analyse les en-têtes de la réponse serveur.
  • cook(<nom>) : Valeur d'un cookie spécifique.
  • cook_beg(<nom>) : Le cookie commence par...
  • cook_sub(<nom>) : Le cookie contient...
  • cook_cnt(<nom>) : Nombre de cookies présents dans la requête.
4. Paramètres d'URL (Query String) :
  • urlp(<nom>) : Vérifie la présence d'un paramètre spécifique dans la requête.
  • urlp_val(<nom>) : Extrait la valeur entière d'un paramètre d'URL.
  • query : La chaîne de requête complète située après le '?'.
  • url_param_found : Détecte si des paramètres d'URL sont présents.
5. SSL / TLS :
  • ssl_fc : Vrai si la connexion est sécurisée (SSL/TLS).
  • ssl_fc_has_crt : Vrai si le client a présenté un certificat.
  • ssl_fc_sni : Valeur du SNI (Server Name Indication) envoyé par le client.
  • ssl_fc_protocol : Version du protocole TLS utilisé (ex: TLSv1.3).
  • ssl_fc_cipher : Nom de l'algorithme de chiffrement négocié.
  • ssl_fc_alg_keysize : Taille de la clé de chiffrement symétrique utilisée.
  • ssl_bc : Vrai si la connexion vers le backend est sécurisée.
  • ssl_fc_is_resumed : Détecte si la session SSL a été reprise.
6. État de l'Infrastructure (Health & Load) :
  • nbsrv(<backend>) : Nombre de serveurs 'UP' dans un backend spécifique.
  • srv_is_up(<serveur>) : Vérifie l'état de santé d'un serveur précis.
  • be_conn(<backend>) : Nombre total de connexions actives sur un backend.
  • fe_conn : Nombre de connexions actives sur le frontend.
  • connslots(<backend>) : Nombre de slots de connexion encore disponibles.
  • queue(<backend>) : Nombre de requêtes en attente dans la file du backend.

[flags]

Les flags sont des modificateurs optionnels qui affinent le comportement de la comparaison. Les plus courants sont :

  • -i : Rend la comparaison insensible à la casse (ex: hdr(Host) -i example.com correspondra à Example.com).
  • -m <méthode> : Spécifie la méthode de correspondance. Les valeurs possibles incluent str (chaîne exacte), sub (sous-chaîne), beg (commence par), end (finit par), reg (expression régulière), found (présence de l'élément), bool (valeur booléenne).
  • -f <fichier> : Permet de charger les valeurs à comparer depuis un fichier externe, utile pour les longues listes d'IP ou de User-Agents.

<valeurs>

Ce sont les données avec lesquelles le critère doit être comparé. Elles peuvent être une ou plusieurs chaînes de caractères, des adresses IP/CIDR, des nombres, ou des expressions régulières, en fonction du critère et des flags utilisés. Si plusieurs valeurs sont spécifiées, l'ACL est vraie si le critère correspond à l'une des valeurs (logique OU).

2. Les critères de sélection courants

HAProxy propose des centaines de méthodes d'extraction (fetch methods). Voici les plus couramment utilisées pour l'analyse des requêtes.

2.1 Nom de domaine (Host)

Permet le virtual hosting. L'ACL extrait la valeur du header Host de la requête.

acl host_api hdr(host) -i api.domaine.com
use_backend api_cluster if host_api

Le flag -i est crucial ici : il rend la comparaison insensible à la casse. Ainsi, 'API.domaine.com' ou 'api.domaine.com' seront tous deux acceptés.

2.2 Chemin d'URL (Path)

Idéal pour le routage de microservices basé sur l'URI. path_beg teste le début du chemin.

acl is_blog path_beg /blog
use_backend blog_servers if is_blog

Ici, path_beg (Path Begin) vérifie si l'URL commence par /blog. Cela englobe /blog/article1 ou /blog/images/logo.png.

2.3 Headers HTTP

Vous pouvez tester n'importe quel header (Standard ou Custom). Cela permet un routage fin basé sur le contexte applicatif.

# Vérifier si la requête attend du JSON
acl wants_json hdr(Accept) -i application/json

# Vérifier la présence d'un header d'authentification custom
acl has_auth_token hdr(X-Auth-Token) -m found

use_backend json_api if wants_json has_auth_token

L'utilisation de -m found permet de valider la simple existence du header X-Auth-Token, sans se soucier de sa valeur. C'est très utile pour forcer la présence de jetons de sécurité avant même de les traiter.

2.4 User-Agent

Le header User-Agent permet d'identifier le client. C'est essentiel pour la redirection mobile ou la lutte contre les bots.

# Détecter les mobiles pour redirection
acl is_mobile hdr_sub(user-agent) -i android iphone
redirect prefix https://m.monsite.com if is_mobile

# Bloquer un bot par son nom
acl is_bad_bot hdr_sub(user-agent) -i badbot
http-request deny if is_bad_bot

La méthode hdr_sub (Header Substring) cherche si la valeur spécifiée est contenue n'importe où dans la chaîne du User-Agent. C'est plus flexible que hdr qui exigerait une correspondance exacte.

3. Contrôle d'accès et Sécurité

Les ACLs sont fondamentales pour sécuriser vos applications en filtrant le trafic entrant.

Limitation par IP (Whitelist/Blacklist)

Vous pouvez autoriser ou bloquer des accès basés sur l'adresse IP source (src).

acl network_interne src 10.0.0.0/8
acl is_admin path_beg /admin

# Bloquer l'accès admin si l'IP n'est pas dans le réseau interne
http-request deny if is_admin !network_interne

Le critère src identifie l'adresse IP du client qui initie la connexion. L'usage du point d'exclamation ! devant network_interne signifie "Si la requête provient de n'importe où SAUF du réseau interne".

Authentification HTTP

Combinez les ACLs avec des userlist pour forcer une authentification sur des chemins sensibles.

userlist admins
  user martin password password123

acl auth_ok http_auth(admins)
http-request auth realm Protection if is_admin !auth_ok

La fonction http_auth vérifie si les identifiants envoyés dans le header Authorization correspondent à ceux définis dans la section userlist. Si ce n'est pas le cas (!auth_ok), HAProxy renvoie un code 401 au navigateur.

4. Géolocalisation

Prendre des décisions basées sur l'origine géographique du visiteur.

Routage par pays

En utilisant des bases GeoIP2 ou des headers injectés par un CDN amont, vous pouvez cibler des zones géographiques.

# Exemple basé sur un header injecté par un CDN amont
acl is_france hdr(X-Country-Code) -i FR
use_backend fr_cluster if is_france

# Bloquer certains pays pour des raisons légales ou de sécurité
acl blocked_countries hdr(X-Country-Code) -i CN RU
http-request deny if blocked_countries

Cette technique repose sur le fait que le service en amont (comme Cloudflare ou Akamai) a déjà identifié l'origine géographique et l'a transmise via un header HTTP spécifique. Si vous gérez votre propre base MaxMind nativement dans HAProxy, vous utiliserez plutôt le fetch src_get_gpc0 ou des convertisseurs dédiés.

5. Opérateurs logiques

Combiner plusieurs ACLs pour créer des règles de décision complexes.

ET, OU et NON

La logique d'application des ACLs suit des règles simples :

  • ET (Implicite) : Juxtaposer des ACLs sur la même ligne (ex: if acl1 acl2).
  • OU (Explicite) : Utiliser l'opérateur || ou définir plusieurs lignes d'action.
  • NON : Utiliser le point d'exclamation ! devant le nom de l'ACL.
# Si (Admin OU Maintenance) ET (Pas Local)
acl is_admin path_beg /admin
acl is_maint nbsrv(maint_backend) lt 1
acl is_local src 127.0.0.1

http-request deny if { is_admin || is_maint } !is_local

L'utilisation des accolades { ... } permet de créer des ACLs anonymes ou de grouper des conditions complexes sans avoir à les définir au préalable. Dans cet exemple, HAProxy bloque la requête si l'on tente d'accéder à l'admin OU si le serveur est en maintenance, SAUF si l'on se connecte depuis la machine locale.

Conclusion

La puissance au service de l'architecture.

Un couteau suisse pour le DevOps

La maîtrise des ACLs transforme HAProxy d'un simple répartiteur de charge en un véritable moteur de contrôle de trafic intelligent. Que ce soit pour implémenter du Blue/Green deployment, sécuriser des endpoints ou optimiser l'expérience utilisateur par la géolocalisation, les ACLs sont votre outil principal.

À propos de cet article

Auteur(s) : Martin LEKPA (Tech Lead et formateur Observabilité)

Mots-clés : HAProxy ACL routing path_beg hdr condition redirection contrôle d'accès géolocalisation User-Agent Headers HTTP sécurité Blue/Green SSL TLS SNI backend frontend health check query string cookie load balancing reverse proxy filtrage DevOps src src_port dst dst_port fe_ip fe_port be_id fc_err method path path_end path_sub path_dir path_len path_reg url url_beg url_sub base hdr_beg hdr_end hdr_sub hdr_cnt hdr_found hdr_val res.hdr cook cook_beg cook_sub cook_cnt urlp urlp_val query url_param_found ssl_fc ssl_fc_has_crt ssl_fc_sni ssl_fc_protocol ssl_fc_cipher ssl_fc_alg_keysize ssl_bc ssl_fc_is_resumed nbsrv srv_is_up be_conn fe_conn connslots queue

Envie d'aller plus loin ?

Lien copié dans le presse-papiers !