...

Ограничение пропускной способности в NGINX: эффективная защита от бот-трафика и атак

Скорость 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
  • Итеративная донастройка и оповещение об аномалиях

Текущие статьи

Веб-сервер NGINX в современном центре обработки данных с визуализированными потоками данных
Веб-сервер Plesk

Ограничение пропускной способности в NGINX: эффективная защита от бот-трафика и атак

Узнайте, как с помощью функции ограничения скорости NGINX защитить свой сайт от бот-трафика и атак, тем самым повысив безопасность веб-сервера. Включены практические примеры и рекомендации.

Сервер Linux с визуализированными показателями давления и сваливания в центре обработки данных
Администрация

Linux PSI для точного анализа производительности и мониторинга

Linux PSI (Pressure Stall Information) позволяет увидеть, насколько сильно процессор, память и операции ввода-вывода замедляют работу вашей системы. Узнайте, как включить PSI и использовать его для точного мониторинга производительности.

Визуализация современной архитектуры Redis Streams с потоками данных в центре обработки данных
Базы данных

Redis Streams — мощная альтернатива традиционным очередям сообщений

Узнайте, как Redis Streams обеспечивает современный обмен сообщениями без использования дополнительных систем очередей и повышает эффективность вашей системы обмена сообщениями на базе Redis.