Вопрос или проблема
Пытаюсь заставить nginx работать следующим образом:
Ограничение скорости по умолчанию 1r/s для каждого IP при использовании браузера. Ограничение скорости 10r/s для поисковых роботов bing и google. Отклонение плохих ботов.
К сожалению, google не публикует IP-адреса для googlebot, поэтому я ограничен использованием useragent.
Пока что это приближается к цели:
http {
# Ограничения скорости
map $http_user_agent $uatype {
default 'user';
~*(google|bing|msnbot) 'okbot';
~*(slurp|nastybot) 'badbot';
}
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=two:10m rate=10r/s;
...
server {
...
location / {
if ($uatype == 'badbot) {
return 403;
}
limit_req zone=one burst=5 nodelay;
if ($uatype != 'user') {
limit_req zone=two burst=10 nodelay;
}
...
}
...
}
}
НО – ‘if’ не разрешено использовать таким образом.
$ nginx -t
nginx: [emerg] “limit_req” directive is not allowed here in /etc/nginx/nginx.conf nginx: неудалось протестировать конфигурационный файл /etc/nginx/nginx.conf
Так много непроверенных предложений на форумах nginx, большинство из них даже не проходят проверку конфигурации.
Один из перспективных вариантов – Ограничение скорости в Nginx по рефереру? — Недостатком этой версии является то, что вся конфигурация повторяется для каждого разного ограничения (у меня много правил переписывания)
Кто-нибудь узнал что-то полезное?
К сожалению, таким образом нельзя динамически задавать параметры, модуль ограничения запросов этого не поддерживает.
Ссылка, которую вы нашли, вероятно, единственный способ достичь этого. Используйте директиву include
, чтобы “избежать” повторения вашей конфигурации.
Но что, если сторонний краулер вдруг начнет выдавать себя за пользователя goodbot?
Сегодня я смог реализовать ограничение скорости на основе user agent; попробуйте это:
map $http_user_agent $bad_bot {
default 0;
(foo|bar) 1;
}
map $http_user_agent $nice_bot {
default "";
(baz|qux) 1;
}
limit_req_zone $nice_bot zone=one:10m rate=1r/s;
limit_req_status 429;
server {
...
location / {
limit_req zone=one nodelay;
if ($badbot) {
return 403;
}
...
}
}
Очень запоздалый ответ. Но так как я потратил большую часть сегодняшнего дня на изучение этой проблемы, я подумал, что покажу, что сработало для меня. Кратко, это использование map
и перезапуск службы вместо простого сигнала о перезагрузке.
Вот что у меня есть ближе к началу моего файла sites-available/default
:
# Строки user agent могут быть довольно длинными
map_hash_bucket_size 256;
# Определяем тип агента (бот или нет)
map $http_user_agent $agent_type {
# Не бот
default 0;
# Все ниже перечисленные - это боты, которые должны иметь ограничение скорости
"~*(Amazonbot|ClaudeBot|DataForSeoBot|GPTBot|SemrushBot)" 1;
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, как Gecko) Chrome/127.0.0 Safari/537.36" 1;
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, как Gecko) Chrome/133.0.0.0 Safari/537.36" 1;
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, как Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43" 1;
}
# Определяем зоны ограничения скорости для использования позже
map $agent_type $default_zone_key {
default '';
0 $binary_remote_addr;
}
limit_req_zone $default_zone_key zone=default_zone:20m rate=5r/s;
map $agent_type $bot_zone_key {
default '';
1 $binary_remote_addr;
}
limit_req_zone $bot_zone_key zone=bot_zone:10m rate=6r/m;
Обратите внимание, что помимо некоторых ботов, которые объявляют о себе (например, ClaudeBot и GPTBot), я добавил несколько случаев “точно такого же” для некоторых ботнетов, которые не объявляют о себе. Возможно, я случайно наказываю некоторых реальных пользователей. Но я просто рад, что это работает.
Затем в разделе server
у меня есть это:
server {
server_name somedomain.com;
...
limit_req zone=default_zone burst=50 nodelay;
limit_req zone=bot_zone burst=10 nodelay;
limit_req_status 429; # Слишком много запросов
...
# Хотите узнать, считается ли вы ботом? Раскомментируйте следующее:
#add_header X-Routing-Agent-Type "$agent_type";
}
Если вы не понимаете, что происходит, я объясню. Как относительно начинающий в NGINX я вас понимаю. limit_rate_zone
позволяет задать ключ. Если он пуст, то это правило фактически игнорируется. В нашем случае мы подаем IP-адрес. Более конкретно, у нас есть два правила. Одно правило совпадает со всеми IP-адресами, связанными с ботами (по user agent). Другое правило совпадает со всеми IP-адресами, которые нет. Эти блоки map $agent_type <ключ>
заполняют эти два ключа IP-адресов или пустых строк.
Стоит отметить, что вы можете добавить больше номеров $agent_type
, если хотите более тонкое градиентирование, чем просто “бот” и “все остальное”. Вам просто нужно будет добавить больше различных блоков определений и строк.
Сегодня я был так расстроен, потому что многие из того, что я пробовал, не работало. Только под конец я понял, что NGINX не загружает мою конфигурацию, как ожидалось. Я использовал nginx -s reload
. Все заработало, когда я вместо этого использовал service nginx restart
.
.
Ответ или решение
Вопрос о том, как ограничить скорость запросов в Nginx на основе User-Agent, является актуальной задачей для администраторов серверов, стремящихся оптимизировать нагрузку и защитить свои ресурсы от потенциально вредоносных или нежелательных ботов. Давайте подробно разберем, как реализовать такую конфигурацию и на что стоит обратить внимание.
Теория
Цель состоит в том, чтобы создать три различные стратегии обработки запросов, основанные исключительно на User-Agent:
- Браузеры пользователей: Ограничение скорости 1 запрос в секунду (1r/s) для каждого IP-адреса.
- Поисковые боты (например, Googlebot и Bingbot): Большее ограничение скорости — 10 запросов в секунду (10r/s).
- Плохие боты: Прямой отказ в доступе с кодом ответа HTTP 403.
Для выполнения этих задач используется модуль Nginx для ограничения запросов (limit_req
), который требует жесткого контроля конфигурации и тщательной настройки.
Пример
Важно использовать директиву map
для классификации User-Agent. Мы создадим несколько map
, которые позволят накладывать различные условия на определенные группы пользователей:
http {
# Регистрация User-Agent
map $http_user_agent $uatype {
default 'user';
~*(google|bing|msnbot) 'okbot';
~*(slurp|nastybot) 'badbot';
}
# Определение зон ограничения запросов
limit_req_zone $binary_remote_addr zone=user_zone:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=bot_zone:10m rate=10r/s;
server {
...
location / {
# Ограничить доступ для плохих ботов
if ($uatype = 'badbot') {
return 403;
}
# Применение ограничений для браузеров пользователей
limit_req zone=user_zone burst=5 nodelay;
# Применение ограничений для хороших ботов
if ($uatype = 'okbot') {
limit_req zone=bot_zone burst=10 nodelay;
}
...
}
...
}
}
Применение
Теперь мы подробно разберем, как правильно реализовать этот подход, учитывая ограничения конфигурации Nginx.
Шаг 1: Настройка map
map
позволяет динамически задавать переменные на основе условий. В нашем случае мы использовали регулярные выражения для определения, является ли User-Agent плохим ботом (badbot
), хорошим ботом (okbot
) или пользовательским (user
). Мы создали три категории, но вы можете добавлять больше в зависимости от необходимости.
Шаг 2: Определение зон ограничения
Директива limit_req_zone
используется для установления зон ограничения скорости. Каждая зона основана на IP-адресе пользователя ($binary_remote_addr
), что делает ограничения применимыми отдельно для каждого IP.
Шаг 3: Конфигурация сервера
В блоке сервера мы применяем мультиустойчивую логику через map
и limit_req
. Это позволяет реализовать более сложные стратегии на уровне location.
Решение проблем с if
Использование if
в Nginx может быть проблематичным, так как оно не всегда работает предсказуемо. Вместо этого рекомендуется использовать встроенные механизмы Nginx, такие как map
и ngx_http_rewrite_module
для задания условий.
Кроме того, важно использовать правильный подход к перезапуску и повторному анализу конфигурации Nginx. Часто nginx -s reload
может не работать правильно, и требуется более тщательный подход, например, sudo service nginx restart
, чтобы убедиться, что изменения применились корректно.
Заключение
Настройка ограничения скорости запросов на основе User-Agent в Nginx — это более сложная задача, чем может показаться на первый взгляд. Она требует детального понимания работы Nginx и возможности применять его богатый функционал для достижения поставленных целей. Важно не только стандартизировать ваш подход к классификации запросов, но и быть готовым к адаптации при возникновении новых сценариев использования или угроз.
Учитывая вышеописанные методы, можно эффективно управлять нагрузкой на ваш сервер, обеспечивая безопасность и высокую производительность для конечных пользователей.