sadrix logoSadriX
Минцифры готовит обязательную регистрацию IMEI смартфонов, купленных за границей
Гайды

Как ограничить частоту запросов в Nginx: защита от DDoS и брутфорса

Настройка модуля limit_req для контроля нагрузки и предотвращения атак

08 920 просмотров5 мин
0
Поделиться:TelegramVK

Введение

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, чтобы найти баланс между безопасностью и удобством пользователей. Не забывайте тестировать конфигурацию и мониторить логи. Тогда ваш сайт останется доступным даже при неблагоприятных условиях.

Читайте также

Комментарии

Комментарии доступны только зарегистрированным пользователям. Войти

  • Пока нет комментариев. Будьте первым.