Как я защищался от 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. Если бот под UAM, то обычные пользователи видят заглушку с ссылками на других ботов нашей системы, а премиум-пользователи проходят дальше. Это позволило сохранять работоспособность во время атаки хотя бы для 50% пользователей.
1.5 года в проде
С момента внедрения этой системы прошло уже полтора года. За это время ботов пытались ддосить тысячи раз, и ни одна атака не смогла вывести из строя всю систему.
Бывало, что отдельные зеркала уходили в UAM на 15 минут, но это и был план: локализовать проблему и не дать ей расползтись.
В условиях Telegram это максимум из того, что можно сделать без ущерба для UX. Можно было ввести капчу. Можно было включать rate-limit каждому новому пользователю.
Но я принципиально не хотел этого. Всё должно работать нативно, быстро и бесшовно — как и ждёт пользователь от телеграм-бота.
Поэтому я пошёл по пути умной активной фильтрации: бот сам понимает, что на него идёт подозрительный трафик, и сам уходит в UAM. Это честный компромисс между безопасностью и удобством.
Пользователи об атаках даже не догадывались.
И самое главное — система оказалась самодостаточной. 0 доработок за 1.5 года. Просто работает.
Самое ироничное в этой истории то, что через несколько месяцев после отличной работы защиты активность ддосеров резко упала. Сначала попытки стали реже, потом вовсе тишина. А потом тот самый конкурент полностью ушёл из Telegram и закрыл свой проект. Видимо, понял, что соревноваться честно не получится, а ломать смысла нет.
Мы же просто продолжаем работать. Без капч, без лишних проблем для пользователей, без паники. Просто я сделал всё правильно и вовремя.
А лучший показатель того, что защита работает — это когда про неё вообще забываешь.