SOLVED: How to configure basic DDOS protection when behind AWS ELB (X-Forwarded-For)?


#1

Hello All,

I would like to configure basic DDOS protection measures on a pair of HAProxy 1.5 servers that are behind an AWS ELB.
The ELB is in tcp mode with proxy-protocol enabled.

I have read through the internet and came accross several examples but none of them seemed to have worked.

In my current config I can finally see entries in the relevant stick-table but having problems taking action based on them.
I can see the counters go up in the table when generating loads using “ab”, but there are no denied sessions when looking at the HAProxy status page.

What am I doing wrong?

Any help would be appreciated.

frontend bits:
tcp-request connection reject if { src_conn_rate(Logger) ge 20 }
tcp-request connection reject if { src_conn_cur(Logger) ge 10 }
tcp-request connection reject if { src_get_gpc0(Logger) gt 0 }
tcp-request connection expect-proxy layer4
tcp-request content track-sc0 src table Logger

Application backend:
acl abuse src_http_req_rate(Logger) ge 10
acl flag_abuser src_inc_gpc0(Logger)
tcp-request content reject if abuse flag_abuser

Logger backend for the stick table:
backend Logger
stick-table type ip size 100k expire 3m store conn_rate(3s),gpc0,conn_cur,http_req_rate(10s),http_err_rate(10s)

Example entries in the table:
0x85302c: key=1xx.2xx.2xx.2xx use=0 exp=169083 gpc0=91 conn_rate(3000)=0 conn_cur=0 http_req_rate(10000)=93 http_err_rate(10000)=9
0x85302c: key=1xx.2xx.2xx.2xx use=2 exp=179997 gpc0=5483 conn_rate(3000)=456 conn_cur=2 http_req_rate(10000)=1543 http_err_rate(10000)=0


#2

Figured out in the end, here is my working config that behaved as expected when using ab and browsers by hand.
The solution is to use tcp-request content instead of tcp-request connection as the latter uses the actual ip, in thi scase the ip of the ELB instead of the forwarded one.

frontend http-listener
mode http
option forwardfor
option httplog
bind *:80 accept-proxy

    # Abuse protection.

    # Sources that are not filtered.
    tcp-request content accept if { src -f /etc/haproxy/whitelist.lst }

    # Sources rejected immeditely.
    tcp-request content reject if { src -f /etc/haproxy/blacklist.lst }

    # Limiting the connection rate per client. No more than 10 connections over 3 seconds.
    tcp-request content reject if { src_conn_rate(Logger) ge 10 }

    # Reject if more than 50 connections from client.
    # This is to accommodate clients behind a NAT.
    tcp-request content reject if { src_conn_cur(Logger) ge 50 }

    # Block based on backend.
    tcp-request content reject if { src_get_gpc0(Logger) gt 0 }

    # Track counters based on forwarded ip.
    tcp-request content track-sc1 src table Logger

backend Logger
# Table.
stick-table type ip size 100k expire 3m store conn_rate(3s),gpc0,conn_cur,http_req_rate(10s),http_err_rate(10s)

backend App
balance roundrobin
cookie SERVERID insert indirect nocache
mode http
option httplog
acl abuse src_http_req_rate(Logger) ge 100
acl flag_abuser src_inc_gpc0(Logger) ge 0
tcp-request content reject if abuse flag_abuser