HAProxy – Tracking multiple sample fetches in stick-table

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.

Leave a Reply