Скорость NGINX Limiting останавливает автоматические запросы, снижает пиковую нагрузку и защищает конечные точки входа в систему, API и форм от ботов и атак. Я покажу тебе, как задавать ограничения и применять их для Защита от ботов и на его основе разрабатывает надежную концепцию безопасности для сайтов с высокой посещаемостью.
Центральные пункты
Существенно Вот основные тезисы:
- Ограничения по ставкам предотвращают вредоносные атаки и защищают бэкенд-ресурсы.
- Burst/без задержки поглощают законные пики, не блокируя пользователей.
- зоны разделять людей и ботов с разными лимитами.
- Ведение журнала предоставляет данные для итеративного уточнения пределов.
- Интеграция в сочетании с WAF, защитой от DDoS-атак и мониторингом повышает эффективность.
Почему ограничение скорости позволяет своевременно пресекать атаки
Нападающие делают ставку на высокую Частота запросов, чтобы злоупотреблять формами входа, перегружать API или автоматически сканировать контент. Поэтому я ограничиваю количество запросов на один ключ — как правило, на один IP-адрес — и решаю, следует ли их ограничить, задержать или ответить кодом 429. Таким образом я защищаю процессор, базу данных и логику приложения от бот-трафика, пропуская при этом легитимных пользователей. Особенно выигрывают от этого такие чувствительные пути, как /login, /auth, /xmlrpc.php, а также ресурсоемкие поиски. Источником данного метода является Документация по Nginx о модуле ngx_http_limit_req_module.
Как работает модуль NGINX на практике
Модуль работает по принципу Негерметичное ведроПринцип: для каждого ключа NGINX сохраняет показатели счетчика в зоне и сравнивает их с допустимой скоростью. Типичными ключами являются $binary_remote_addr для IP-адресов, токены для ключей API или значения, полученные с помощью map. Если клиент постоянно превышает допустимую скорость и пределы буфера пиковых нагрузок, NGINX отклоняет запрос до его передачи на бэкенд. Это экономит вычислительное время и снижает задержки для реальных посетителей. В качестве ответа я использую код 429 «Too Many Requests» или, по желанию, другой Код состояния эм...
Настройка: пошаговое руководство
Я начинаю с зоны в разделе http, устанавливаю умеренную скорость и целенаправленно активирую её на уязвимых маршрутах. Для кратковременных пиков я определяю режим «Burst», при необходимости с параметром «nodelay», чтобы избежать резких отказов. Затем я тестирую в тестовой среде и анализирую логи, прежде чем запускать систему в производственную среду. Таким образом, я не рискую наложить ненужные ограничения на реальных пользователей. Конкретный пример иллюстрирует Синтаксис осязаемый:
# http {}
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
server {
location /api/ {
limit_req zone=req_limit_per_ip burst=20 nodelay;
limit_req_status 429;
}
location /login {
limit_req zone=req_limit_per_ip burst=5;
limit_req_status 429;
}
}
Защита от ботов с использованием зон и логики User-Agent
Ограничения на основе IP-адресов редко оказываются достаточными для борьбы с распределенными ботнетами, поэтому я разделяю трафик на зоны: Для людей устанавливаются более щедрые ограничения, а для обычных краулеров — более строгие. С помощью map я анализирую пользовательские агенты, распознаю разрешенных ботов, таких как Googlebot, и устанавливаю для них отдельные, тщательно контролируемые ограничения. Для безымянных скрейперов я устанавливаю жесткие ограничения на дорогостоящих маршрутах. При обнаружении подозрительных паттернов я динамически повышаю строгость ограничений, пока Тариф снова находится в пределах нормы.
Точная настройка: скорость передачи, пакетная передача, отсутствие задержки и коды состояния
Параметр «Rate» регулирует пропускную способность в секунду, «Burst» допускает кратковременное буферирование, а «nodelay» определяет, что я предпочитаю: буферизацию или немедленную пропускную способность. Я начинаю с умеренных значений, например, 10r/s с burst 20 для API, а затем настраиваю параметры после анализа логов. Для маршрутов входа в систему я устанавливаю, например, 1r/s с небольшим burst, чтобы замедлить атаки методом перебора. В случае превышения лимитов я возвращаю код 429, поскольку клиенты благодаря этому справляться и алгоритм повторных попыток работает как надо. В особых случаях я использую альтернативные коды, если этого требуют клиенты.
Обзор в таблице: директивы и их применение
Следующие Таблица обобщает основные рекомендации и показывает, в каких случаях их целесообразно применять.
| директива | Эффект | Пример | Типичное использование |
|---|---|---|---|
| limit_req_zone | Укажите ключ, зону и Тариф крепко | limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s; | Основание: по IP-адресу, токену или пользовательскому агенту |
| limit_req | Включает ограничение в Местоположение/Сервер | limit_req zone=perip burst=20 nodelay; | Точное управление для каждого пути или виртуального хоста |
| limit_req_status | Добавляет HTTP-код Превышение | limit_req_status 429; | Корректное поведение клиента и повторные попытки |
| карта | Перенаправляет запросы в зоны на сайте | map $http_user_agent $is_bot {…} | Разделение «бот/человек» по User-Agent |
Практика: целенаправленная защита конечной точки входа в систему
Я очень строго ограничиваю количество попыток входа в систему, поскольку боты пробуют пароли с высокой Частота Попробовать разные варианты. 1 запрос в секунду с burst 3 предотвращает массовые попытки взлома, не нанося при этом слишком большого ущерба реальным пользователям. Кроме того, я фиксирую повторяющиеся неудачные попытки в журнале, чтобы временно блокировать IP-адреса. В сочетании с двухфакторной аутентификацией (2FA) и, по желанию, капчей нагрузка на базу данных и систему управления сессиями заметно снижается. Таким образом, я сдерживаю количество неудачных попыток на низком уровне и обеспечиваю Доступ готовы к работе.
Практика: справедливое и контролируемое предоставление API
API должны иметь четкие Коэффициенты, чтобы отдельные клиенты не занимали всю пропускную способность. Для общих маршрутов я устанавливаю 10 запросов в секунду и пиковую нагрузку 20, для важных конечных точек — более строгие значения. Если доступны токены или API-ключи, я устанавливаю ограничения на каждый токен, а не на каждый IP-адрес. Это обеспечивает справедливость между клиентами и предотвращает злоупотребления. Более подробную информацию можно найти в моей заметке о Ограничение скорости API, в котором эта концепция рассматривается в более широком контексте.
Мониторинг, ведение журналов и итеративная доработка
Я регистрирую 429 ответов, включая Ключевой (например, IP-адрес или токен) и путь, чтобы выявить закономерности. Всплески на нескольких путях указывают на скрапинг или атаки методом перебора; распределенная нагрузка свидетельствует о ботнетах. Используя эти данные, я устанавливаю ограничения только там, где это необходимо, и свожу к минимуму ложные срабатывания. Дашборды с показателями скорости, доли ошибок и задержки позволяют мне оценить эффект каждого изменения. Таким образом, Производительность высокий, в то время как уровень защиты повышается.
Включение в комплексную концепцию защиты
Я считаю ограничение скорости эффективным первым шагом слой, но я сочетаю его с правилами WAF, оценкой репутации IP-адресов и усилением безопасности TLS. Против массивных атак помогает предшествующая защита от DDoS-атак, которая фильтрует трафик на сетевом уровне до того, как NGINX начнёт работать. Я постоянно отслеживаю метрики, настраиваю оповещения о необычных пиках нагрузки и реагирую обновлением правил. Таким образом, из нескольких компонентов формируется надёжная система защиты. Практический обзор дают следующие Стратегии защиты от DDoS-атак.
Конкретные шаблоны поведения ботов и людей
Я разделяю посетителей по категориям с помощью map и направляю их в отдельные зоны. Известным краулерам устанавливаются умеренные ограничения, а общим агентам — более строгие. К путям типа /search или /report я отношусь более строго, так как они сильно загружают процессор. В случае повторных нарушений я не повышаю лимиты, а на время блокирую доступ или перенаправляю проверку в модуль распознавания ботов. Таким образом, Показатель неправомерного использования незначительный, не создавая помех для работы поисковых систем.
Пример: две зоны и сопоставление пользовательских агентов
В приведённом ниже фрагменте показано разделение по Пользовательский агент и назначение соответствующих ограничений. Я сочетаю это с дифференцированными кодами статуса и полями журнала, чтобы точно измерить эффективность. Боты с общим агентом попадают в зону с жесткими ограничениями. Люди или проверенные сканеры используют зону с более мягкими ограничениями. Такой подход обеспечивает предсказуемые Пропускная способность на каждый класс:
map $http_user_agent $is_bot {
default 0;
"~*googlebot" 0;
"~*bingbot" 0;
"~*crawler|scraper|bot" 1;
}
limit_req_zone $binary_remote_addr zone=human:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=bot:10m rate=1r/s;
server {
location / {
if ($is_bot) {
limit_req zone=bot burst=5;
}
if ($is_bot = 0) {
limit_req zone=human burst=20 nodelay;
}
limit_req_status 429;
}
}
Обработка ошибок: правильное отображение ошибки 429
В разделе «Лимиты» я даю четкое Ответить с указанием, когда целесообразно повторить попытку. Для API-интерфейсов это включает в себя заполнение заголовка Retry-After, чтобы клиенты применяли алгоритм отката (backoff). Пользователи-люди получают краткое объяснение без технических подробностей. Это сокращает количество обращений в службу поддержки и обеспечивает понятное поведение системы. Четкое UX делает ограничения приемлемыми и предотвращает разочарование.
Хостинг, сеть и ядро: укрепление фундамента
Высокий объем легитимного трафика и меры защиты требуют надежных Ресурсы и разумные настройки по умолчанию на сетевом уровне. Я слежу за актуальными версиями NGINX, достаточным объемом оперативной памяти для зон и средствами защиты от транспортных атак. Для защиты от SYN-флудов помогает активация TCP SYN-куки в ядре, чтобы соединения не застревали. В целом это избавляет NGINX от ненужной нагрузки. Таким образом, я сосредотачиваю ограничения на HTTP-уровнях и поддерживаю Пропускная способность стабильный.
Вкратце: как я эффективно использую ограничение скорости в NGINX
Я ограничиваю количество запросов на ключ, изолирую критические пути и удерживаю ботов на расстоянии с помощью строгого зонирования. Функции Burst и nodelay помогают допускать легитимные пики нагрузки, не способствуя при этом злоупотреблениям. На основе 429-журналов я постоянно настраиваю параметры и ужесточаю ограничения только там, где в этом есть необходимость. В сочетании с WAF, защитой от DDoS-атак, мониторингом и укреплением ядра получается надёжная концепция защиты. Кто последовательно её реализует, значительно сокращает бот-трафик и сохраняет Производительность даже под нагрузкой.
Элементы, которые часто отсутствуют на практике
Во многих конфигурациях отсутствуют некоторые ключевые компоненты, которые заметно повышают эффективность ограничения скорости:
- Реальные IP-адреса клиентов за прокси-серверами: Без правильной обработки реальных IP-адресов NGINX часто ограничивает IP-адрес устройства балансировки нагрузки — в этом случае ограничения распространяются на всех пользователей, объединенных в пул.
- Пробные запуски (Dry-Run): Лимиты активируются „вслепую“. Лучше сначала просто отслеживать, сколько раз лимит сработал бы.
- Ключи с мелкой зернистостью: Вместо того чтобы ограничивать доступ только по IP-адресу, целесообразно вводить ограничения на каждый API-токен, сеанс или пользователя, чтобы обеспечить более справедливое распределение ресурсов.
- Взаимодействие с limit_conn: Параллельные соединения и частота запросов отражают различные модели злоупотребления.
- Целевые исключения: Для проверок работоспособности, веб-хуков или внутренних сервисов часто требуются более мягкие ограничения или их полное отсутствие.
Обратный прокси: надежный анализ реального IP-адреса клиента
Если NGINX находится за балансировщиком нагрузки, я задаю директивы Real-IP, чтобы $binary_remote_addr отражал реальный адрес клиента. Я доверяю только тем сетям, которые принадлежат мне, и включаю рекурсивную оценку:
http {
# Диапазоны IP-адресов доверенных прокси-серверов (пример)
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 192.168.0.0/16;
# при необходимости добавьте диапазоны публичных LB/CDN
real_ip_header X-Forwarded-For;
real_ip_recursive on;
limit_req_zone $binary_remote_addr zone=perip:20m rate=10r/s;
}
Без этой настройки ограничение может затронуть одновременно большое количество невиновных пользователей. После настройки я проверяю по журналам доступа, появляется ли ожидаемый IP-адрес клиента.
Ключевая стратегия: IP, пользователи, токены и путь
Выбранный ключ определяет справедливость и эффективность. Несколько проверенных шаблонов:
- Pro IP ($binary_remote_addr): Быстро готов к работе, подходит для /login и анонимных конечных точек.
- На каждый токен API: Справедливость в отношениях между клиентами; защита от NAT-объединения. Я извлекаю токены с помощью map.
- По классу пути: Отдельно ограничивать дорогостоящие конечные точки, например, /search в большей степени, чем /status.
map $http_authorization $api_token {
default "";
"~*^Bearer\s+(.+)$" $1;
}
limit_req_zone $api_token zone=per_token:30m rate=5r/s;
server {
location /api/ {
# Имеет значение только при наличии токена
limit_req zone=per_token burst=10;
limit_req_status 429;
}
}
Важно: высокая кардинальность ключей приводит к значительному потреблению памяти в зоне. Предусмотрите буферы и следите за загрузкой памяти.
Накопители и расчет размеров зон
Зона сохраняет метаданные для каждого активного ключа. Объём данных на одну запись составляет несколько десятков байт плюс накладные расходы. Из этого я делаю следующий вывод:
- Если одновременно используется много IP-адресов/токенов, я выбираю зоны большего размера, например, 50–100 МБ.
- Я начинаю с достаточно широких настроек и просматриваю логи NGINX: сообщение „shared memory zone is full“ указывает на необходимость донастройки.
- Неиспользованные ключи теряют силу после короткого периода бездействия; пиковые значения важнее среднесуточных.
Точное использование режимов Burst и nodelay
Без nodelay NGINX упорядочивает превышения в пределах буфера всплеска и с задержкой Запросы. С помощью nodelay допустимые пакетные запросы пропускаются немедленно, а избыточные — отклоняются. Мой подход:
- Интерактивные маршруты (HTML): лучше без nodelay, чтобы создавать короткие задержки вместо жестких ошибок 429.
- API: часто с параметром nodelay, чтобы клиенты однозначно получали код 429 и применяли алгоритм отката.
- Дорогие конечные точки: небольшой импульс для сглаживания пиков в бэкенде.
Пробный запуск, уровень журнала и анализ
Прежде чем ввести ограничения в действие, я включаю режим «Dry-Run» и настраиваю уровень логгирования. Так я могу увидеть результат без риска:
server {
location /api/ {
limit_req zone=perip burst=20;
limit_req_dry_run on; # — только регистрировать, не блокировать
limit_req_log_level notice; # — менее строго, чем 'error'
}
}
Затем я анализирую данные о доступе за 3–7 дней, выявляю «горячие точки», настраиваю параметры rate/burst и только после этого отключаю режим Dry‑Run.
429. Чистая передача данных: HTML, JSON и Retry-After
Для обеспечения хорошего пользовательского опыта (UX) я разделяю браузеры и API-клиенты и использую Retry‑After. Вот как я чётко сообщаю о пределах:
map $http_accept $wants_json {
default 0;
"~*application/json|/json" 1;
}
server {
error_page 429 = @rate_limited;
location @rate_limited {
add_header Retry-After 2 always;
if ($wants_json) {
add_header Content-Type application/json;
return 429 '{"error":"too_many_requests","retry_after":2}';
}
return 429 "Пожалуйста, попробуйте позже.";
}
}
API могут реагировать программно, а пользователи получают понятное сообщение.
Объединение limit_req и limit_conn
limit_req пропускная способность за временной интервал, limit_conn ограничивает количество одновременных подключений. Для защиты от скачиваний, «болтливых» клиентов или HTTP/2-флудов я использую комбинацию обоих методов:
limit_conn_zone $binary_remote_addr zone=perip_conn:10m;
server {
location /api/ {
limit_req zone=perip burst=20 nodelay;
limit_conn zone=perip_conn 20; #, максимум 20 одновременных подключений на один IP-адрес
}
}
Таким образом я предотвращаю ситуацию, когда небольшое количество клиентов, хотя и соблюдают ограничение по скорости, но из-за слишком большого количества параллельных соединений занимают ресурсы.
Исключения, проверки работоспособности и внутренние маршруты
Не для каждого пути требуются ограничения. Проверки работоспособности (/healthz), внутренние веб-хуки или обратные вызовы платежных систем получают собственные локации без параметра limit_req — либо с более мягкими значениями:
server {
# без ограничений для проверок работоспособности
location = /healthz { return 200 "ok"; }
# мягкие ограничения для обратных вызовов при оплате
location /webhooks/pay/ {
limit_req zone=perip burst=5;
}
# строгая защита для входа в систему
location = /login {
limit_req zone=perip rate=1r/s burst=3;
}
}
Детальные исключения снижают количество ложных срабатываний и обеспечивают стабильную работу интеграций.
Более надежная зональная маршрутизация без использования «If-магии»
Для разделения „бот против человека“ я предпочитаю использовать внутренние перенаправления через именованные локации. Это делает настройку понятной и предсказуемой:
map $http_user_agent $is_bot {
default 0;
"~*googlebot|bingbot" 0;
"~*crawler|scraper|bot" 1;
}
limit_req_zone $binary_remote_addr zone=human:20m rate=10r/s;
limit_req_zone $binary_remote_addr zone=bot:10m rate=1r/s;
server {
error_page 418 = @bot;
location / {
if ($is_bot) { return 418; } # внутреннее перенаправление
limit_req zone=human burst=20 nodelay;
limit_req_status 429;
try_files $uri $uri/ /index.html;
}
location @bot {
limit_req zone=bot burst=5;
limit_req_status 429;
}
}
Таким образом, боты детерминированно попадают в «строгую» зону, а люди — в «расслабленную», причем эти два ограничения не действуют одновременно.
Тестирование, измерение, примерка: практичный порядок действий
- Постановка: выбрать консервативный режим «Rate/Burst», включить «Dry-Run», запустить синтетическую нагрузку на «Hot-Path».
- Дымовые испытания: С помощью curl или Lasttools создать короткие импульсы и проверить поведение при кодах ошибок 429 и задержках.
- Пилотная версия для производственной среды: Сначала применить к отдельным локациям, тщательно отслеживать журналы.
- Итеративная заточка: Устанавливать ограничения только там, где прослеживаются закономерности; свести к минимуму ложные срабатывания.
Пример #: быстрый тест с серийными запросами с помощью curl
for i in {1..50}; do curl -s -o /dev/null -w "%{http_code}\n" https://example.com/login & done; wait
Счет в минутах вместо секунд и детализированные пути
NGINX поддерживает интервалы в секундах или минутах (r/s, р/м). Чтобы предотвратить злоупотребление при входе в систему, я часто устанавливаю ограничение 60r/m вместо 1r/s, чтобы разрешить короткие законные двойные щелчки, но ограничить непрерывный ввод. Для дорогих путей устанавливаются более жесткие ограничения, чем для дешевых. Пример:
limit_req_zone $binary_remote_addr zone=perip_min:20m rate=60r/m;
server {
location /search/ {
limit_req zone=perip_min burst=10; # более строго
}
location /status {
# без ограничения — недорого и используется внутри сети
return 200;
}
}
Препятствия и как я их обхожу
- Неправильный ключ: При использовании прокси-серверов без реального IP-адреса я случайно ограничиваю доступ для всех пользователей одновременно.
- Слишком маленькие зоны: Сообщение „zone is full“ приводит к непредсказуемому поведению — следует предусматривать запас по мощности.
- Ограничение на всё: Различные пути требуют разных подходов; универсальный подход вызывает разочарование.
- Нет мониторинга: Без анализа по коду 429 ошибки в настройках остаются незамеченными.
- Сверх-белый список: Слишком широкие исключения открывают дорогу для злоупотреблений — следует составлять белые списки целенаправленно, на временной основе и с обеспечением прозрачности.
Особенности работы с HTTP/2, SSE и кэшированием
HTTP/2 объединяет запросы в несколько соединений; limit_conn тем не менее остается актуальным, поскольку потоки потребляют ресурсы. Server-Sent Events или длительные загрузки редко приводят к срабатыванию ограничений скорости (небольшое количество запросов), но отнимают время — в таких случаях я ограничиваю количество одновременных подключений с помощью limit_conn или применяю стратегии управления пропускной способностью. Где это возможно, я снижаю нагрузку с помощью Кэширование (например, статические ресурсы, частые запросы GET), чтобы ограничения срабатывали реже, а пользователи получали ответы быстрее.
Оперативный контрольный список
- Реальный IP-адрес указан правильно, ключ определён (IP/токен/пользователь)
- Зоны имеют достаточно большие размеры, имеются метрики и журналы
- скорость/импульс настроены для каждого класса пути, параметр nodelay установлен намеренно
- Проведено тестирование в режиме Dry-Run, реализована связь по протоколу 429 (Retry-After)
- Исключения для Health/Webhooks, сочетание с limit_conn
- Итеративная донастройка и оповещение об аномалиях


