Как ограничить частоту запросов в Nginx: защита от DDoS и брутфорса
Настройка модуля limit_req для контроля нагрузки и предотвращения атак
Введение
Nginx — один из самых популярных веб-серверов и обратных прокси, но даже он не застрахован от чрезмерной нагрузки. Всплески трафика могут быть вызваны как легитимными пользователями (например, при распродаже), так и злоумышленниками, пытающимися подобрать пароль или устроить простой DDoS. Ограничение частоты запросов (rate limiting) — эффективный способ защитить бэкенд, снизить нагрузку и сохранить доступность сервиса.
В этой статье мы подробно разберём, как настроить rate limiting в Nginx с помощью модуля ngx_http_limit_req_module. Вы узнаете, как работают зоны, что такое burst и nodelay, как применять лимиты к разным частям сайта и избежать типичных ошибок.
Требования
Установленный Nginx (версия 1.18+ рекомендуется). Проверить можно командой
nginx -v.Права на редактирование конфигурационных файлов (обычно
/etc/nginx/nginx.confили файлы в/etc/nginx/conf.d/).Базовое понимание синтаксиса Nginx и работы HTTP.
Доступ к командной строке с правами sudo.
1. Как работает limit_req в Nginx
Модуль limit_req использует алгоритм «leaky bucket» (дырявое ведро). Суть проста: запросы от одного клиента (определяемого по ключу, например, IP-адресу) помещаются в очередь. Если скорость поступления запросов превышает заданную, лишние запросы либо отбрасываются с ошибкой 503, либо задерживаются, если разрешён burst.
Основные понятия:
Зона (zone) — общая память, где хранятся счётчики для каждого ключа.
Ключ (key) — параметр, по которому группируются запросы (обычно
$binary_remote_addr).Rate — допустимая скорость запросов (например, 10r/s).
Burst — максимальное количество запросов сверх лимита, которые могут быть обработаны с задержкой.
Nodelay — при использовании burst запросы обрабатываются сразу, без задержки, но всё равно ограничиваются по скорости.
2. Определение зоны limit_req_zone
Директива limit_req_zone задаётся в контексте http. Она создаёт зону разделяемой памяти.
Пример:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
...
}Здесь:
$binary_remote_addr— ключ (IP-адрес клиента в бинарном виде, экономит память).zone=one:10m— имя зоны и размер 10 МБ (хватит примерно на 160 000 уникальных IP).rate=10r/s— средняя скорость 10 запросов в секунду.
Можно использовать и другие ключи: $server_name, $http_user_agent или комбинации. Но для защиты от брутфорса и DDoS чаще всего берут IP.
3. Применение лимита в location
После создания зоны её нужно применить в нужном location или server с помощью директивы limit_req.
Пример для всего сервера:
server {
listen 80;
server_name example.com;
limit_req zone=one burst=20 nodelay;
location / {
proxy_pass http://backend;
}
}Здесь burst=20 разрешает до 20 запросов сверх лимита, а nodelay заставляет Nginx обрабатывать их немедленно, не задерживая. Без nodelay запросы из burst будут обрабатываться с задержкой, чтобы средняя скорость соответствовала rate.
4. Настройка burst и nodelay
Параметры burst и nodelay — ключевые для тонкой настройки.
burst — это буфер для кратковременных всплесков. Если клиент делает 15 запросов при rate=10r/s, то 10 будут обработаны сразу, а 5 попадут в очередь. Без burst лишние запросы сразу получат 503.
nodelay — если указан, запросы из очереди обрабатываются сразу, а не с задержкой. Это удобно для API, где важна скорость ответа.
Пример с задержкой (без nodelay):
limit_req zone=one burst=5;Клиент, превысивший лимит, будет получать ответы с задержкой, что может быть нежелательно.
Рекомендация: для большинства случаев используйте burst и nodelay вместе, чтобы сгладить пики, но не тормозить пользователей.
5. Ограничение для разных location
Можно создавать несколько зон и применять их к разным частям сайта.
Пример:
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
server {
location /api/ {
limit_req zone=api burst=10 nodelay;
proxy_pass http://api_backend;
}
location /login {
limit_req zone=login burst=3 nodelay;
proxy_pass http://auth_backend;
}
}
}Так вы защитите чувствительные эндпоинты (вход, регистрация) более строгими лимитами, а API — более мягкими.
6. Настройка кода ответа и логирования
По умолчанию при превышении лимита Nginx возвращает 503 Service Unavailable. Это можно изменить директивой limit_req_status.
Пример:
limit_req_status 429;Код 429 (Too Many Requests) более информативен для клиента.
Также можно настроить уровень логирования для отклонённых запросов:
limit_req_log_level warn;По умолчанию используется error. Уровень warn поможет снизить шум в логах.
7. Тестирование конфигурации
После внесения изменений обязательно проверьте синтаксис:
sudo nginx -tЕсли ошибок нет, перезагрузите Nginx:
sudo systemctl reload nginxДля тестирования можно использовать утилиту ab (ApacheBench) или wrk. Например, отправить 100 запросов с 10 потоками:
ab -n 100 -c 10 http://example.com/loginСмотрите, сколько запросов получили 429/503. Так вы убедитесь, что лимит работает.
8. Мониторинг и анализ логов
Ведите мониторинг ошибок 429/503. В логах Nginx они будут отмечены как limiting requests. Можно использовать grep:
grep 'limiting requests' /var/log/nginx/error.logЕсли таких записей слишком много, возможно, лимиты слишком строгие. Проанализируйте, какие IP чаще всего попадают под ограничения, и при необходимости скорректируйте зоны.
9. Типичные ошибки
1. Слишком маленький burst — приводит к отказу обслуживания при малейшем всплеске. Увеличьте burst, если пользователи жалуются на 429. 2. Использование `$remote_addr` вместо `$binary_remote_addr` — первый хранится как строка и занимает больше памяти. Всегда используйте бинарный формат. 3. Забыли про `nodelay` — запросы могут обрабатываться с задержкой, что увеличивает время ответа. 4. Применение лимита ко всем запросам, включая статику — это может замедлить загрузку сайта. Лучше ограничивать только динамические или чувствительные location. 5. Неправильный размер зоны — если зона переполнится, новые ключи не будут добавляться, и лимит перестанет работать. Следите за размером: 1 МБ ≈ 16 000 IP. 6. Отсутствие мониторинга — без анализа логов вы не узнаете, что лимиты мешают легитимным пользователям.
10. FAQ
Вопрос: Можно ли ограничивать по количеству соединений, а не запросов? Да, для этого есть модуль limit_conn. Он полезен для ограничения числа одновременных соединений с одного IP.
Вопрос: Что делать, если за прокси стоит много пользователей с одним IP? В таком случае используйте другой ключ, например, $http_x_forwarded_for или комбинацию с cookie. Но будьте осторожны: эти заголовки легко подделать.
Вопрос: Как исключить определённые IP из ограничений? Можно использовать geo и map для создания белого списка. Например, задать переменную, которая будет пустой для доверенных IP, и использовать её как ключ.
Вопрос: Влияет ли rate limiting на SEO? Если поисковые боты получают 429, это может негативно сказаться на индексации. Настройте отдельные лимиты для известных ботов или добавьте их в белый список.
Вопрос: Можно ли использовать несколько зон одновременно? Да, можно применить несколько директив limit_req в одном location. Тогда будут действовать оба ограничения.
Итог
Настройка rate limiting в Nginx — мощный инструмент для защиты от перегрузок и атак. Используйте limit_req_zone для создания зон, limit_req для применения лимитов, экспериментируйте с burst и nodelay, чтобы найти баланс между безопасностью и удобством пользователей. Не забывайте тестировать конфигурацию и мониторить логи. Тогда ваш сайт останется доступным даже при неблагоприятных условиях.
Читайте также
Комментарии
Комментарии доступны только зарегистрированным пользователям. Войти
- Пока нет комментариев. Будьте первым.



