Защита API от злоупотреблений: рабочая схема с нуля
Одного лимита запросов недостаточно: злоумышленник может обойти его сменой IP, токенов или идентификаторов. Разбираем, как выстроить защиту API по слоям — от шлюза до бизнес-операций.

API может выдержать тысячу обычных запросов в секунду и всё равно быть уязвимым: злоумышленник будет не перегружать сервер, а массово подбирать коды, создавать аккаунты, скачивать чужие данные или нажимать дорогой endpoint. Привычное решение — поставить общий лимит по IP — защищает только от простого HTTP-флуда. Ниже — практическая схема для HTTP API: какие ограничения поставить на границе, что проверять в приложении и как не превратить защиту в блокировку легитимных клиентов.
Сначала определите, что именно вы защищаете
До настройки лимитов составьте карту операций. У публичного каталога, входа в аккаунт и перевода денег не может быть одинаковая политика доступа: у них разная цена ошибки и разная допустимая частота.
- Дорогие операции. Поиск по сложным фильтрам, генерация отчётов, экспорт, отправка писем и вызовы внешних сервисов расходуют CPU, память или деньги.
- Чувствительные операции. Вход, восстановление пароля, смена телефона, создание API-ключа и изменение платёжных реквизитов требуют защиты от перебора и автоматизации.
- Операции с данными. Получение объекта по идентификатору, список заказов или скачивание файла могут раскрыть сведения, если сервер проверяет только факт авторизации, но не право на конкретный объект.
- Массовые операции. Регистрация, отправка приглашений, публикация объявлений и применение промокодов нужно ограничивать не только по запросам, но и по результату.
Составьте таблицу: endpoint, метод, тип клиента, стоимость операции, требуемая авторизация, лимит, реакция на превышение и событие для мониторинга. Без этой инвентаризации команда обычно защищает самые заметные URL и пропускает внутренние или редко используемые маршруты.
Лимит запросов отвечает на вопрос «как часто клиент обращается к API», но не отвечает на главный вопрос безопасности: «что этот клиент успел сделать».
Разделите защиту на четыре слоя
1. Периметр: фильтруйте очевидный автоматизированный трафик
На CDN, WAF или API-шлюзе удобно отсекать превышение частоты, подозрительные сетевые шаблоны и слишком большие тела запросов. Это дешёвый первый барьер: запрос не доходит до приложения и не занимает его пул соединений.
Но IP — слабый идентификатор. За одним адресом могут находиться офис, мобильный оператор или NAT нескольких клиентов. Поэтому не ставьте жёсткий глобальный запрет только по IP. Используйте несколько измерений: IP, маршрут, идентификатор приложения, пользователя и, где это допустимо, подсеть.
2. Аутентификация: отличайте клиента от анонимного трафика
Для публичных методов задайте отдельные лимиты для анонимных запросов, авторизованных пользователей, организаций и доверенных внутренних сервисов. Секрет клиента не должен быть единственным доказательством личности: украденный ключ иначе даст злоумышленнику тот же уровень доступа, что и владельцу.
Короткоживущие токены уменьшают окно злоупотребления, а отзыв ключа позволяет быстро остановить утечку. Не передавайте токены в URL: они могут попасть в историю, логи прокси и заголовок Referer. Проверяйте срок действия, назначение токена и права на конкретную операцию.
3. Авторизация объекта: проверяйте не только роль
Проверка «пользователь вошёл» не означает, что он может прочитать заказ с указанным идентификатором. Для каждого запроса к объекту сервер должен сопоставить объект с пользователем, организацией или другим контекстом доступа.
Это особенно важно для последовательных идентификаторов. Если API отвечает разными статусами или размерами тела на существующий и чужой объект, клиент может постепенно собрать информацию о базе. В спорных случаях лучше возвращать одинаковое внешнее поведение и писать детали только во внутренний журнал.
4. Бизнес-ограничения: считайте результат, а не только запросы
Клиент может укладываться в лимит HTTP-запросов и при этом создать тысячи аккаунтов, отправить сотни приглашений или перебрать все варианты одноразового кода. Для таких сценариев вводите квоты на действие: количество регистраций на устройство или организацию, число попыток на аккаунт, суточный объём экспорта, число активных задач.
Квота должна быть привязана к серверному событию. Не доверяйте полям вроде user_id из тела запроса и не храните счётчик только в памяти одного экземпляра приложения: при нескольких инстансах ограничение начнёт расходиться.
Сравните способы ограничения частоты
Алгоритм выбирайте после определения цели. Для защиты от коротких всплесков нужен один механизм, для равномерной выдачи ресурса — другой.
| Подход | Что контролирует | Плюсы | Цена и риск |
|---|---|---|---|
| Лимит на шлюзе по IP и маршруту | Сетевой поток до приложения | Быстро внедряется, снижает нагрузку на backend | Ложные блокировки за NAT, не видит бизнес-контекст |
| Лимит по пользователю или API-ключу | Частоту действий конкретного клиента | Точнее для авторизованных сценариев | Не защищает до аутентификации, требует общего хранилища состояния |
| Квота на бизнес-операцию | Регистрации, экспорты, попытки, расходы | Останавливает дорогие и вредные сценарии | Нужна корректная модель идемпотентности и учёт результата |
| Адаптивная реакция | Изменение поведения при подозрительном паттерне | Меньше помех обычным клиентам | Сложнее объяснять и тестировать, возможны ошибки классификации |
Токен-бакет1 подходит, когда нужно разрешить короткий всплеск в пределах накопленного запаса, но ограничить среднюю скорость. Скользящее окно проще объяснить и отлаживать, однако граница окна может дать клиенту два всплеска подряд. Для чувствительных операций алгоритм вторичен: важнее отдельный лимит на действие и корректное хранение счётчика.
Возвращайте клиенту предсказуемую реакцию
При превышении частоты используйте HTTP 429 Too Many Requests. Если сервер знает время следующей попытки, передайте его через заголовок Retry-After; клиент должен использовать задержку, а не немедленно повторять запрос в цикле.
Ответ не должен раскрывать внутреннюю схему защиты. Не сообщайте, какой именно порог сработал, какой IP связан с аккаунтом или существует ли чужой адрес электронной почты. Для легитимного клиента верните машинно читаемый код ошибки, корреляционный идентификатор и безопасное описание следующего шага.
Повторы опасны для операций, которые создают побочный эффект. Клиент может не получить ответ из-за разрыва соединения и повторить оплату, заказ или отправку письма. Для таких маршрутов нужен механизм идемпотентности: сервер связывает повтор с тем же ключом операции и не выполняет побочный эффект второй раз. Формат и срок хранения такого ключа должны быть частью контракта API, а не неформальной договорённостью команд.
Не превращайте защиту в чёрный ящик
Минимальный набор метрик должен позволять ответить на три вопроса: кто создаёт нагрузку, на каком этапе запрос остановлен и сколько легитимных клиентов пострадало.
- доля ответов 401, 403, 404 и 429 по маршрутам;
- число запросов и бизнес-действий на IP, пользователя, ключ и организацию;
- доля повторных попыток, ошибки авторизации и задержка ответа после срабатывания лимита;
- расход CPU, памяти, соединений с базой и внешних сервисов на дорогих endpoint;
- срабатывания квот, блокировки и ручные разблокировки.
Логи должны содержать время, маршрут, результат проверки, идентификатор клиента в безопасном виде и correlation ID. Токены, пароли, cookies и полные персональные данные в лог не записывайте. Для расследования полезнее хэш или внутренний идентификатор, чем секрет, который потом придётся считать скомпрометированным.
Что ломается чаще всего
Один лимит для всего API
Общий порог защищает документацию и каталог ценой доступности для входа или оформления заказа. Разделите профили: публичное чтение, чувствительные операции, дорогие задачи и внутренний трафик.
Ограничение только по IP
Оно обходится сменой сети, прокси или распределением запросов по адресам и одновременно может заблокировать целый офис. Сочетайте сетевой сигнал с аутентификацией и лимитом на бизнес-действие.
Счётчик в памяти одного процесса
При нескольких экземплярах приложения каждый видит только свою часть запросов. При перезапуске счётчики сбрасываются. Состояние ограничения должно жить в общем отказоустойчивом хранилище либо на уровне компонента, который действительно видит весь поток.
Проверка квоты после тяжёлой операции
Если сначала построить отчёт, обратиться к платному сервису и только потом проверить лимит, злоумышленник всё равно создаст расходы. Дешёвые проверки доступа и квоты ставьте до дорогой работы, а окончательное списание ресурса делайте атомарно.
Когда что выбирать
Если угроза — короткий всплеск запросов, начните с ограничения на периметре. Если нужно защитить аккаунт от перебора, добавьте лимит на пользователя, операцию и идентификатор цели. Если проблема связана с расходами или массовыми действиями, одной частоты запросов недостаточно — нужна квота на результат.
Адаптивные правила добавляйте после появления базовых метрик. Иначе система будет блокировать клиентов по непрозрачным признакам, а команда не сможет доказать, почему запрос был отклонён.
Что сделать дальше
Возьмите пять самых дорогих и пять самых чувствительных endpoint и проведите для них отдельный тестовый сценарий: нормальный клиент, превышение частоты, смена IP, повтор запроса после тайм-аута и обращение к чужому объекту. Зафиксируйте ожидаемые статусы, лимиты, логи и время восстановления.
После этого настройте алерты не только на всплеск 5xx, но и на рост 401, 403, 429, неудачных попыток входа и расхода внешних сервисов. За базовую модель угроз используйте OWASP API Security Top 10 2023, а семантику ответа 429 сверяйте с RFC 6585. Следующий показатель для продакшена — не общее число запросов, а стоимость и результат действий на одного клиента.
1 Токен-бакет — алгоритм, в котором для клиента постепенно накапливаются условные токены. Каждый запрос тратит токен, а превышение доступного запаса временно ограничивает поток.
Генератор изображений: Иллюстрация, обложка, баннер, схема — по текстовому описанию, без исходного фото.
Спросить за 20 ₽Источники: OWASP API Security Top 10 2023, RFC 6585: Additional HTTP Status Codes
Частые вопросы
Достаточно ли поставить rate limit по IP?
Какой ответ должен получать клиент при превышении лимита?
Нужно ли ограничивать уже авторизованные запросы?
Что делать, если клиент повторил операцию после тайм-аута?
Можно ли хранить счётчики лимитов в памяти приложения?
Что делать, если защита блокирует обычных пользователей?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.