How to Configure Haproxy Rate Limiting with Stick Tables and Acls on Ubuntu

Learning how to configure HAProxy rate limiting with stick tables and ACLs on Ubuntu is one of the most effective ways to protect your web applications from traffic abuse, brute-force attacks, and DDoS floods. HAProxy is a high-performance load balancer and proxy server trusted by major websites worldwide. Its stick table feature lets you track client behavior across requests. Combined with ACLs, you can build smart, dynamic rate-limiting rules that block bad actors automatically. In this tutorial, you will install HAProxy on Ubuntu, configure stick tables to count requests per IP, write ACL rules to enforce limits, and test that everything works correctly. By the end, you will have a working rate-limiting setup that can protect any backend service you run.

Prerequisites and Requirements for HAProxy Rate Limiting

Before you start configuring HAProxy rate limiting with stick tables and ACLs, make sure you have the following in place.

System requirements:

  • Ubuntu 20.04 or 22.04 (fresh or existing server)
  • Root or sudo access
  • A backend web server or application running (such as Nginx or Apache)
  • Basic familiarity with the Linux command line

Estimated time: 30–45 minutes

You should also have a basic understanding of how proxies and load balancers work. You don’t need to be an expert. If you’ve edited config files and run commands in a terminal before, you’re ready. Make sure your Ubuntu server has internet access so you can install packages. It also helps to have a second machine or tool like curl or Apache Benchmark available for testing your rate limits later.

Step-by-Step Guide to Configure HAProxy Rate Limiting with Stick Tables and ACLs

For a related walkthrough, see: How to Optimize Docker Images with Multi-stage Builds

Follow these steps carefully. Each step builds on the previous one.

Step 1: Update your system and install HAProxy

Start by refreshing your package list and installing HAProxy.

sudo apt update && sudo apt upgrade -y
sudo apt install haproxy -y

After installation, verify the version:

haproxy -v

You should see version 2.x or higher. HAProxy 2.x includes full stick table support with expiry and rate tracking. Check the official HAProxy configuration documentation for a complete reference on all directives.

Step 2: Back up the default configuration

Always back up config files before editing them.

sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak

Step 3: Open the HAProxy configuration file

sudo nano /etc/haproxy/haproxy.cfg

You’ll edit this file throughout the next steps.

Step 4: Configure the global and defaults sections

Replace or update the existing global and defaults blocks with the following:

global
    log /dev/log local0
    log /dev/log local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    maxconn 50000
    user haproxy
    group haproxy
    daemon

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5s
    timeout client  30s
    timeout server  30s

These settings establish logging, connection limits, and timeouts. Keep timeouts short to free resources from slow or abusive clients.

Step 5: Create a frontend with a stick table

Now add your frontend block. This is where rate limiting happens. Add the following after your defaults section:

frontend http_front
    bind :80
    mode http

    # Define a stick table to track request rates per IP
    stick-table type ip size 100k expire 30s store http_req_rate(10s)

    # Track the client IP in the stick table
    http-request track-sc0 src

    # Define ACL: flag IPs making more than 100 requests in 10 seconds
    acl too_many_requests sc_http_req_rate(0) gt 100

    # Deny flagged IPs with a 429 response
    http-request deny deny_status 429 if too_many_requests

    default_backend web_servers

Here’s what each part does. The stick-table line creates an in-memory table. It stores up to 100,000 IP entries. Each entry expires after 30 seconds of inactivity. The store option tracks the HTTP request rate over a 10-second window. The http-request track-sc0 src line logs each request’s source IP into the table. The ACL checks if any IP exceeds 100 requests in 10 seconds. If it does, HAProxy returns a 429 Too Many Requests response immediately.

Step 6: Configure the backend

Add your backend block pointing to your actual web server:

backend web_servers
    mode http
    balance roundrobin
    server web1 127.0.0.1:8080 check

Replace 127.0.0.1:8080 with your actual backend server address and port.

Step 7: Validate and reload HAProxy

Always validate your config before reloading. A syntax error will take down your proxy.

sudo haproxy -c -f /etc/haproxy/haproxy.cfg

You should see: Configuration file is valid

Then reload the service:

sudo systemctl reload haproxy
sudo systemctl status haproxy

Step 8: Test your rate limiting rules

Use Apache Benchmark to simulate high traffic from a single IP:

ab -n 200 -c 10 http://your-server-ip/

After 100 requests, you should start receiving 429 responses. You can also use curl in a loop:

for i in {1..120}; do curl -s -o /dev/null -w "%{http_code}n" http://your-server-ip/; done

Watch the output change from 200 to 429 after the threshold is hit. For more advanced testing strategies, see the Ubuntu Server documentation for network and firewall tools you can combine with HAProxy.

Troubleshooting Common HAProxy Rate Limiting Problems

Even with a clean setup, things can go wrong. Here are the most common issues and how to fix them.

Problem: HAProxy won’t start after config changes
Run sudo haproxy -c -f /etc/haproxy/haproxy.cfg to find the exact line causing the error. Fix the syntax and try again.

Problem: Rate limiting isn’t triggering
Double-check your ACL threshold. If your test tool isn’t sending enough requests fast enough, the counter won’t exceed the limit. Lower the threshold temporarily to 10 requests for testing, then raise it back.

Problem: All clients get blocked, not just abusers
This usually means you’re tracking the wrong source. Check that http-request track-sc0 src is using the correct client IP. If your server is behind a CDN or another proxy, the source IP might always be the same upstream address. In that case, track by req.hdr(X-Forwarded-For) instead.

Problem: Stick table fills up too fast
Increase the size parameter in your stick-table definition. Start with 200k or 500k if you handle high traffic volumes. Also reduce the expire time to flush stale entries sooner.

Warning: Don’t set your rate limit threshold too low in production. Legitimate users behind shared IPs (like office networks or mobile carriers) can share a single IP address. A threshold of 100–200 requests per 10 seconds is a reasonable starting point for most applications.

Conclusion

You now know how to configure HAProxy rate limiting with stick tables and ACLs on Ubuntu from start to finish. You installed HAProxy, set up an in-memory stick table to track per-IP request rates, wrote ACL rules to identify abusive clients, and confirmed the setup works with real traffic tests. This configuration gives your server a strong first line of defense against floods and scraping bots. From here, you can extend this setup by adding multiple stick tables for different metrics, combining rate limiting with geo-blocking, or integrating HAProxy with a logging stack like Graylog or ELK. Keep your HAProxy version updated and review your thresholds regularly as your traffic patterns change.

Similar Posts