如果 http_req_rate(60s) > 20 连续 3 次,Haproxy 是否会阻止?

如果 http_req_rate(60s) > 20 连续 3 次,Haproxy 是否会阻止?

这是示例配置,

frontend fe_app

    bind 0.0.0.0:8484 name http
    acl has_auth_header req.fhdr(api-key) -m found



    acl mark_as_abuser       sc0_inc_gpc0(be_429_table_api) gt 10
    acl req_rate_api_abuse   sc0_http_req_rate(be_429_table_api) gt 10


    http-request set-header X-Concat %[req.fhdr(api-key)]_%[src] if has_auth_header
    http-request track-sc0 req.fhdr(X-Concat) table be_429_table_api if has_auth_header
    capture request header X-Concat len 100 

    use_backend be_429_slow_down if mark_as_abuser req_rate_api_abuse has_auth_header

    default_backend be_default

backend be_429_table_api
    stick-table type string size 100k expire 10s store http_req_rate(10s),http_req_cnt,gpc0,gpt0

backend be_429_slow_down
    timeout tarpit 10s
    http-request tarpit

我测试了watch -n2 'echo "show table be_429_table_api" | socat stdio unix:/var/run/haproxy.sock'

问题出现在收到请求时gpc0 自动开始增加。直到表过期。这似乎与任何方式都无关http_req_rate。那么这个计数器的用途是什么?

我想要一个计数器,只有当 http_req_rate >10 时才会增加。因此,当它超过 3(即攻击者在 1 分钟内重复超过 3 次)时,我可以阻止。类似以下内容

1)下午 2:00:00 :http_req_rate > 10,abuae_counter =1

2)下午 2:00:07:http_req_rate > 10,abuse_counter = 2

3)下午 2:00:17 :http_req_rate > 10 abuse_counter =3

4)下午 2:00:45:http_req_rate > 10 abuse_counter =4 > 阻止

然后我可以简单地使用

use_backend be_429_slow_down if abuse_counter has_auth_header

如何实现?我考虑过使用 lua 或 set.var,但没有任何效果。

答案1

如果你想要一个带有大时间片的简单计数,你可以使用

frontend website
    bind :80
    stick-table  type ip  size 100k  expire store http_req_rate(24h)
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 20 }
    default_backend servers

我从 stick 表中删除了 expires 参数,如文档中所述:

A stick table record expires and is removed after a period of inactivity by the client, as set by the expire parameter. That’s just a way of freeing up space. Without an expire parameter, oldest records are evicted when the storage becomes full

相关内容