Что именно считает rate limit
«У нас ограничены запросы» — половина ответа. Главный вопрос другой: что берётся ключом ограничения и во сколько атакующему обходится смена этого ключа?
«У нас ограничены запросы» — половина ответа. Главный вопрос другой: что берётся ключом ограничения и во сколько атакующему обходится смена этого ключа?
Любой rate limit состоит из трёх вещей: ключ, окно и порог. Ключ — то, от чьего имени мы считаем запросы. Настраивают обычно окно и порог, а ключ остаётся по умолчанию.
По умолчанию ключом почти всегда оказывается IP-адрес. Это самый простой вариант: он есть всегда и не требует никакой логики приложения.
Ровно поэтому он и самый слабый: сменить IP атакующему дёшево, а у ваших настоящих пользователей IP часто общий.
Первая ошибка — ложное срабатывание. За NAT мобильного оператора стоят тысячи абонентов. Общий порог на них означает, что обычный пользователь блокируется, ничего не сделав.
Вторая — пропуск. В современной атаке запросы идут с тысяч домашних прокси, и с каждого адреса выходит один-два запроса в секунду. Каждый адрес по отдельности ниже порога, а суммарный поток кладёт сервис.
Обе ошибки из одной причины: IP-адрес принадлежит не атакующему, а сети. А контролировать вы хотите поведение.
На практике ключ не один, их несколько и они работают вместе. Самый точный — идентификатор учётной записи: для вошедшего пользователя сменить его дорого.
Следующий — идентификатор сессии или устройства: работает для неавторизованных потоков, но чистится легко. Третий — сетевой блок: не один IP, а подсеть или автономная система целиком.
Четвёртый ключ забывают чаще всего: само действие. «Сколько SMS отправлено на один номер» — это тоже rate limit, и он работает независимо от того, кто отправляет.
Единого порога быть не должно. Запрос статического файла и выполнение поиска или отправка SMS стоят по-разному, поэтому держать их под одним порогом бессмысленно.
Практический пример: статическая страница весит 1×, поиск — 10×, отправка SMS — 100×. Бюджет тратится по этому весу, поэтому пользователь может открыть сто страниц, но выполнить десять поисков.
Особенно это важно там, где расход внешний: SMS, почта, сторонний API. Там ограничение считается не техническим, а финансовым.
Превысивший порог запрос необязательно отклонять сразу. Чаще достаточно его замедлить: ответ задерживается на 200 миллисекунд, и живой пользователь этого не замечает.
Для скрипта это фатально: вся его эффективность была в скорости. Замедление делает атаку бессмысленной, но даже при ошибке не теряет пользователя.
Ступени строятся так: сначала замедление, потом требование проверки, потом отказ. Каждая следующая применяется по результату предыдущей.
Фиксированное окно — самый простой способ и самый легко обходимый. Если счёт обнуляется каждую минуту, атакующий шлёт двойной порог: в последнюю секунду минуты и в первую следующей.
Поэтому используют скользящее окно или token bucket. Второй даёт дополнительную пользу: он разрешает короткий всплеск, удерживая среднюю скорость.
Разница ощутима на практике. При открытии страницы браузер шлёт десятки запросов — это нормальный всплеск, и ограничение, которое его режет, ломает сайт.
Rate limit работает, когда место принятия решения отделено от места исполнения. Решение принимается в контексте приложения, исполнение — как можно ниже и дешевле.
Если ограничение исполняется внутри приложения, вы всё равно оплачиваете соединение, TLS и чтение запроса. На большом потоке само ограничение становится нагрузкой.
Второе требование — общий счёт. Если счётчик не разделяется между серверами, атакующий просто попадает каждый раз на другую копию и умножает порог.
Достаточно трёх тестов. Первый: одной учётной записью, но с десяти разных IP. Если порог сработал, ключом является учётная запись.
Второй: с одного IP, но десятью разными учётными записями. Если блокировки нет, вы не наказываете пользователей за общей сетью.
Третий: по одному запросу в секунду, но со ста источников. Если ничего не заметно, у вас ограничение только по источнику, и распределённая медленная атака проходит незамеченной.
Покажите домен — дадим первичный анализ вашего текущего внешнего состояния. На этом этапе ничего не меняется.

