Ограничение скорости с помощью haproxy на URL-адрес и IP-адрес

Ограничение скорости с помощью haproxy на URL-адрес и IP-адрес

На наши серверы постоянно кто-то нападает. Это не DDOS. Просто один IP-адрес заходит на один URL-адрес более 200 раз в секунду. В настоящее время я блокирую пользователя по таблицам IP-адресов. Мы используем HAproxy для балансировки нагрузки. Есть ли способ ограничить пользователя на основе его IP-адреса и URL-адреса, на который он заходит?

Я не хочу блокировать только на основе IP, так как это может повлиять на пользователей NAT. Допустим, я хочу показать страницу ошибки 503, если определенный IP-адрес заходит на тот же URL, например www.example.com/somepage.php?some=option&other=option2, более 3000 раз за 5 минут? Это означает, что тот же IP-адрес может получить доступ к другим URL-адресам, например www.example.com/somepage.php?another=someotheroption.

решение1

Для этого решения требуется как минимум haproxy 1.6.

Сначала добавьте в интерфейс следующее:

http-request set-header X-DOS-Protect %[src];%[req.fhdr(host)]%[capture.req.uri]

Затем добавьте в бэкэнд следующее:

stick-table type integer size 1m expire 5m store http_req_rate(5m)
tcp-request inspect-delay 5s
tcp-request content track-sc0 req.fhdr(X-DOS-Protect),crc32(1) if HTTP
http-request tarpit if { sc0_http_req_rate gt 3000 }

Мне не удалось найти способ выполнить отслеживание во внешнем интерфейсе, поскольку я не нашел способа применить конвертер к этой объединенной строке, составляющей заголовок X-DOS-Protect.

Я применяю хэш-функцию, чтобы убедиться, что вы не храните огромную строку в stick-table, так как это может легко привести к отказу в обслуживании. Если вы считаете, что эта хэш-функция вам не подходит из-за слишком большого количества возможных коллизий, вы также можете сделать ее больше, применив crc32 к каждому из объединенных компонентов (и, конечно, удалив ее при сохранении данных и переключившись на большее хранилище stick-table), вот так:

http-request set-header X-DOS-Protect %[src,crc32(1)];%[req.fhdr(host),crc32(1)]%[capture.req.uri,crc32(1)]

stick-table type string len 30 size 1m expire 5m store http_req_rate(5m)
tcp-request inspect-delay 5s
tcp-request content track-sc0 req.fhdr(X-DOS-Protect) if HTTP
http-request tarpit if { sc0_http_req_rate gt 3000 }

Обратите внимание, что это последнее решение будет использовать в 7 раз больше памяти, чем первое, для каждой записи в таблице палочек. Конечно, риск столкновения также будет намного меньше.

Связанный контент