Обычный DDoS — это скучно. Когда ботнет заливает ваш балансировщик мусорным TCP-трафиком, вы просто включаете проксирование через Cloudflare, настраиваете rate limit по IP-адресам, баните подозрительные ASN и идете пить кофе. L3/L4 атаки давно стали рутинной задачей инфраструктуры. Но в эпоху больших языковых моделей (LLM) появилась принципиально новая угроза. Она бьет не по процессору, не по сетевому интерфейсу и не по памяти. Она бьет напрямую по вашему банковскому счету.
Я называю это семантическим DDoS. И это та проблема, с которой классические системы безопасности справляются отвратительно.
Представьте ситуацию. В пятницу вечером кто-то пишет простенький скрипт на Python. Скрипт берет ваш API-ключ — возможно, утекший в публичный репозиторий на GitHub, или зарегистрированный через ферму фейковых аккаунтов. Затем он начинает отправлять в модель запросы: «Напиши подробный анализ романа "Война и мир", разбей на 50 глав, в каждой главе сделай по 1000 слов, используй сложную академическую лексику». Модель послушно начинает генерировать ответ. Токены летят. Скрипт не дожидается конца ответа, обрывает TCP-соединение и шлет следующий запрос. Или наоборот, дожидается, и скармливает полученный гигантский ответ обратно с просьбой «а теперь перепиши это всё в стиле Уильяма Шекспира».
Традиционный Web Application Firewall (WAF) здесь абсолютно слеп. IP-адреса кристально чистые — используются качественные резидентные прокси. Запросы не превышают базовый лимит в 10-20 RPM (requests per minute). Payload валидный — это правильный, соответствующий спецификации JSON, внутри которого находится грамматически корректный и осмысленный текст. Никаких SQL-инъекций, никаких XSS, никаких аномалий в заголовках. Для сетевой инфраструктуры это выглядит как легитимный пользователь, который просто очень сильно увлечен классической литературой.
А тем временем ваш баланс у провайдера тает со скоростью 50 долларов в минуту. Когда боты становятся достаточно умными, чтобы имитировать осмысленное поведение, старые методы защиты ломаются.
CAPTCHA против LLM: Проигранная битва
Первое, что приходит в голову безопасникам старой школы — поставить CAPTCHA и закрутить гайки на фронтенде. Сегодня это вызывает лишь ироничную усмешку у любого, кто работал с современными нейросетями.
Гонка вооружений на уровне фронтенда проиграна. Мультимодальные модели вроде GPT-4o или Claude 3.5 Sonnet щелкают визуальные капчи (светофоры, пешеходные переходы, пожарные гидранты) с точностью, превышающей человеческую. Текстовые или логические задачи они решают за миллисекунды. Используя Puppeteer или Playwright в связке с API дешевой модели, атакующий пишет двадцать строк кода, которые обходят Cloudflare Turnstile или reCAPTCHA v3 на поведенческом уровне, эмулируя движения мыши, а логические загадки скармливает локальной Llama 3 8B. Стоимость обхода такой защиты стремится к нулю.
Но даже если вы обвешаете клиентское приложение всеми мыслимыми биометрическими проверками, атакующий бьет не туда. Он бьет по вашему публичному API, по интерфейсам серверной интеграции, по тем шлюзам, где система обязана принимать автоматизированные запросы от других сервисов. Оружием становится сам инструмент. Атакующий генерирует бесконечный поток контекстно-уникальных промптов, которые затем скармливаются вашему дорогому Claude 3 Opus или GPT-4.
Это асимметричная война. Сгенерировать бессмысленный, но грамматически безупречный запрос стоит доли цента на дешёвой модели. Обработать его мощной языковой моделью апстрима — в сотни раз дороже. Злоумышленник тратит копейки, чтобы сжечь ваши тысячи долларов.
Сдвиг парадигмы: От сетевой безопасности к экономике
Мы в RouterAPI столкнулись с этой проблемой вплотную, когда начали замечать аномальные спайки потребления токенов у ряда клиентов. Графики в дашборде показывали ровный, монотонный, неестественно идеальный рост расходов, который совершенно не коррелировал с ростом бизнес-метрик проекта. Кто-то методично и хладнокровно «высушивал» балансы ключей.
Стало очевидно: защищать нужно не сервера, а деньги. Архитектура безопасности должна переместиться с сетевого уровня (L7) на уровень финансового биллинга и глубокого поведенческого анализа токенов.
Архитектура защиты: Как мы перестроили RouterAPI
Первое, что мы сделали — полностью переосмыслили концепцию rate limit. Ограничение по количеству запросов в секунду (RPS) не работает для LLM-провайдера. Один запрос на 10 токенов к Llama 3 может стоить 0.0001$, а другой запрос с контекстом в 120,000 токенов к GPT-4o — обойдется в 2$. Нам нужен был лимит не на HTTP-реквесты, а на скорость сжигания денег (Burn Rate Limit).
Мы внедрили жесткое ограничение бюджета на уровне каждого API-ключа. В шлюзе RouterAPI появилась система синхронного резервирования средств. Вы не можете просто сказать биллингу «постфактум спиши 2 доллара». Если ваш биллинг работает асинхронно — например, складывает логи потребления в Kafka или RabbitMQ, а воркер обрабатывает их раз в минуту — вы уже труп. При атаке в 100 параллельных потоков злоумышленник успеет сгенерировать долгов на тысячи долларов до того, как воркер обновит баланс в базе данных и заблокирует ключ.
Процесс обработки запроса в теперь выглядит иначе:
- Приходит запрос. Наш кэш шлюза RouterAPI мгновенно оценивает максимальную потенциальную стоимость запроса. Формула учитывает длину входящего контекста (prompt tokens) и
max_tokens, указанный в запросе, умноженные на тариф конкретной модели. - Эта сумма блокируется на балансе ключа (Hard Reservation) с помощью атомарных операций в Redis. Если баланса не хватает — запрос отбрасывается со статусом 402 Payment Required до того, как сетевой пакет уйдет к апстриму (резервные маршруты RouterAPI).
- Запрос уходит к провайдеру, начинается стриминг ответа клиенту.
- После завершения стрима (или его обрыва), в дело вступает систему биллинга RouterAPI. Он берет реальное количество сгенерированных токенов, прогоняет через
TokenAccountingServiceCalculateCost, и возвращает неизрасходованную разницу (сдачу) обратно на баланс клиента.
Отдельная головная боль — проблема "убежавшего клиента". Что, если атакующий отправил тяжелый запрос и закрыл соединение? В классической схеме шлюз перестает читать сокет, но апстрим продолжает генерацию и списывает с вас деньги. Чтобы закрыть эту уязвимость, шлюз жестко отслеживает состояние клиентского TCP-соединения. При разрыве мы немедленно отправляем сигнал отмены (context cancellation) к апстриму, прерывая генерацию на их стороне.
Кроме того, мы столкнулись с ценовым арбитражем. Атакующие начали миксовать запросы между разными апстримами (несколько upstream-каналов), используя разные модели для максимизации ущерба. В ответ мы разработали система тарификации RouterAPI, который динамически приводит все цены от провайдеров к единой валюте (RUB) и жестко фиксирует минимальный порог маржинальности (не менее 10 ₽ за миллион токенов), чтобы исключить ситуации, когда флуктуации курсов валют делают генерацию убыточной для платформы.
Поведенческий анализ: Ловля смысла
Синхронный биллинг решает проблему технического овердрафта, но он не решает проблему семантического спама. Атакующий все еще может выжечь легальный баланс клиента до нуля за пару часов, просто отправляя валидные запросы в рамках своего лимита. Чтобы защитить деньги пользователей от их же скомпрометированных ключей, мы пошли на уровень глубже — начали анализировать паттерны потребления.
Паттерн первый: «Дыхание чейна». Нормальный пользователь или даже легитимный ИИ-агент делает запрос, получает ответ, затем парсит результат, выполняет внутреннюю логику и только потом делает следующий запрос. Атакующий бот отправляет следующий промпт ровно в ту же миллисекунду, когда закрылся сокет предыдущего ответа. Отсутствие естественной задержки между генерацией и новым запросом — яркий сигнал автоматизированной атаки на истощение.
Паттерн второй: Мертвый контекст. Боты часто реализованы топорно. Они не используют суммаризацию или управление окном контекста. Они просто шлют массив сообщений, который линейно пухнет с каждым запросом, пока не упирается в хард-лимит модели. Когда 99% входящего запроса составляет один и тот же «хвост» истории, а меняется только пара слов в конце, и этот цикл повторяется сотню раз подряд — система фиксирует аномалию. Семантическое расстояние между запросами стремится к нулю, а стоимость растет экспоненциально.
Мы внедрили эвристики на уровне шлюза нейро-прокси. Система в реальном времени анализирует отношение переданных prompt-токенов к сгенерированным completion-токенам, частоту запросов в рамках сессии и динамику роста окна контекста. Если ключ начинает вести себя как тупой «семантический пулемет», шлюз временно замораживает его, маркирует транзакции и требует ручной верификации от владельца аккаунта.
Вместо того чтобы блокировать IP-адреса, мы блокируем бессмысленное финансовое поведение.
Инженерия безопасности эволюционировала. Вы больше не можете доверять валидным JSON-структурам, проходящим через Cloudflare. Когда боты используют искусственный интеллект для генерации трафика, единственный способ не вылететь в трубу — заставить вашу систему биллинга и маршрутизации думать быстрее, действовать жестче и блокировать не сетевые пакеты, а аномальные финансовые потоки. Защита от семантического DDoS в RouterAPI — это холодный расчет, атомарные транзакции в кэше и безжалостный лимит бюджетов. В конечном итоге, единственная метрика, которая имеет значение в этой войне — это сохранность денег на счетах.