Hi all! we are currently exploring the different options available within HAProxy to protect our systems from attacks and accidental overloads. We got the basics figured out by following the very well written introduction to stick tables [1]. What we ended up with is something like this:
stick-table type ip size 10m expire 10s store http_req_rate(10s) tcp-request content track-sc0 src http-request deny status 429 content-type "text/plain" string "429: Too Many Requests" if { sc_http_req_rate(0) gt 5 } This allows us to protect the systems behind HAProxy very well by not letting request through that are above our defined limit. However, we realised that the load on HAProxy per blocked request is very similar to the load per "allowed" request. The idea we had was to block earlier if we know that an IP already made a lot of requests. This would reduce the load on HAProxy since it doesn't have to perform a TLS handshake and inspect the request before blocking it. We expected to be able to just add the following line to the config and block any new connections: tcp-request connection reject if { sc_http_req_rate(0) gt 10 } The idea being that we "softly" limit IPs that exceed our limits a bit, but we have the possibility to completely lock out a certain IP if it continues to generate a high number of requests. However, this does not work at all and we do not understand why. Can you please explain to us why this doesn't work and if there is a different way to achieve this goal? Blocking based on the connection rate does work as described in the documentation [2], which led us to believe that the client IP is available and we should be able to reject the connection based on it. Thanks in advance! Best Regards, Max [1] https://www.haproxy.com/blog/introduction-to-haproxy-stick-tables/ [2] https://cbonte.github.io/haproxy-dconv/2.5/configuration.html#4-tcp-request%20connection PS: We are aware that open connections could keep sending requests and loading HAProxy even if the connection rejection rule kicks in, this could be solved by adding a `http-request reject if { sc_http_req_rate(0) gt 10 }` which closes the connection.