Как ограничить частоту запросов в Nginx: пошаговая настройка rate limiting
Настройка limit_req_zone и limit_req для контроля нагрузки
Введение
Ограничение частоты запросов (rate limiting) — важный инструмент защиты веб-сервера от перегрузок, брутфорс-атак, парсинга и простейших DDoS. Nginx предоставляет встроенный модуль ngx_http_limit_req_module, который позволяет гибко настраивать лимиты для разных зон (по IP, по ключу, по расположению). В этом руководстве мы разберём, как правильно настроить ограничение частоты запросов в Nginx, чтобы не блокировать легитимных пользователей и при этом эффективно отсекать вредоносный трафик.
Требования
Установленный Nginx версии 1.10 и выше (модуль limit_req входит в стандартную сборку).
Права на редактирование конфигурационных файлов (обычно
/etc/nginx/nginx.confили файлы в/etc/nginx/conf.d/).Базовые знания синтаксиса Nginx.
Доступ к командной строке сервера.
Шаг 1: Понимание принципов работы limit_req
Модуль limit_req использует алгоритм «leaky bucket» (протекающее ведро). Вы задаёте зону с определённой скоростью (например, 10 запросов в секунду), и Nginx пропускает запросы с этой скоростью. Если запросы приходят быстрее, они могут быть либо отклонены с кодом 503, либо поставлены в очередь (burst) с задержкой. Важно правильно выбрать ключ зоны — обычно это IP-адрес клиента ($binary_remote_addr), но можно использовать и другие переменные, например, $server_name или $http_user_agent.
Шаг 2: Определение зоны ограничения (limit_req_zone)
Директива limit_req_zone задаёт зону разделяемой памяти для хранения состояния. Она размещается в контексте http. Пример:
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/s;
...
}Здесь:
$binary_remote_addr— ключ, по которому ведётся учёт (IP-адрес в бинарном виде, экономит память).zone=mylimit:10m— имя зоны и размер памяти (10 МБ хватает примерно на 160 000 уникальных IP).rate=5r/s— разрешённая скорость: 5 запросов в секунду. Можно указывать в минутах:30r/m.
Шаг 3: Применение ограничения в location (limit_req)
Директива limit_req включается в контексте http, server или location. Пример для location:
location /login/ {
limit_req zone=mylimit burst=10 nodelay;
proxy_pass http://backend;
}Параметры:
zone=mylimit— имя зоны, определённой ранее.burst=10— разрешает всплеск до 10 запросов сверх установленной скорости. Эти запросы обрабатываются сразу, но следующие за ними будут отклоняться, пока не восстановится баланс.nodelay— не задерживать обработку burst-запросов, а сразу их выполнять (без этого они бы помещались в очередь с задержкой).
Если не указать nodelay, то при превышении скорости запросы будут ставиться в очередь и обрабатываться с задержкой, что может увеличить время ответа.
Шаг 4: Настройка кода ошибки и логирования
По умолчанию при превышении лимита возвращается код 503 (Service Unavailable). Его можно изменить с помощью директивы limit_req_status (доступна с версии 1.3.15). Например:
limit_req_status 429;Код 429 (Too Many Requests) более информативен для клиентов. Также можно настроить уровень логирования для отклонённых запросов:
limit_req_log_level warn;По умолчанию используется уровень error. Уровень warn поможет снизить шум в логах.
Шаг 5: Разные лимиты для разных зон
Вы можете создать несколько зон с разными скоростями и применять их к разным частям сайта. Например, для API — строже, для статики — мягче:
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=2r/s;
limit_req_zone $binary_remote_addr zone=static:10m rate=20r/s;
server {
location /api/ {
limit_req zone=api burst=5 nodelay;
...
}
location /static/ {
limit_req zone=static burst=30 nodelay;
...
}
}
}Шаг 6: Исключение определённых IP из ограничений
Иногда нужно освободить от лимитов доверенные адреса (например, мониторинг или офис). Это делается с помощью директивы geo и переменной, которая будет пустой для исключённых IP:
http {
geo $limit {
default 1;
192.168.1.0/24 0;
10.0.0.1 0;
}
map $limit $limit_key {
0 "";
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=mylimit:10m rate=5r/s;
...
}Теперь для IP из списка ключ будет пустым, и ограничения не применятся.
Шаг 7: Тестирование конфигурации и перезагрузка
После внесения изменений проверьте синтаксис:
nginx -tЕсли ошибок нет, перезагрузите Nginx:
systemctl reload nginxили
nginx -s reloadШаг 8: Мониторинг и анализ логов
Следите за логами ошибок Nginx (/var/log/nginx/error.log), чтобы видеть, какие IP попадают под ограничения. Если лимиты слишком строгие, вы увидите много записей об отклонённых запросах. Анализируйте их и корректируйте параметры rate и burst. Также можно использовать сторонние инструменты, например, goaccess для анализа логов в реальном времени.
Шаг 9: Тонкая настройка burst и nodelay
Параметр burst определяет, сколько запросов может быть обработано сверх лимита одновременно. Если burst слишком мал, легитимные пользователи могут получать ошибки при кратковременных всплесках (например, при загрузке страницы с множеством ресурсов). Если слишком велик — защита ослабевает. Рекомендуется начинать с небольших значений (5–10) и увеличивать при необходимости. nodelay позволяет обрабатывать burst-запросы без задержки, что улучшает отзывчивость, но может привести к кратковременной перегрузке бэкенда. Если бэкенд слабый, лучше не использовать nodelay, чтобы запросы сглаживались.
Шаг 10: Использование limit_conn для ограничения соединений
Дополнительно к limit_req можно ограничить количество одновременных соединений с одного IP с помощью модуля limit_conn. Это полезно для защиты от медленных атак (slowloris). Пример:
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
...
server {
location / {
limit_conn addr 10;
...
}
}
}Здесь разрешено не более 10 одновременных соединений с одного IP.
Типичные ошибки
1. Слишком строгий rate — приводит к блокировке реальных пользователей. Начните с более мягких значений и постепенно ужесточайте. 2. Отсутствие burst — при всплесках запросов (например, при загрузке страницы) пользователи будут получать ошибки. Всегда добавляйте небольшой burst. 3. Использование `$remote_addr` вместо `$binary_remote_addr` — первый хранится в виде строки и занимает больше памяти. Всегда используйте бинарный вариант. 4. Забыли про `nodelay` — если не указать, burst-запросы будут задерживаться, что может увеличить время загрузки страниц. 5. Не учтены прокси — если Nginx стоит за балансировщиком, $binary_remote_addr будет содержать IP балансировщика. Используйте real_ip модуль для корректного определения клиентского IP. 6. Игнорирование логов — без анализа логов невозможно понять, эффективны ли ограничения и не мешают ли они пользователям.
FAQ
Вопрос: Можно ли ограничить скорость по URL? Да, в качестве ключа можно использовать $request_uri или $uri. Например: limit_req_zone $request_uri zone=by_uri:10m rate=1r/s;. Но будьте осторожны: это может привести к неожиданным эффектам, если URI многообразны.
Вопрос: Что лучше: `limit_req` или `limit_conn`? Они решают разные задачи. limit_req ограничивает частоту запросов, а limit_conn — количество одновременных соединений. Для комплексной защиты используйте оба.
Вопрос: Какой код ошибки возвращать? Рекомендуется 429 (Too Many Requests) — он стандартизирован и понятен клиентам. Код 503 тоже допустим, но менее информативен.
Вопрос: Как проверить, что ограничения работают? Используйте утилиту ab (Apache Bench) или wrk для генерации нагрузки и смотрите на коды ответов. Также анализируйте логи ошибок Nginx.
Вопрос: Можно ли применять лимиты только к POST-запросам? Да, с помощью карты map можно задать ключ только для определённых методов. Например:
map $request_method $limit_key {
POST $binary_remote_addr;
default "";
}
limit_req_zone $limit_key zone=post_limit:10m rate=1r/s;Итог
Настройка ограничения частоты запросов в Nginx — мощный и гибкий способ защитить сервер от перегрузок и атак. Используйте limit_req_zone для определения зон, limit_req для применения лимитов, экспериментируйте с burst и nodelay, не забывайте про мониторинг. Комбинируйте с limit_conn для комплексной защиты. Помните, что цель — не заблокировать всех, а отсечь вредоносный трафик, сохранив комфорт для реальных пользователей.
Читайте также
Комментарии
Комментарии доступны только зарегистрированным пользователям. Войти
- Пока нет комментариев. Будьте первым.



