RousselTMLEARNING

Proxy & networking

Mastering ACLs in HAProxy: the complete guide

A complete guide to HAProxy ACLs: learn how to configure smart routing, IP-based access control, geolocation, and header and User-Agent analysis to secure and optimize your traffic.

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_image

In 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.
2. Layer 7 (HTTP: URI, path and method):
  • 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).
3. Headers and cookies:
  • 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.
4. URL parameters (query string):
  • 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.
5. SSL / TLS:
  • 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.
6. Infrastructure state (health & load):
  • 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.com matches Example.com).
  • -m <method>: specifies the matching method. Possible values include str (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_api

The -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_blog

Here, 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_token

Using -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_bot

The 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_interne

The 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_ok

The 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_countries

This 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_local

Using 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.

Related articles

Anatomy of HAProxy configuration, clustering and high availability

Understand the structure of an haproxy.cfg file: the global, defaults, frontend (high performance), backend a…

HAProxy in Kubernetes: the high-performance Ingress Controller

Discover in depth how HAProxy integrates with Kubernetes: direct-to-pod architecture, hot update options (DNS…

What's new in HAProxy: OpenTelemetry, native JWT and performance optimizations

Explore HAProxy's latest innovations: native OpenTelemetry support for observability, JWT validation at the e…

Keep learning

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!