Это образец конфигурации,
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 (т.е. нарушитель повторяет его более 3 раз в течение 1 м), я могу заблокировать. Что-то вроде следующего
1) 14:00:00: http_req_rate> 10, abuae_counter = 1
2) 14:00:07: http_req_rate> 10, abuse_counter = 2
3) 14:00:17: http_req_rate> 10 abuse_counter = 3
4) 14:00:45: http_req_rate> 10 abuse_counter = 4> Заблокировать
Тогда я могу просто использовать
use_backend be_429_slow_down if abuse_counter has_auth_header
Как этого добиться? Я думал об использовании lua или set.var, но ничего не помогло.
если вам нужен простой счет с большим отрезком времени, вы можете использовать
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
Я удалил параметр 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