May 7

Как я защищался от DDOS атак 1.5 года назад

Проблема

Есть один проект. Название разглашать не могу — у меня NDA.

Но проект выстрелил. Мы обошли всех конкурентов: и по функционалу, и по стабильности, и по скорости. В итоге — просто вытеснили их с рынка. Никого не душили, не ддосили, просто сделали лучше.

А они этого не оценили. Видимо, один из "побеждённых" решил, что раз фактически проиграл — стоит пробовать грязными методами.

Через пару месяцев после запуска на наших ботов посыпались DDoS-атаки.

Сначала это был мелкий флуд и спам /start с ботнетов. Мы даже посмеивались. Но потом стало куда интереснее

Они начали жестко ддосить одного конкретного бота, через которого шёл основной трафик. Но, как это часто бывает, из-за архитектурных связей — ложилась вся система. База задыхалась, нагрузка расползалась по всем микросервисам. Даже те боты, которых не трогали напрямую, начинали лагать и в конце концов ложились.

База данных задыхалась от огромного подключений — соединения открывались быстрее, чем закрывались. Но самым весёлым оказалось то, что сыпаться начала уже ОС. Сервер банально упирался в ulimit (число одновременно открытых файлов и сокетов).

Это был не просто DDoS одного бота — это был каскадный эффект, который клал всю систему.

Решение

Первым делом я, как и любой нормальный человек, полез в ulimit. Повысил лимиты на сокеты — установил бесконечные значения. Но, как оказалось, это не спасло. Linux перестал сразу сыпаться, но нагрузка продолжала расползаться — и вместо ошибки "too many open files" я просто получал сервер с 100% CPU и зависшей БД.

Было ясно: проблема не в ОС, а в логике приложения.

Что в итоге сделал:

Я встроил слой внутренней защиты прямо в бота. Всё крутилось вокруг одного принципа: если мы не можем отличить реального пользователя от атакующего, то мы хотя бы должны быстро понять, когда началась аномалия, и временно начать фильтровать трафик.

  • Пассивная защита: анализ параметров в /start. Если бот получает слишком много сомнительных параметров (?start=asdasd, ?start=999, ?start=test1), это фиксируется в счётчике. При превышении порога шлётся алерт в лог-канал. Плюс, старты со всеми аргументами, не входящими в вайтлист, просто игнорируются. Это аннулирует нагрузку с мусорного трафика.
  • Активная защита: анализ онлайна в реальном времени. Подсчитываются уникальные пользователи без Telegram Premium за последние N секунд. Если их слишком много — бот переходит в режим защиты (UAM).
  • Активная защита: анализ общего трафика. Если за 2 минуты начинаются аномальные, сильно отклоняющиеся от нормы всплески активности — тоже триггерится защита (UAM).
  • Дополнение: кеширование всех запросов к БД на этапе проверки. Запросы к базе кешируются, чтобы не бить БД по 100 раз в секунду.
  • Дополнение: автоматическое уведомление в лог-канал. При срабатывании любого защитного триггера — я сразу получаю сообщение с ID бота и описанием аномалии. Реагировать можно сразу, без ручного мониторинга.

UAM - Under Attack Mode

Очень активная защита: UAM. Если бот под UAM, то обычные пользователи видят заглушку с ссылками на других ботов нашей системы, а премиум-пользователи проходят дальше. Это позволило сохранять работоспособность во время атаки хотя бы для 50% пользователей.

1.5 года в проде

С момента внедрения этой системы прошло уже полтора года. За это время ботов пытались ддосить тысячи раз, и ни одна атака не смогла вывести из строя всю систему.

Бывало, что отдельные зеркала уходили в UAM на 15 минут, но это и был план: локализовать проблему и не дать ей расползтись.

В условиях Telegram это максимум из того, что можно сделать без ущерба для UX. Можно было ввести капчу. Можно было включать rate-limit каждому новому пользователю.

Но я принципиально не хотел этого. Всё должно работать нативно, быстро и бесшовно — как и ждёт пользователь от телеграм-бота.

Поэтому я пошёл по пути умной активной фильтрации: бот сам понимает, что на него идёт подозрительный трафик, и сам уходит в UAM. Это честный компромисс между безопасностью и удобством.

Пользователи об атаках даже не догадывались.

Боты — продолжали работать. Атаки — пропали.

И самое главное — система оказалась самодостаточной. 0 доработок за 1.5 года. Просто работает.

Самое ироничное в этой истории то, что через несколько месяцев после отличной работы защиты активность ддосеров резко упала. Сначала попытки стали реже, потом вовсе тишина. А потом тот самый конкурент полностью ушёл из Telegram и закрыл свой проект. Видимо, понял, что соревноваться честно не получится, а ломать смысла нет.

Мы же просто продолжаем работать. Без капч, без лишних проблем для пользователей, без паники. Просто я сделал всё правильно и вовремя.

А лучший показатель того, что защита работает — это когда про неё вообще забываешь.