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