У нас есть довольно загруженный веб-сервис с двумя балансировщиками HAProxy перед ним. Иногда мы получаем распределенные DOS-атаки на уровне сценариев (DDoS), при которых небольшое количество серверов атак (около 100 или меньше) инициирует множество запросов к динамическим веб-страницам. Я знаю, что если они могут инициировать DDoS-атаки SYN-флуда, заполняющие наши каналы, я ничего не смогу сделать с балансировщиками. Однако этот вопрос касается строго ограничения нагрузки на бэкэнд-серверы.
Я знаю, что haproxy поддерживает флеш-таблицы, и такой трафик можно обнаружить. Однако я бы предпочел не отвечать 429 или отклонять соединение, потому что при любом обнаружении могут быть ложные срабатывания. Вместо этого я бы хотел заставить эти запросы обрабатывать медленно (желательно n
запросов в заданное временное окно вместо фиксированной задержки).
Один из возможных методов описан на https://billus.co.uk/haproxy-slowing-down-abuse-with-user-friendly-rate-controls/ где используется простой скрипт LUA:
function delay_request(txn)
core.msleep(1500 + math.random(1000))
end
core.register_action("delay_request", { "http-req" }, delay_request);
и haproxy
есть что-то вроде
global
lua-load /etc/haproxy/delay.lua
frontend
http-request lua.delay_request if { sc0_get_gpc0(Abuse) gt 0 }
Однако, делая это в frontend
занимает места в maxconn
очереди для этого интерфейса и при достаточно длительной атаке это может DOS frontend
очередь.
Есть ли способ сделать такую принудительную задержку в главной очереди? Я предполагаю, что у большинства злоумышленников-скриптингов есть достаточно агрессивные клиенты, поэтому они не будут ждать в очереди даже 5 секунд и отключатся, если не будут обслужены достаточно быстро. Таким образом, запрос никогда не вызовет никакой нагрузки на внутренние серверы.
Или было бы нормально просто поднять maxconn для frontend
к глобальному maxconn
значение и просто держите очередь в frontend
? Является haproxy
достаточно умен, чтобы вообще не подключать серверную часть, если клиент отключается во время frontend
очередь?
Наша ожидаемая (= без атаки) общая дневная нагрузка для динамических страниц составляет около 500 запросов / с во время пиковой нагрузки, поэтому мы не можем запускать действительно тяжелое обнаружение для каждого запроса.