SecurityHAProxy20 min read

HAProxy Security Hardening: DDoS Protection, SSL & Rate Limiting (2025 Checklist)

A practical, step-by-step guide to hardening HAProxy for production: configure DDoS mitigation, enforce modern TLS, implement rate limiting with stick tables, block malicious traffic, and monitor for attacks. Includes a 15-point security checklist and copy-paste config snippets.

PS
PentaSynth Team
September 20, 2024 · Updated March 2025

HAProxy Security Checklist (15 Points)

Use this as your audit checklist. Each item is covered in detail below with config examples.

SSL/TLS

Enforce TLS 1.2 minimum, prefer TLS 1.3
Disable SSLv3 and TLSv1.0/1.1 explicitly
Use ECDHE cipher suites only (forward secrecy)
Enable HSTS with preload
Configure OCSP stapling

DDoS

Rate limit per IP with stick tables (HTTP layer)
Rate limit TCP connections per IP (connection layer)
Block known bad bots and scanners via User-Agent ACLs
Limit max connections per IP (maxconnrate)
Set request timeout to prevent slow HTTP attacks

Hardening

Run HAProxy as non-root user
Restrict stats endpoint with auth and IP whitelist
Remove or mask Server headers

Monitoring

Enable error logging to detect attack patterns
Monitor connection/error rates via Prometheus

1. SSL/TLS Hardening

SSL misconfiguration is responsible for a significant portion of web security incidents. HAProxy gives you full control over TLS settings — use it.

Enforce TLS 1.2+ and Modern Cipher Suites

Add these settings to your global section:

global
    # Enforce minimum TLS version
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-sslv3 no-tls-tickets

    # Modern cipher suites (ECDHE only - provides forward secrecy)
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384

    # Same settings for server-side connections
    ssl-default-server-options ssl-min-ver TLSv1.2 no-sslv3 no-tls-tickets
    ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256

Add HSTS and Security Headers

frontend web_frontend
    bind *:443 ssl crt /etc/ssl/certs/site.pem alpn h2,http/1.1

    # HSTS - tells browsers to always use HTTPS
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

    # Additional security headers
    http-response set-header X-Frame-Options "DENY"
    http-response set-header X-Content-Type-Options "nosniff"
    http-response set-header X-XSS-Protection "1; mode=block"
    http-response set-header Referrer-Policy "strict-origin-when-cross-origin"

    # Remove server information
    http-response del-header Server
    http-response del-header X-Powered-By

OCSP Stapling

frontend web_frontend
    bind *:443 ssl crt /etc/ssl/certs/site.pem \
        crt-ignore-err all \
        alpn h2,http/1.1 \
        ocsp-update on

2. DDoS Mitigation with Stick Tables

HAProxy's stick tables are its most powerful DDoS mitigation tool. They allow you to track connection counts, request rates, and other metrics per client IP — and automatically block abusive clients.

TCP-Layer Connection Rate Limiting

This stops connection floods before HAProxy even parses the HTTP request:

frontend web_frontend
    bind *:443 ssl crt /etc/ssl/certs/site.pem

    # Track connection count per IP (TCP layer)
    tcp-request connection track-sc0 src table conn_per_ip_tracker
    tcp-request connection reject if { sc_conn_cur(0) gt 100 }
    tcp-request connection reject if { sc_conn_rate(0) gt 200 }

backend conn_per_ip_tracker
    stick-table type ip size 100k expire 30s store conn_cur,conn_rate(3s)

HTTP Request Rate Limiting

After TCP connection is established, track HTTP request rates per IP:

frontend web_frontend
    bind *:443 ssl crt /etc/ssl/certs/site.pem
    mode http

    # Track request rate per IP
    http-request track-sc0 src table req_rate_tracker

    # Deny if more than 100 requests in 10 seconds
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 }

    # Whitelist your own IPs
    acl is_trusted_ip src 10.0.0.0/8 192.168.0.0/16
    http-request allow if is_trusted_ip

backend req_rate_tracker
    stick-table type ip size 100k expire 30s store http_req_rate(10s),http_err_rate(10s)

Automatic IP Banning

For persistent attackers, implement automatic banning with a longer ban table:

frontend web_frontend
    bind *:443 ssl crt /etc/ssl/certs/site.pem
    mode http

    # Check the ban table first
    http-request deny deny_status 403 if { src,table_gpc0(ban_table) gt 0 }

    # Track error rates - if >50 errors in 3 minutes, add to ban table
    http-request track-sc1 src table ban_table
    http-request sc-inc-gpc0(1) if { sc_http_err_rate(1) gt 50 }

backend ban_table
    stick-table type ip size 100k expire 24h store gpc0,http_err_rate(3m)

3. Blocking Bad Bots and Scanners

A significant portion of attack traffic comes from known malicious scanners, vulnerability tools, and bad bots. Block them at the edge with User-Agent ACLs:

frontend web_frontend
    bind *:443 ssl crt /etc/ssl/certs/site.pem
    mode http

    # Block known malicious scanners
    acl bad_bot hdr_sub(user-agent) -i sqlmap nikto masscan zgrab nmap dirbuster
    acl bad_bot hdr_sub(user-agent) -i python-requests curl libwww-perl
    acl empty_ua hdr_len(user-agent) eq 0

    # Deny empty user agents (bots often omit them)
    http-request deny if empty_ua !{ path /health /metrics }
    http-request deny if bad_bot

