1. The ACL concept #
Access Control Lists (ACLs) are the heart of HAProxy's intelligence. They define logical conditions based on almost any aspect of an HTTP request or a TCP connection. Once an ACL is defined, it can be used to make routing decisions, block traffic or modify headers.
Basic syntax #
The standard syntax of an ACL follows this pattern: acl <name> <criterion> [flags] <values>. It returns a boolean result (true/false).
# 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_imageIn this example, path_end analyzes the end of the URL. If the URL ends with one of the listed extensions, the ACL becomes 'true'. The use_backend directive runs only if this condition is met.
1.2 Detailed ACL configuration #
Each element of the ACL syntax plays a precise role in defining the condition.
#
A unique, descriptive identifier for your ACL. Use clear names that reflect the condition being tested (e.g. is_mobile, host_api, network_interne). This name is then used in if or unless rules.
(fetch method) #
The criterion, or 'fetch method', tells HAProxy which part of the request or connection to analyze. Here is a list of 50 essential criteria grouped by use:
1. Layer 4 (network and transport):src: client source IP address.src_port: client source TCP port.dst: destination IP address (IP of the HAProxy interface).dst_port: destination TCP port.fe_ip: frontend listening IP address.fe_port: frontend listening port.be_id: internal ID of the backend being processed.fc_err: detects whether a connection error occurred.
method: HTTP method (GET, POST, PUT, DELETE, etc.).path: full URI path (e.g. /index.html).path_beg: checks whether the path starts with a specific string.path_end: checks whether the path ends with a string.path_sub: checks whether a string is contained in the path.path_dir: checks whether a string matches a directory in the path.path_len: number of characters in the path.path_reg: regular expression match on the path.url: the full request URL (including parameters).url_beg: start of the URL.url_sub: substring present in the URL.base: concatenation of Host and path (e.g. example.com/api).
hdr(<name>): exact value of a header (e.g. Host, User-Agent).hdr_beg(<name>): the header starts with...hdr_end(<name>): the header ends with...hdr_sub(<name>): the header contains the substring...hdr_cnt(<name>): number of occurrences of a specific header.hdr_found(<name>): true if the header is present, whatever its value.hdr_val(<name>): extracts the integer value of a header.res.hdr(<name>): analyzes the server response headers.cook(<name>): value of a specific cookie.cook_beg(<name>): the cookie starts with...cook_sub(<name>): the cookie contains...cook_cnt(<name>): number of cookies in the request.
urlp(<name>): checks for a specific parameter in the request.urlp_val(<name>): extracts the integer value of a URL parameter.query: the full query string after the '?'.url_param_found: detects whether URL parameters are present.
ssl_fc: true if the connection is secure (SSL/TLS).ssl_fc_has_crt: true if the client presented a certificate.ssl_fc_sni: SNI (Server Name Indication) value sent by the client.ssl_fc_protocol: TLS protocol version used (e.g. TLSv1.3).ssl_fc_cipher: name of the negotiated cipher.ssl_fc_alg_keysize: size of the symmetric encryption key used.ssl_bc: true if the connection to the backend is secure.ssl_fc_is_resumed: detects whether the SSL session was resumed.
nbsrv(<backend>): number of servers 'UP' in a specific backend.srv_is_up(<server>): checks the health of a specific server.be_conn(<backend>): total number of active connections on a backend.fe_conn: number of active connections on the frontend.connslots(<backend>): number of connection slots still available.queue(<backend>): number of requests waiting in the backend queue.
[flags] #
Flags are optional modifiers that refine how the comparison behaves. The most common are:
-i: makes the comparison case-insensitive (e.g.hdr(Host) -i example.commatchesExample.com).-m <method>: specifies the matching method. Possible values includestr(exact string),sub(substring),beg(starts with),end(ends with),reg(regular expression),found(presence of the element),bool(boolean value).-f <file>: loads the values to compare from an external file, useful for long lists of IPs or User-Agents.
#
The data the criterion is compared with. Depending on the criterion and flags used, they can be one or more strings, IP addresses/CIDRs, numbers or regular expressions. If several values are specified, the ACL is true if the criterion matches any of the values (OR logic).
2. Use cases: routing by User-Agent and headers #
ACLs enable fine-grained routing based on the information contained in HTTP headers.
2.1 Routing by domain name (Host) #
Enables virtual hosting. The ACL extracts the value of the request's Host header.
acl host_api hdr(host) -i api.domaine.com
use_backend api_cluster if host_apiThe -i flag is crucial here: it makes the comparison case-insensitive. So 'API.domaine.com' and 'api.domaine.com' are both accepted.
2.2 Routing by URL path #
Ideal for URI-based microservice routing. path_beg tests the beginning of the path.
acl is_blog path_beg /blog
use_backend blog_servers if is_blogHere, path_beg (path begin) checks whether the URL starts with /blog. This covers /blog/article1 or /blog/images/logo.png.
2.3 Analyzing HTTP headers #
You can test any header (standard or custom). This enables fine-grained routing based on the application context.
# 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_tokenUsing -m found validates the simple existence of the X-Auth-Token header, regardless of its value. It is very useful to require security tokens before even processing them.
2.4 Filtering by User-Agent #
The User-Agent header identifies the client. It is essential for mobile redirection or fighting 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_botThe hdr_sub (header substring) method checks whether the specified value appears anywhere in the User-Agent string. It is more flexible than hdr, which would require an exact match.
3. Access control and security #
ACLs are fundamental to secure your applications by filtering incoming traffic.
IP-based restriction (whitelist/blacklist) #
You can allow or block access based on the source IP address (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_interneThe src criterion identifies the IP address of the client initiating the connection. The exclamation mark ! in front of network_interne means "if the request comes from anywhere EXCEPT the internal network".
HTTP authentication #
Combine ACLs with userlist sections to require authentication on sensitive paths.
userlist admins
user martin password password123
acl auth_ok http_auth(admins)
http-request auth realm Protection if is_admin !auth_okThe http_auth function checks whether the credentials sent in the Authorization header match those defined in the userlist section. If not (!auth_ok), HAProxy returns a 401 code to the browser.
4. Focus on geolocation #
Making decisions based on the visitor's geographic origin.
Routing by country #
Using GeoIP2 databases or headers injected by an upstream CDN, you can target geographic areas.
# 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_countriesThis technique relies on the upstream service (such as Cloudflare or Akamai) having already identified the geographic origin and passed it through a specific HTTP header. If you manage your own MaxMind database natively in HAProxy, you will instead use the src_get_gpc0 fetch or dedicated converters.
5. Logical operators #
Combining several ACLs to create complex decision rules.
AND, OR and NOT #
ACL logic follows simple rules:
- AND (implicit): place ACLs next to each other on the same line (e.g.
if acl1 acl2). - OR (explicit): use the
||operator or define several action lines. - NOT: use the exclamation mark
!in front of the ACL name.
# 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_localUsing curly braces { ... } creates anonymous ACLs or groups complex conditions without defining them beforehand. In this example, HAProxy blocks the request if someone tries to access the admin area OR if the server is in maintenance, UNLESS the connection comes from the local machine.
Conclusion #
Power in the service of architecture.
A Swiss Army knife for DevOps #
Mastering ACLs turns HAProxy from a simple load balancer into a true intelligent traffic control engine. Whether you implement blue/green deployments, secure endpoints or optimize the user experience through geolocation, ACLs are your main tool.
My progress
Sign in to track your progress and take notes. Sign in
💬 Questions about this lesson
No questions yet: be the first to ask for help or share your configuration.
Recommended Articles
Mastering ACLs in HAProxy
A complete guide to HAProxy ACLs: learn how to configure smart routing, IP-based access control, ...
HAProxy: a detailed guide to configuration directives
A complete exploration of HAProxy's essential directives: from bind to http-check, learn how to c...
HAProxy and SSL: TLS termination, SSL passthrough and hardening
HAProxy and SSL/TLS: SSL termination, SSL passthrough in TCP mode with SNI routing, re-encryption...
HAProxy as a Kubernetes Ingress Controller: the production guide
Learn how to use HAProxy as an Ingress Controller in Kubernetes: direct-to-pod architecture, TLS ...
The ACME protocol: ACME server, http-01 and dns-01 challenges, TLS automation
Understand the ACME protocol: the role of the ACME server (Let's Encrypt, ZeroSSL, step-ca), the ...
HAProxy best practices: optimization, security and high availability
Discover the best practices for configuring HAProxy to ensure the performance, security and resil...
Managing SSL/TLS certificates with Let's Encrypt and ACME
Learn how to automate the generation and renewal of your SSL/TLS certificates with Let's Encrypt....
HAProxy in Kubernetes: the high-performance Ingress Controller
Discover in depth how HAProxy integrates with Kubernetes: direct-to-pod architecture, hot update ...
Health checks and high availability
How HAProxy detects failures and handles automatic failover to healthy servers.