Rate limiting в nginx: ограничиваем частоту запросов
Один агрессивный бот или скрипт способен уложить сайт, забив все воркеры запросами. Директива limit_req в nginx ставит лимит на частоту обращений с одного адреса — разбираем зоны, burst, nodelay и защиту чувствительных эндпоинтов.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Зачем ограничивать частоту
Rate limiting — это защита от того, что один клиент шлёт слишком много запросов слишком быстро: перебор паролей на форме логина, парсинг всего каталога, DoS с одного IP, ошибочный retry-цикл в приложении. nginx умеет это на уровне веб-сервера, ещё до того как запрос дойдёт до PHP или бэкенда.
- Защита логина — брутфорс упирается в лимит запросов в секунду.
- Разгрузка бэкенда — всплеск трафика режется на входе, а не роняет приложение.
- Честность — один клиент не забирает все ресурсы у остальных.
Механизм основан на алгоритме leaky bucket: запросы «протекают» с заданной скоростью, а лишние либо ждут, либо отбрасываются с кодом 503.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS для отказоустойчивого сайтаОбъявляем зону limit_req
Сначала в контексте http объявляется зона — область общей памяти, где nginx хранит счётчики по ключу (обычно IP клиента). Ключ задаётся через limit_req_zone.
http {
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
}
Разберём параметры: $binary_remote_addr — компактная форма IP (экономит память), zone=perip:10m — имя зоны и её размер (10 МБ хватает примерно на 160 тысяч адресов), rate=10r/s — базовая скорость: не более 10 запросов в секунду с одного IP.
Скорость можно задавать и в минутах: rate=30r/m — 30 запросов в минуту, удобно для редких, но чувствительных операций.
Применяем лимит с burst
Объявленную зону подключают директивой limit_req в нужном location или server. Голый лимит без burst слишком жёсткий — реальные браузеры шлют запросы пачками. Параметр burst разрешает всплеск.
location / {
limit_req zone=perip burst=20 nodelay;
proxy_pass http://backend;
}
burst=20 — очередь на 20 «лишних» запросов сверх скорости: короткий всплеск пропускается, устойчивое превышение режется. nodelay означает, что запросы из очереди обрабатываются сразу, а не растягиваются во времени — так лимит незаметен обычным пользователям, но душит флуд.
Без nodelay nginx будет искусственно задерживать запросы из burst-очереди, выравнивая их под rate — это плавнее для бэкенда, но добавляет задержку. Для API чаще берут nodelay, для тяжёлых бэкендов — версию с задержкой.
Жёсткий лимит на логин
Форму входа и API аутентификации стоит защищать отдельной, более строгой зоной — здесь важнее остановить брутфорс, чем удобство. Заведём вторую зону и применим её точечно.
http {
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
}
server {
location = /login {
limit_req zone=login burst=3 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
}
rate=5r/m пропускает лишь 5 попыток входа в минуту с адреса — этого хватает человеку и мало ботнету. Директива limit_req_status 429 заставляет отдавать корректный код «Too Many Requests» вместо дефолтного 503.
Проверка и мониторинг
После правки конфига всегда проверяй синтаксис перед перезагрузкой — сломанный конфиг положит весь nginx.
sudo nginx -t && sudo systemctl reload nginx
Сработавшие лимиты видны в error-логе: nginx пишет строки limiting requests. Отследить их можно так.
grep 'limiting requests' /var/log/nginx/error.log | tail
Смоделировать нагрузку для проверки удобно утилитой ab или hey: пусти 100 запросов в 10 потоков и убедись, что часть вернулась с 429 или 503.
ab -n 100 -c 10 https://example.com/
Частые ошибки
- Лимит за прокси — если сайт за Cloudflare или балансировщиком,
$binary_remote_addrпокажет IP прокси, а не клиента. Используй$http_x_forwarded_forсreal_ip. - Слишком маленький burst — легитимные пользователи ловят 503 при обычной навигации. Тестируй значения под реальный трафик.
- Забыли nginx -t — опечатка в зоне валит весь веб-сервер.
- Один лимит на всё — статику, API и логин лучше разводить по разным зонам с разной строгостью.
Rate limiting снимает нагрузку, но не заменяет мощное железо: когда трафик реально растёт, важен быстрый диск и производительное ядро. AMD EPYC + NVMe на MAATRIX держат больше одновременных соединений на том же лимите.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS для отказоустойчивого сайтаОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Чем limit_req отличается от limit_conn?
limit_req ограничивает частоту запросов в секунду, а limit_conn — число одновременных соединений с одного IP. Их часто используют вместе.
Как понять правильное значение rate?
Оцени нормальный трафик по логам: посмотри, сколько запросов в секунду делает обычный пользователь, и поставь rate с запасом, а burst — на короткие всплески.
Лимит защищает от DDoS?
От флуда с небольшого числа адресов — да. Против распределённой атаки с тысяч IP нужен внешний уровень защиты, nginx лишь снижает нагрузку на бэкенд.