我一直在尝试对我网站上的一些 HTTP POST 请求实施速率限制。效果很好,但有一个细节除外:我的 stick-table 中条目的过期时间始终重置为 30 秒,这意味着如果客户端在被阻止后 29 秒错误地发出请求,它将再次被阻止 30 秒。
这是我的配置,为了便于阅读,我将其精简到最基本的配置:
frontend http-in
mode http
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
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
使用此配置,只要客户端在 30 秒内每秒发出超过 1 个请求,该客户端就会被标记为滥用者mybackend
。然后,正如预期的那样,前端会阻止后续请求http-in
。
但是,每次当前标记的source_is_abuser
客户端发送请求时,http-in
的 stick-table 的过期计数器都会重置为 30 秒。我预计过期计数器会继续下降,因为据说只有在 时才会跟踪连接!source_is_abuser
。
对我做错的事情有什么见解吗?
答案1
要检查计数器而不更新其值,可以使用表_http_req_rate。在您的情况下,您可以在前端放置以下配置,以便在到达 stick-table 之前拒绝请求。
http-request deny if { key,table_http_req_rate(name_of_your_table) gt 30 }
更多参考:粘贴表文档