Как ограничить частоту запросов в Nginx: настройка rate limiting
Защищаем сайт от перегрузки и ботов с помощью модулей limit_req и limit_conn
Введение
Ограничение частоты запросов (rate limiting) — важный инструмент защиты веб-сервера от избыточной нагрузки, будь то случайные всплески трафика, агрессивные парсеры или целенаправленные атаки (брутфорс, DDoS). Nginx предоставляет два основных модуля для этой задачи: ngx_http_limit_req_module (ограничение числа запросов в единицу времени) и ngx_http_limit_conn_module (ограничение числа одновременных соединений). В этом руководстве мы подробно разберём, как настроить оба модуля, избежать типичных ошибок и протестировать конфигурацию.
Требования
Установленный Nginx версии 1.10 или выше (модули limit_req и limit_conn входят в стандартную сборку).
Права на редактирование конфигурационных файлов (обычно
/etc/nginx/nginx.confили файлы в/etc/nginx/conf.d/).Базовое понимание синтаксиса Nginx и умение перезагружать конфигурацию.
Доступ к логам Nginx для диагностики.
Шаг 1: Определите зоны ограничения
Прежде чем прописывать правила, решите, что именно вы хотите ограничивать: запросы к определённым URL (например, /login, /api), ко всему сайту или соединения с одного IP. Для разных целей создаются отдельные зоны. Например, для защиты формы входа достаточно зоны с ключом $binary_remote_addr и скоростью 5 запросов в минуту, а для API — 10 запросов в секунду. Помните, что зоны объявляются на уровне http, а применяются — в server или location.
Шаг 2: Настройте limit_req_zone
Директива limit_req_zone задаёт зону разделяемой памяти для хранения состояния запросов. Синтаксис:
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;Здесь $binary_remote_addr — ключ (IP-адрес клиента в бинарном виде), zone=req_limit:10m — имя зоны и размер памяти (10 МБ хватит примерно на 160 000 уникальных IP), rate=10r/s — разрешённая скорость (10 запросов в секунду). Можно использовать r/m для минут. Если нужно учитывать несколько параметров, например IP и URL, используйте составной ключ: $binary_remote_addr$uri.
Шаг 3: Примените limit_req в location
В нужном блоке location добавьте директиву limit_req:
location /login {
limit_req zone=req_limit burst=5 nodelay;
proxy_pass http://backend;
}Параметр burst=5 разрешает кратковременное превышение скорости до 5 запросов (они ставятся в очередь). nodelay отключает задержку для этих запросов — они обрабатываются сразу, но при превышении лимита возвращается ошибка 503. Без nodelay Nginx будет задерживать обработку, чтобы уложиться в среднюю скорость.
Шаг 4: Настройте limit_conn_zone и limit_conn
Для ограничения числа одновременных соединений с одного IP используется модуль limit_conn. Сначала объявите зону:
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;Затем в server или location примените:
limit_conn conn_limit 10;Это разрешит не более 10 одновременных соединений с одного IP. Полезно для защиты от медленных атак (Slowloris) и скачивания файлов в несколько потоков.
Шаг 5: Настройте код ответа и логирование
По умолчанию при превышении лимита возвращается 503 Service Unavailable. Можно изменить код на 429 Too Many Requests:
limit_req_status 429;
limit_conn_status 429;Эти директивы можно разместить в блоке http, server или location. Для логирования отклонённых запросов добавьте в log_format переменную $limit_req_status (доступна с версии 1.17.6) или просто анализируйте коды ответов в access-логе.
Шаг 6: Настройте отдельные зоны для разных локаций
Часто требуется разная политика для разных частей сайта. Создайте несколько зон:
limit_req_zone $binary_remote_addr zone=login_zone:10m rate=3r/m;
limit_req_zone $binary_remote_addr zone=api_zone:10m rate=20r/s;И применяйте их в соответствующих location:
location /login {
limit_req zone=login_zone burst=2 nodelay;
...
}
location /api/ {
limit_req zone=api_zone burst=10 nodelay;
...
}Шаг 7: Исключите доверенные IP из ограничений
Если у вас есть офисные или мониторинговые IP, которые не должны попадать под лимиты, используйте директиву geo и переменную-исключение:
geo $limited {
default 1;
192.168.1.0/24 0;
10.0.0.1 0;
}
limit_req_zone $limited$binary_remote_addr zone=req_limit:10m rate=10r/s;При значении 0 в переменной $limited ключ зоны будет начинаться с нуля, и такие запросы фактически не будут учитываться (если не добавить другие компоненты). Более надёжный способ — использовать map:
map $remote_addr $limit_key {
default $binary_remote_addr;
192.168.1.0/24 "";
10.0.0.1 "";
}
limit_req_zone $limit_key zone=req_limit:10m rate=10r/s;Пустой ключ означает, что запрос не будет учитываться в зоне.
Шаг 8: Проверьте конфигурацию и перезагрузите Nginx
После внесения изменений обязательно проверьте синтаксис:
nginx -tЕсли ошибок нет, перезагрузите конфигурацию:
nginx -s reloadНе используйте restart без необходимости — reload применяет изменения без разрыва текущих соединений.
Шаг 9: Протестируйте ограничения
Для проверки используйте утилиту ab (Apache Bench) или curl в цикле. Например, отправим 20 запросов подряд с одного IP на /login:
for i in {1..20}; do curl -s -o /dev/null -w "%{http_code}\n" http://example.com/login; doneЕсли настроено rate=3r/m с burst=2, вы должны увидеть несколько кодов 200, затем 429 (или 503). Также проверьте, что доверенные IP не блокируются.
Шаг 10: Анализируйте логи и корректируйте лимиты
Ведите мониторинг отклонённых запросов. В access-логе обратите внимание на коды 429/503. Если их слишком много для легитимных пользователей, увеличьте burst или rate. Если наоборот, атака продолжается — уменьшите лимиты. Помните, что слишком жёсткие ограничения могут навредить SEO и пользовательскому опыту.
Типичные ошибки
1. Использование `$remote_addr` вместо `$binary_remote_addr` — первый хранится как строка и занимает больше памяти. Всегда используйте бинарный вариант. 2. Слишком маленький размер зоны — при нехватке памяти Nginx начнёт удалять старые записи, что снизит эффективность ограничений. Выделяйте с запасом. 3. Забыли `nodelay` — без него запросы в пределах burst будут задерживаться, увеличивая время ответа. Используйте nodelay, если не нужна искусственная задержка. 4. Ограничение по `$uri` без учёта IP — ключ $uri ограничит суммарные запросы ко всем URL, а не по клиентам. Для защиты от ботов комбинируйте $binary_remote_addr с другими переменными. 5. Применение limit_req в `http` без зоны — директива limit_req требует предварительно объявленной зоны. Нельзя использовать её глобально без указания зоны. 6. Игнорирование ошибок 503 — стандартный код может сбивать с толку; лучше явно указать limit_req_status 429. 7. Отсутствие тестирования — после настройки обязательно проверьте поведение под нагрузкой, чтобы не заблокировать реальных пользователей.
FAQ
Вопрос: Можно ли ограничить скорость по URL, а не по IP? Да, в качестве ключа зоны можно указать $uri или $request_uri. Но тогда лимит будет общим для всех клиентов, что обычно нежелательно.
Вопрос: Что лучше использовать: limit_req или limit_conn? Они дополняют друг друга. limit_req ограничивает частоту запросов, limit_conn — число одновременных соединений. Для комплексной защиты применяйте оба.
Вопрос: Как исключить поисковых ботов из ограничений? Создайте map по $http_user_agent, где для известных ботов (Googlebot, YandexBot) задаётся пустой ключ. Но помните, что user-agent можно подделать.
Вопрос: Влияет ли rate limiting на SEO? Если лимиты слишком строгие и поисковые роботы получают ошибки, это может негативно сказаться на индексации. Настройте исключения для доверенных ботов.
Вопрос: Где хранятся данные зон? В разделяемой памяти, указанной при объявлении зоны. При перезагрузке Nginx данные сохраняются, если используется reload, а не restart.
Итог
Настройка ограничения частоты запросов в Nginx — мощный и гибкий способ защитить сервер от перегрузки. Используйте limit_req_zone и limit_req для контроля скорости запросов, а limit_conn_zone и limit_conn — для ограничения одновременных соединений. Не забывайте про тестирование, мониторинг логов и корректировку параметров под реальные условия. Грамотно настроенный rate limiting помогает сохранить производительность и доступность вашего сайта.
Читайте также
Комментарии
Комментарии доступны только зарегистрированным пользователям. Войти
- Пока нет комментариев. Будьте первым.



