Recently i’ve searched a way to do rate-limiting in HAProxy based on multiple client identifiers.
The standard example you can find in the docs or in many tutorials is to track on “src” (source ip). Track on “src” is fine in most cases, but can be a problem if users are behind NAT/mobile gateways where many clients share the same ip address.
Therefore, i would like to combine (concatenate) Source IP + User-Agent or X-Forwarded-For + User-Agent and track on this new “identifier”.
There isn’t a builtin method or sample fetch at the moment in HAProxy which combine multiple variables (besides something as base32+src).
I need to track in a frontend because the client should be rate-limited globally (in all backends).
The following is an example if you need to track on the concatenated header in a frontend (currently, a header which is set by “http-request” is available to ACL’s in the same frontend, but not to the tracking/stick-table functionality. Therefore a “workaround” is needed (HAProxy 1.5)).
HAProxy 1.5:
frontend http_in
bind 0.0.0.0:80
http-request set-header X-Concat %[req.fhdr(User-Agent)]_%[src]
default_backend forwarder
backend forwarder
server localhost 127.0.0.1:4444 send-proxy
frontend http_in_local
bind 127.0.0.1:4444 accept-proxy
stick-table type string len 180 size 32m expire 5m store http_req_rate(10s)
tcp-request inspect-delay 5s
tcp-request content track-sc0 req.fhdr(X-Concat) if HTTP
default_backend webnodes
backend webnodes
server apache01 192.168.100.50:80 check inter 2s rise 2 fall 2 maxconn 20 weight 50
Checking stick-table entries:
# echo "show table http_in_local" | socat stdio /run/haproxy/admin.sock
In HAProxy 1.6, you don’t need the workaround any more:
frontend http_01
.
.
.
http-request track-sc0 req.fhdr(X-Concat)
HAProxy is very powerful and flexible, you can combine any possible sample fetches and use these for tracking. See HAProxy docs for all available fetches.