Hi there,
I've been trying to implement rate limiting for some HTTP POST requests on
my website. It works great, except for one detail: the expiration of my
entry in my stick-table is always reset to 30 seconds, which means that if
the client mistakenly makes a request 29 seconds after being blocked, it
will be blocked, again, for 30 seconds.
Here's my config, stripped down tp the bare minimal for ease of reading:
frontend http-in
mode http
option httplog
bind *:80
### Request limiting
# Declare stick table
stick-table type string size 100k expire 30s store gpc0
# Inspect layer 7
tcp-request inspect-delay 15s
# Declare ACLs
acl source_is_abuser sc0_get_gpc0 gt 0
tcp-request content track-sc0 req.cook(frontend) if
!source_is_abuser
### End Request limiting
use_backend rate-limit if source_is_abuser
default_backend mybackend
backend mybackend
mode http
option httplog
option forwardfor
stick-table type string size 100k expire 30s store
http_req_rate(30s)
tcp-request content track-sc1 req.cook(frontend) if METH_POST
acl post_req_rate_abuse sc1_http_req_rate gt 30
acl mark_as_abuser sc0_inc_gpc0 gt 0
tcp-request content accept if post_req_rate_abuse mark_as_abuser
server myLocalhost 127.0.0.1:8081
backend rate-limit
mode http
errorfile 503 /usr/local/etc/haproxy/rate-limit.http
With this config, as soon as a client makes more than 1 request per second
over 30 seconds, this client is marked as an abuser by "mybackend". The
following request are then, as expected, blocked by the "http-in" frontend.
However, every time the currently marked "source_is_abuser" client sends a
request, the expiration counter of "http-in" 's stick-table is reset to 30
seconds. I would expect the expiration counter to keep going down, since
the connection is supposedly only tracked when `!source_is_abuser`.
Any insight into what I am doing wrong?
Thanks!
-Hugues
I've been trying to implement rate limiting for some HTTP POST requests on
my website. It works great, except for one detail: the expiration of my
entry in my stick-table is always reset to 30 seconds, which means that if
the client mistakenly makes a request 29 seconds after being blocked, it
will be blocked, again, for 30 seconds.
Here's my config, stripped down tp the bare minimal for ease of reading:
frontend http-in
mode http
option httplog
bind *:80
### Request limiting
# Declare stick table
stick-table type string size 100k expire 30s store gpc0
# Inspect layer 7
tcp-request inspect-delay 15s
# Declare ACLs
acl source_is_abuser sc0_get_gpc0 gt 0
tcp-request content track-sc0 req.cook(frontend) if
!source_is_abuser
### End Request limiting
use_backend rate-limit if source_is_abuser
default_backend mybackend
backend mybackend
mode http
option httplog
option forwardfor
stick-table type string size 100k expire 30s store
http_req_rate(30s)
tcp-request content track-sc1 req.cook(frontend) if METH_POST
acl post_req_rate_abuse sc1_http_req_rate gt 30
acl mark_as_abuser sc0_inc_gpc0 gt 0
tcp-request content accept if post_req_rate_abuse mark_as_abuser
server myLocalhost 127.0.0.1:8081
backend rate-limit
mode http
errorfile 503 /usr/local/etc/haproxy/rate-limit.http
With this config, as soon as a client makes more than 1 request per second
over 30 seconds, this client is marked as an abuser by "mybackend". The
following request are then, as expected, blocked by the "http-in" frontend.
However, every time the currently marked "source_is_abuser" client sends a
request, the expiration counter of "http-in" 's stick-table is reset to 30
seconds. I would expect the expiration counter to keep going down, since
the connection is supposedly only tracked when `!source_is_abuser`.
Any insight into what I am doing wrong?
Thanks!
-Hugues