Третья волна DDoS: атакующие ушли с L3/L4 на HTTP, и upstream-фильтрация перестала справляться
Май 2022: третья волна DDoS за квартал, и на этот раз - application-layer атаки на HTTP/HTTPS. Разбираем, где WAF помог, а где выручил rate-limiting на L7.
Май 2022: продолжаются волновые DDoS-атаки на российские финансовые и корпоративные сети, атакующие адаптируют векторы
Третья волна за квартал. После февральских атак мы пересмотрели конфигурации и настроили rate limiting, после 24-25 февраля - подняли scrubbing и задокументировали процедуры. В мае атакующие поменяли тактику, и оказалось, что часть инструментов, которые работали раньше, теперь не при делах.
Что изменилось
Февральские атаки были преимущественно volumetric: UDP-флуд, SYN-флуд, усиление через открытые резолверы. Это классика - бьют объёмом, пытаясь забить канал или перегрузить сетевое оборудование. Провайдерские scrubbing-центры и BGP Blackhole для этого и сделаны - с объёмом они справляются приемлемо.
Майская волна на нескольких клиентских площадках выглядела иначе. Объём трафика - в пределах нормы. На графиках Grafana по входящему потоку ничего экстремального. При этом сервис деградирует: response time растёт, часть запросов отваливается по таймауту, у одного клиента упал пул соединений приложения. Мониторинг по полосе пропускания ничего не показывает, а сервис лежит.
Смотрим в логи nginx - и видим HTTP-запросы. Много, методично, с паузами между сериями. Не миллионы пакетов в секунду на L3, а аккуратные GET и POST на конкретные эндпоинты: страницы с поиском, публичные API, формы авторизации. Запросы внешне корректные - валидные HTTP/1.1, разные User-Agent, нет очевидных ботовых сигнатур. Это application-layer атака, и провайдерскому scrubbing-центру на неё, в общем-то, наплевать - трафик «выглядит нормально» с точки зрения L3/L4.
Где сработал WAF, где нет
На одной площадке стоит WAF - развёрнутый ещё до февраля, не в рамках антидосовых мер, а просто как элемент защиты веб-приложения. ModSecurity в режиме detection с частично подключёнными правилами OWASP CRS. В майскую волну он сработал частично: поймал часть запросов по сигнатурам сканирования и некоторые паттерны автоматизированных клиентов. Не всё - часть запросов прошла, потому что атакующие имитировали нормальный браузерный трафик достаточно убедительно.
Честный вывод: WAF в режиме «поставили и забыли» с дефолтными правилами - это не защита от целенаправленной L7-атаки. Он снижает поверхность, отфильтровывает явных ботов и сканеры, но от грамотно выстроенной HTTP-атаки с ротацией User-Agent и распределёнными источниками не спасёт. Для этого нужна тонкая настройка под конкретное приложение, а не общий набор сигнатур.
Вторая площадка - без WAF, зато с нормально настроенным rate limiting на nginx. И вот там было интереснее.
Почему rate limiting на L7 помог больше upstream-фильтрации
У этого клиента ещё после февральского разбора настроили limit_req_zone по нескольким осям: по IP отдельно, по комбинации IP + URI для тяжёлых эндпоинтов. Плюс limit_conn на количество одновременных соединений с одного адреса. Плюс кеширование результатов на тяжёлых публичных страницах.
Когда пошла майская атака - картина на этой площадке была принципиально другой. Nginx честно вернул атакующим клиентам 429 по rate limit, не пустил запросы дальше в upstream, приложение работало в штатном режиме. Нагрузка на сервер поднялась, но не критически - nginx отбивает 429 дёшево, без обращения к базе.
При этом scrubbing у этого клиента тоже подключён, провайдер трафик видит - и не вмешивается, потому что объём в норме. С точки зрения провайдера всё хорошо, он ничего не делает. Всю работу делает nginx на нашей стороне.
Это наблюдение, которое хочется зафиксировать: при application-layer атаке «правильного размера» - достаточно большой, чтобы убить приложение, но недостаточно объёмной, чтобы триггернуть upstream-фильтры - вся защита оказывается именно на уровне L7. Провайдер здесь не помощник.
Что пришлось докручивать в процессе
Несколько вещей выяснились уже во время инцидента.
Лимиты нужно выставлять с запасом на «хороший трафик». На одной площадке rate limit был настроен агрессивно - и в процессе отражения атаки начал задевать реальных пользователей. Пришлось оперативно поднимать пороги и добавлять whitelist для партнёрских IP. Не катастрофа, но осадок.
Кеширование статики и публичных ответов - это антидос-мера. Один из атакующих паттернов бил по страницам, которые при каждом запросе лезли в базу за одними и теми же данными. После включения nginx-кеша для этих эндпоинтов нагрузка на базу упала, атака перестала давать эффект. Причём кеш мы включили за 20 минут прямо в процессе - не архитектурное решение, а быстрый тактический ответ.
Атакующие реагируют. Примерно через несколько часов после того, как основной паттерн заблокировали - запросы к /search с определёнными параметрами - атака сменила вектор, перешла на другие URI. Не сильный сдвиг, но достаточный, чтобы часть правил перестала работать. Мы их обновили, но это подтверждает: на той стороне есть петля обратной связи, оператор видит эффективность и адаптируется.
Что это значит для конфигурации
После трёх волн за квартал у нас сложилось более чёткое понимание эшелонов защиты, чем было в январе.
- Upstream scrubbing / BGP Blackhole - нужен, незаменим против volumetric. Но это инструмент L3/L4, и на L7-атаки он не смотрит.
- WAF - снижает шум, ловит сканеры и грубых ботов. Для точечной L7-атаки нужна настройка под конкретное приложение, общие правила не панацея.
- Rate limiting на nginx по IP и URI - оказался первой линией именно против HTTP-флуда. Дёшев в работе, быстро настраивается, может быть скорректирован прямо в ходе инцидента без перезагрузки сервиса.
- Кеширование тяжёлых эндпоинтов - неожиданно хорошее антидос-средство. Атака, которая убивает базу через тяжёлые запросы, теряет смысл, если ответы кешируются.
- Connection limits и upstream concurrency - защищают пул соединений приложения и базы от перегрева даже если запросы прошли через rate limit.
Всё это работает в связке. Убирать один слой в расчёте на другой - ошибка, которую мы уже видели в феврале.
Где мы сейчас
Атаки не закончились - продолжаются в фоне, периодически нарастая. Картина в рунете в целом такова, что «повышенная готовность» уже перестала ощущаться как что-то экстраординарное - это просто рабочий режим.
По клиентам в рамках managed-сопровождения прошлись по конфигурациям ещё раз: добавили rate limiting там, где его не хватало, включили кеш на тяжёлых публичных страницах, зафиксировали процедуры реагирования для L7-сценария. WAF там, где нет - рассматриваем, но без иллюзий насчёт «поставил и забыл».
Вектор атак явно смещается в сторону application layer - это логично, там меньше дорогостоящих ресурсов нужно атакующему, а провайдерская защита не помогает. Значит, защита тоже должна быть там.