❌

Reading view

There are new articles available, click to refresh the page.

HAProxy EP 4: Understanding ACL – Access Control List

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:

  1. 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.
  2. Security: ACLs can block unwanted traffic, enforce security policies, and prevent malicious access.
  3. Performance Optimization: By directing traffic to specific servers optimized for certain types of content, ACLs can help balance the load and improve performance.
  4. 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_static routes the traffic to the static_backend if the ACL is_static matches. All other requests are routed to the dynamic_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 Mobile checks if the User-Agent header 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_method checks for the POST method.
  • is_submit_path checks 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.

❌