Imagine you are managing a busy highway with multiple lanes, and you want to direct specific types of vehicles to particular lanes: trucks to one lane, cars to another, and motorcycles to yet another. In the world of web traffic, this is similar to what Access Control Lists (ACLs) in HAProxy do—they help you direct incoming requests based on specific criteria.
Let’s dive into what ACLs are in HAProxy, why they are essential, and how you can use them effectively with some practical examples.

What are ACLs in HAProxy?
Access Control Lists (ACLs) in HAProxy are rules or conditions that allow you to define patterns to match incoming requests. These rules help you make decisions about how to route or manage traffic within your infrastructure.
Think of ACLs as powerful filters or guards that analyze incoming HTTP requests based on headers, IP addresses, URL paths, or other attributes. By defining ACLs, you can control how requests are handled—for example, sending specific traffic to different backends, applying security rules, or denying access under certain conditions.
Why Use ACLs in HAProxy?
Using ACLs offers several advantages:
- Granular Control Over Traffic: You can filter and route traffic based on very specific criteria, such as the content of HTTP headers, cookies, or request methods.
- Security: ACLs can block unwanted traffic, enforce security policies, and prevent malicious access.
- Performance Optimization: By directing traffic to specific servers optimized for certain types of content, ACLs can help balance the load and improve performance.
- Flexibility and Scalability: ACLs allow dynamic adaptation to changing traffic patterns or new requirements without significant changes to your infrastructure.
How ACLs Work in HAProxy
ACLs in HAProxy are defined in the configuration file (haproxy.cfg). The syntax is straightforward
acl <name> <criteria>
<name>: The name you give to your ACL rule, which you will use to reference it in further configuration.<criteria>: The condition or match pattern, such as a path, header, method, or IP address.
It either returns True or False.
Examples of ACLs in HAProxy
Let’s look at some practical examples to understand how ACLs work.
Example 1: Routing Traffic Based on URL Path
Suppose you have a web application that serves both static and dynamic content. You want to route all requests for static files (like images, CSS, and JavaScript) to a server optimized for static content, while all other requests should go to a dynamic content server.
Configuration:
frontend http_front
bind *:80
acl is_static path_beg /static
use_backend static_backend if is_static
default_backend dynamic_backend
backend static_backend
server static1 127.0.0.1:5001 check
backend dynamic_backend
server dynamic1 127.0.0.1:5002 check
- ACL Definition:
acl is_static path_beg /static: checks if the request URL starts with/static. - Usage:
use_backend static_backend if is_staticroutes the traffic to thestatic_backendif the ACLis_staticmatches. All other requests are routed to thedynamic_backend.
Example 2: Blocking Traffic from Specific IP Addresses
Let’s say you want to block traffic from a range of IP addresses that are known to be malicious.
Configurations
frontend http_front
bind *:80
acl block_ip src 192.168.1.0/24
http-request deny if block_ip
default_backend web_backend
backend web_backend
server web1 127.0.0.1:5003 check
ACL Definition:acl block_ip src 192.168.1.0/24 defines an ACL that matches any source IP from the range 192.168.1.0/24.
Usage:http-request deny if block_ip denies the request if it matches the block_ip ACL.
Example 4: Redirecting Traffic Based on Request Method
You might want to redirect all POST requests to a different backend for further processing.
Configurations
frontend http_front
bind *:80
acl is_post_method method POST
use_backend post_backend if is_post_method
default_backend general_backend
backend post_backend
server post1 127.0.0.1:5006 check
backend general_backend
server general1 127.0.0.1:5007 check
Example 5: Redirect Traffic Based on User Agent
Imagine you want to serve a different version of your website to mobile users versus desktop users. You can achieve this by using ACLs that check the User-Agent header in the HTTP request.
Configuration:
frontend http_front
bind *:80
acl is_mobile_user_agent req.hdr(User-Agent) -i -m sub Mobile
use_backend mobile_backend if is_mobile_user_agent
default_backend desktop_backend
backend mobile_backend
server mobile1 127.0.0.1:5008 check
backend desktop_backend
server desktop1 127.0.0.1:5009 check
ACL Definition:acl is_mobile_user_agent req.hdr(User-Agent) -i -m sub Mobilechecks if theUser-Agentheader contains the substring "Mobile" (case-insensitive).
Usage:use_backend mobile_backend if is_mobile_user_agent directs mobile users to mobile_backend and all other users to desktop_backend.
Example 6: Restrict Access to Admin Pages by IP Address
Let’s say you want to allow access to the /admin page only from a specific IP address or range, such as your company’s internal network.
frontend http_front
bind *:80
acl is_admin_path path_beg /admin
acl is_internal_network src 192.168.10.0/24
http-request deny if is_admin_path !is_internal_network
default_backend web_backend
backend web_backend
server web1 127.0.0.1:5015 check
Example with a Flask Application
Let’s see how you can use ACLs with a Flask application to enforce different rules.
Flask Application Setup
You have two Flask apps: app1.py for general requests and app2.py for special requests like form submissions.
app1.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "Welcome to the main page!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5003)
app2.py:
from flask import Flask
app = Flask(__name__)
@app.route('/submit', methods=['POST'])
def submit_form():
return "Form submitted successfully!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5004)
HAProxy Configuration with ACLs
frontend http_front
bind *:80
acl is_post_method method POST
acl is_submit_path path_beg /submit
use_backend post_backend if is_post_method is_submit_path
default_backend general_backend
backend post_backend
server app2 127.0.0.1:5004 check
backend general_backend
server app1 127.0.0.1:5003 check
ACLs:
is_post_methodchecks for thePOSTmethod.is_submit_pathchecks if the path starts with/submit.
Traffic Handling: The traffic is directed to post_backend if both the ACLs match, otherwise, it goes to general_backend.
