What are HAProxy ACLs?

In HAProxy, Access Control Lists (ACLs) are the foundation of intelligent traffic routing and security. While a basic load balancer simply forwards traffic round-robin, ACLs allow HAProxy to inspect incoming requests (IP, headers, paths) and make decisions:

  • Routing: Send /api traffic to one group of servers, and /blog to another.
  • Security: Block malicious IP addresses or deny access to admin panels.
  • Redirection: Redirect HTTP to HTTPS or redirect outdated domains.

ACL Syntax Basics

An ACL declaration looks like this:

acl <aclname> <criterion> [flags] [operator] <value>
  • aclname: A custom name you choose (e.g., is_api, bad_ip).
  • criterion: What data to check (e.g., hdr(host) for domain, path_beg for URL path, src for client IP).
  • flags: Modifiers (e.g., -i for case-insensitive).
  • value: The pattern to match against.

Common ACL Use Cases

1. Host-Based Routing (Virtual Hosts)

Route traffic depending on the domain name requested.

frontend main_frontend
    bind *:80

    # Define ACLs
    acl is_blog hdr(host) -i blog.example.com
    acl is_api  hdr(host) -i api.example.com

    # Actions based on ACLs
    use_backend blog_servers if is_blog
    use_backend api_servers  if is_api
    
    # Default fallback
    default_backend web_servers

2. Path-Based Routing

Route traffic based on the URL path.

frontend main_frontend
    bind *:80

    # Match paths that begin with /api
    acl app_api path_beg /api/
    # Match paths that end with image extensions
    acl app_static path_end .jpg .png .css .js

    use_backend api_servers    if app_api
    use_backend static_servers if app_static
    default_backend web_servers

3. IP Blocking and Whitelisting

Protect sensitive areas or block known bad IPs.

frontend main_frontend
    bind *:80

    # Define ACL for an admin path
    acl is_admin_path path_beg /admin
    
    # Define ACL for allowed office IPs
    acl is_office_ip src 192.168.100.0/24 10.0.0.5

    # Deny access to /admin if the IP is NOT (-m) from the office
    http-request deny if is_admin_path !is_office_ip

    # Block a specific bad IP globally
    acl blocked_ip src 203.0.113.50
    http-request deny if blocked_ip

4. HTTP to HTTPS Redirection

A classic ACL use case to force secure connections.

frontend http_in
    bind *:80
    
    # Redirection rule
    http-request redirect scheme https code 301 if !{ ssl_fc }

(Note: !{ ssl_fc } is an inline anonymous ACL meaning “if not an SSL frontend connection”)

5. Routing by User-Agent

Route mobile users to specific backend servers or block bad bots.

frontend main_frontend
    bind *:80

    acl is_mobile hdr_sub(User-Agent) -i android iphone
    use_backend mobile_servers if is_mobile
    
    acl is_bad_bot hdr_sub(User-Agent) -i curl wget
    http-request deny if is_bad_bot

Applying and Testing Changes

Always validate your HAProxy configuration before reloading the service. A syntax error will cause traffic to drop.

# Check configuration syntax
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

# If it returns "Configuration file is valid", reload HAProxy smoothly
sudo systemctl reload haproxy

ACL Combination Logic

You can combine multiple ACLs using logical operators:

  • AND: Automatically implied if you list multiple ACL names back-to-back.
  • OR: Explicitly defined using ||.
  • NOT: Explicitly defined using !.
# Example: If path is /admin AND IP is NOT office OR User-Agent is bot
http-request deny if is_admin_path !is_office_ip || is_bad_bot

Summary

  • ACLs extract request data, match it against rules, and trigger actions.
  • Use hdr(host) for domains, path_beg for URLs, and src for IPs.
  • Actions like use_backend, http-request deny, and http-request redirect rely on ACLs to function.
  • Always test configuration syntax with haproxy -c before reloading.