Note: Be careful blocking curl and python-requests — these are also used by legitimate monitoring tools. Only block them if they're actually causing you problems.

4. Slow HTTP Attack Prevention

Slow HTTP attacks (like Slowloris) tie up server connections by sending requests extremely slowly. Configure timeouts to protect against them:

defaults
    # Connection must complete within 5 seconds
    timeout connect     5s

    # Client must send headers within 10 seconds
    timeout http-request 10s

    # No more than 30 seconds between keep-alive requests
    timeout http-keep-alive 15s

    # Kill connections idle for more than 30 seconds
    timeout client      30s
    timeout server      30s

    # Tunnel timeouts for WebSockets
    timeout tunnel      3600s

5. Hardening HAProxy Process Security

Run as Non-Root

global
    user haproxy
    group haproxy
    daemon

    # Restrict to single process (better for stick tables)
    nbthread 4
    cpu-map auto:1/1-4 0-3

Restrict the Stats Endpoint

frontend stats
    bind *:8404
    stats enable
    stats uri /haproxy-stats
    stats realm "HAProxy Statistics"
    stats auth admin:$(openssl rand -base64 16)
    stats hide-version

    # Only allow from internal network
    acl internal_network src 10.0.0.0/8 172.16.0.0/12
    http-request deny unless internal_network

6. Hardened HAProxy Config (Complete Example)

Here is a production-ready, hardened haproxy.cfg incorporating all the security measures above:

global
    log /dev/log local0
    maxconn 100000
    user haproxy
    group haproxy
    daemon
    nbthread 4

    # TLS hardening
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-sslv3 no-tls-tickets
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    option  forwardfor
    option  http-server-close
    timeout connect     5s
    timeout http-request 10s
    timeout http-keep-alive 15s
    timeout client      30s
    timeout server      30s

# Connection rate tracker (TCP layer)
backend conn_rate_backend
    stick-table type ip size 200k expire 30s store conn_cur,conn_rate(3s)

# HTTP request rate tracker
backend http_rate_backend
    stick-table type ip size 200k expire 30s store http_req_rate(10s),http_err_rate(3m)

# Ban table for persistent offenders
backend ban_backend
    stick-table type ip size 100k expire 24h store gpc0

frontend web_frontend
    bind *:80
    bind *:443 ssl crt /etc/ssl/certs/site.pem alpn h2,http/1.1

    # Redirect HTTP to HTTPS
    http-request redirect scheme https unless { ssl_fc }

    # TCP-layer rate limiting
    tcp-request connection track-sc0 src table conn_rate_backend
    tcp-request connection reject if { sc_conn_rate(0) gt 200 }

    # Check ban list
    http-request deny status 403 if { src,table_gpc0(ban_backend) gt 0 }

    # HTTP request rate limiting
    http-request track-sc1 src table http_rate_backend
    http-request deny status 429 if { sc_http_req_rate(1) gt 100 }
    http-request sc-inc-gpc0(2) if { sc_http_err_rate(1) gt 50 }

    # Block bad bots
    acl bad_bot hdr_sub(user-agent) -i sqlmap nikto masscan zgrab nmap
    http-request deny if bad_bot

    # Security headers
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    http-response set-header X-Frame-Options "DENY"
    http-response set-header X-Content-Type-Options "nosniff"
    http-response del-header Server
    http-response del-header X-Powered-By

    default_backend web_servers

backend web_servers
    balance roundrobin
    option httpchk GET /health HTTP/1.1
    http-check expect status 200
    server app1 10.0.0.1:8080 check inter 2s fall 3 rise 2
    server app2 10.0.0.2:8080 check inter 2s fall 3 rise 2
    server app3 10.0.0.3:8080 check inter 2s fall 3 rise 2

7. Monitoring for Security Events

A hardened config is only as good as your ability to detect attacks in progress. Set up Prometheus metrics to alert on:

  • Sudden spikes in 4xx/5xx error rates
  • Connection rate increases (>2x normal baseline)
  • Stick table entries approaching capacity
  • Backend server health check failures
frontend prometheus
    bind *:8405
    http-request use-service prometheus-exporter if { path /metrics }
    http-request deny unless { path /metrics }

Pair this with our cloud infrastructure monitoring setup for full Prometheus + Grafana alerting on your load balancer.

Frequently Asked Questions

How do I configure HAProxy for DDoS protection?

Use stick tables to track connection and request rates per IP, then use tcp-request connection reject and http-request deny rules to block IPs that exceed your thresholds. The complete config example above shows the full implementation.

How do I enable TLS 1.3 in HAProxy?

Add "ssl-default-bind-options ssl-min-ver TLSv1.2" to the global section and use TLS 1.3 cipher suites in ssl-default-bind-ciphersuites. HAProxy 2.0+ supports TLS 1.3 natively via OpenSSL 1.1.1+.

Under attack or concerned about security?

Our team has hardened HAProxy for companies handling millions of requests per day. We implement DDoS protection, rate limiting, and full security monitoring.

Get Security Review

Need Production-Grade HAProxy Security?

PentaSynth implements HAProxy security hardening including DDoS protection, rate limiting, TLS 1.3 enforcement, and 24/7 monitoring. Part of our DevOps & Cloud infrastructure service.

Talk to Our Security Team