DDOS ЗАЩИТА СЕРВЕРА при помощи NGINX ч.2

В предыдущем материале мы рассказали как правильно сконфигурировать горячий кеш NGINX для того чтобы снять основную нагрузку с вашего сервера. Давайте перейдем к следующему этапу и рассмотрим организацию фильтрации входящих запросов при помощи языка LUA. Для правильной DDoS защиты сервера нам необходимо корректно разделить динамический и статический контент, постараемся учесть NAT и поработаем с белым списком IP адресов. И, конечно же, всегда можно навернуть еще специфичной логики, что не выйдет при использовании готовых модулей.

DDOS ЗАЩИТА СЕРВЕРА
Данная схема сейчас спокойно и эффективно (практически не сказывается на использовании cpu) обрабатывает порядка 1200 запросов/сек. На предельные величины не тестировалось.

Хочется обрабатывать все входящие запросы сразу по поступлению, а не по факту строчки в access_log (который еще небось и выключен для той же статики). Не вопрос, вешаем обработчик глобально на весь http:

Теперь все запросы, приходящие в nginx, пройдут через наш скрипт req.lua. При этом у нас есть две таблицы req_limit и ban_list для хранения истории запросов и списка уже забаненных соотвественно (подробнее ниже).
А для реализации whitelist по IP вместо велосипедов использован модуль geo nginx, проставляющий значение переменной lua_req_whitelist, которая используется примерно так:

Для проверки статика/динамика (запрос за файлом на диске/backend серверу) делаем простую проверку по имени запрашиваемого файла (тут можно усложнять реализацию, подстраиваясь под свою бизнес логику):

Для хоть какой-то обработки NAT, кроме IP клиентов так же учитывается их UserAgent и проставляется спец кука. Все три элемента в целом и составляют идентификатор пользователя. Если некий злодей долбит сервер, игнорируя передаваемую куку, то в худшем случае просто будет забанен его IP/подсеть. При этом те пользователи с этой подсети, кто уже получил ранее куку, будут спокойно работать дальше (кроме случая бана по IP). Решение не идеальное, но все же лучше, чем считать полстраны/мобильного оператора за одного пользователя.
Генерация и проверки куки:

Теперь в key_prefix содержится идентификатор клиента, чей запрос мы обрабатываем. Если данный клиент уже забанен, то дальнейшая обработка не нужна:

Ключ получили, бан проверили, теперь можно посчитать, не превышает ли данный запрос какой из лимитов:

Проверяем 4 варианта счетчиков: статика/динамика, по одному пути/по разным. Непосредственные проверки выполняются в check_limit_exhaust():

Кроме непосредственного бана на lua_req_ban_ttl секунд, можно реализовать постоянное хранение, а заодно прикрутить логгирование и проброс забаненных по IP в iptables/аналоги. Это уже вне темы поста.

Все это, само собой, лишь пример DDOS защиты сервера, а не готовое решение на 100%. Тем более приведенные числа лимитов указаны с потолка.

Рейтинг материала
[Голосов: 1 Рейтинг: 5]
16 марта 2017, 06:16

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *