Назад | Перейти на главную страницу

Ограничение скорости с использованием 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.

Это решение требует как минимум 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.

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

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 раз больше памяти, чем первое, для каждой записи в таблице флешек. Конечно, риск столкновения будет намного меньше.