Перейти к содержанию

abuse-guard: Авто-блокировка злоупотребляющих клиентов по количеству ответов с ошибками (404/403/5xx)

Требуется план Pro (или выше) подписки GetPageSpeed NGINX Extras.

Установка

Вы можете установить этот модуль в любой дистрибутив на базе RHEL, включая, но не ограничиваясь:

  • RedHat Enterprise Linux 7, 8, 9 и 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 и Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-abuse-guard
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-abuse-guard

Включите модуль, добавив следующее в начало файла /etc/nginx/nginx.conf:

load_module modules/ngx_http_abuse_guard_module.so;

Этот документ описывает nginx-module-abuse-guard v1.1.0, выпущенный 9 июля 2026 года.


Ваш журнал ошибок — это признание. Abuse Guard читает его в реальном времени и блокирует злоупотребляющих клиентов.

Каждый сканер, фуззер и бот для подбора учетных данных оставляет одинаковый отпечаток: сплошные 404, охотящиеся за скрытыми путями, 403, стучащие в закрытые двери, неудачные запросы за неудачным запросом. Abuse Guard отслеживает коды состояния, которые ваш сервер действительно возвращает, идентифицирует клиентов, чей трафик в основном состоит из ошибок, и блокирует их — решение принимается внутри рабочего процесса NGINX, на самом запросе, за несколько микросекунд. Никакого сайдкара. Никакого лог-шиппера. Никакого уровня сценариев. Просто скомпилированный C, который выполняет одну задачу исключительно хорошо.

Технические характеристики

Триггер Уровень ошибок на клиента, который вы выбираете (403/404 по умолчанию)
Действие Временная блокировка — жесткая блокировка на фиксированный срок, а не ограничение
Точка принятия решения Фаза предварительного доступа NGINX, до выполнения любого обработчика или upstream
Модель памяти Фиксированное количество байтов на клиента, независимо от порога → масштаб ботнета
Режим флота Опциональная репликация блокировок между узлами через Redis / Valkey
Долговечность Опциональные снимки блокировок на диске, которые сохраняются при перезагрузках и перезапусках
Объем Один самодостаточный модуль; ноль зависимостей во время выполнения по умолчанию
Платформы RHEL / AlmaLinux / Rocky / CentOS Stream / Oracle / Amazon Linux
##

Проблема, которую он решает

Законопослушные посетители почти никогда не генерируют всплеск ошибок. Злоупотребляющие клиенты генерируют все остальное — эта асимметрия и есть вся игра. Сканер уязвимостей, исследующий вашу структуру, — это стена 404. Бот, исследующий административные конечные точки, — это стена 403. Запуск брутфорса — это стена неудач.

Ограничители скорости обрабатывают этот трафик как любой другой: они замедляют всех по объему запросов и позволяют нарушителю снова войти в систему, как только нагрузка ослабевает. Abuse Guard делает противоположное. Он полностью игнорирует хорошо себя ведущий трафик и оставляет свой единственный ответ — реальную, ограниченную по времени блокировку — для клиентов, определяемых их ошибками.

Используйте ограничитель скорости для формирования нагрузки. Используйте Abuse Guard для удаления злоупотреблений.

Как принимается решение о блокировке

Три движущиеся части, все внутри рабочего процесса:

1 · Утечка счета, на клиента. Каждая клиентская идентичность несет одно небольшое число в общей памяти. Каждая совпадающая ошибка добавляет к нему; счет непрерывно уменьшается на threshold ÷ interval в секунду. Краткий, резкий всплеск поднимает его выше порога; медленный поток никогда не достигает этого. Критически важно, что этот счет — один фиксированный размер записи, независимо от того, насколько высок вы установите порог — так что одна зона с легкостью отслеживает десятки тысяч различных исходных адресов, которые ботнет бросает на вас.

2 · Жесткий срок. В момент, когда счет пересекает ваш порог, клиент получает временную метку blocked_until. До этого момента он просто исчезает — каждый запрос отклоняется на фазе предварительного доступа, до того как NGINX потратит цикл на маршрутизацию, файлы или upstream. Отклонение — это самый дешевый возможный результат.

3 · Корректный отказ в отношении конфиденциальности. Заблокированные клиенты получают 429 Too Many Requests (ваш выбор кода), помеченный так, чтобы ни один общий кэш никогда не мог его сохранить и предоставить наказание одного клиента другому, с Retry-After, сообщающим честным клиентам, когда вернуться.

Идентичности сворачиваются в фиксированный размер дайджест, поэтому ключевание на чем-то большом, как $request_uri или заголовок, стоит ровно столько же памяти, сколько ключевание по IP.

Запустите за минуту

Abuse Guard поставляется как предварительно скомпилированный, подписанный модуль из репозитория GetPageSpeed — просто добавьте его, не требуется инструментальная цепочка сборки.

sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
sudo yum -y install nginx-module-abuse-guard

Подключите его:

load_module modules/ngx_http_abuse_guard_module.so;

http {
    abuse_guard_zone zone=clients:10m;     # одна зона общей памяти

    server {
        location / {
            abuse_guard zone=clients;      # применить здесь
        }
    }
}
sudo nginx -t && sudo systemctl reload nginx

Эти настройки блокируют любой IP, который возвращает 100 403/404 ответов за 5-минутный интервал, на один час. Ужесточите или ослабьте каждое число ниже.

Конфигурация

Abuse Guard состоит из четырех директив. Первая объявляет политику; остальные применяют ее, освобождают людей от нее и (опционально) делятся ею между машинами.

Объявите политику — abuse_guard_zone

Директива уровня http. Она выделяет одну зону общей памяти и устанавливает политику, которая ее регулирует. Установите столько или столько настроек, сколько хотите — имя и размер зоны — это единственное, что вы должны предоставить; разумные значения по умолчанию заполнят остальное (значения, показанные ниже, являются именно этими значениями по умолчанию).

abuse_guard_zone  zone=clients:10m             имя + размер (единственное обязательное)
                  key=$binary_remote_addr      кто "один клиент"
                  statuses=403,404             какие ответы считаются ошибками
                  interval=300s                окно оценки
                  threshold=100                ошибки в этом окне  блокировка
                  block=60m;                   как долго держится блокировка

zone=clients:10m — это идентичность и бюджет политики: имя, на которое вы ссылаетесь из abuse_guard, и размер общей памяти. Около 10 МБ отслеживает порядка ста тысяч активных клиентов.

Все остальное — это опциональная настройка:

  • key — выражение, которое определяет одного клиента. Любая переменная NGINX; по умолчанию $binary_remote_addr ключует по исходному IP. Запрос, чей ключ оказывается пустым, полностью пропускается (удобно с map, ниже).
  • statuses — коды ответов, которые считаются ошибками: отдельные коды, диапазоны или их смесь, например, statuses=401,403,404,500-599. По умолчанию 403,404.
  • interval — окно, в течение которого счет уменьшается (по умолчанию 300s). Всплеск внутри него приводит к блокировке; медленный поток, распределенный шире, никогда не накапливается.
  • threshold — сколько ошибок в этом окне пересекает линию, до 1024 (по умолчанию 100).
  • block — как долго заблокированный клиент остается вне доступа (по умолчанию 60m).
  • inactive — как долго бездействующий клиент остается в памяти, прежде чем его заберут (по умолчанию max(1h, interval, block); любое явное значение должно быть как минимум таким же большим, как interval и block).
  • redison, чтобы реплицировать блокировки этой зоны по флоту (см. ниже); по умолчанию off.
  • persist — путь к файлу, в который будут сохраняться блокировки, чтобы они пережили перезапуск.
  • persist_interval — как часто этот снимок переписывается (по умолчанию 5s).
  • persist_secret — шестнадцатеричный ключ, который подписывает снимок с помощью HMAC-SHA256, так что поддельный файл отклоняется, а не загружается.

Почему 5xx по умолчанию не включен: ошибка сервера обычно является вашей ошибкой, и ее учет позволит одному ненадежному бэкенду заблокировать невиновных посетителей. Добавьте statuses=403,404,500-599 только тогда, когда вы намеренно хотите действовать на клиентов, которые вызывают серверные ошибки.

Примените ее — abuse_guard

*Действительно в блоках http, server и location, так что вы можете защитить целый сайт или только конечные точки, которые привлекают злоупотребления. Укажите зону, чтобы включить ее; напишите abuse_guard off; в вложенной области, чтобы отключить ее.

location /wp-login.php {
    abuse_guard zone=clients status=429 log_level=warn;
}
  • zone — зона (объявленная выше), политика которой применяется здесь.
  • status — код, который получает заблокированный клиент, где угодно в диапазоне 400599 (по умолчанию 429).
  • dry_runon, чтобы наблюдать без принуждения: вердикт записывается, но никакая блокировка не записывается. По умолчанию отключено.
  • log_level — насколько громко записывать каждое решение: info, notice (по умолчанию), warn или error.

Разворачивайтесь без страха с dry_run=on. Он записывает каждую блокировку, которую он бы выдал, не затрагивая состояние, так что вы можете откалибровать пороги по отношению к живому трафику — даже рядом с местом, где применяется политика, в той же зоне — а затем включить это в живом режиме.

Освободите хороших парней — abuse_guard_allow

Контекст: http · server · location · повторяемая, унаследованная вниз.

abuse_guard_allow 127.0.0.0/8;
abuse_guard_allow 10.0.0.0/8 192.168.0.0/16;

Перечисленные клиенты никогда не учитываются и никогда не блокируются. Сопоставление происходит по истинному адресу подключения, поэтому это работает с realip. Это также способ защитить проверенные поисковые краулеры: разрешите опубликованные диапазоны Googlebot / Bingbot, чтобы бот, прокладывающий путь через устаревшие URL (и накапливающий 404), никогда не был пойман.

Делитесь блокировками по всему флоту — abuse_guard_redis

Контекст: http

abuse_guard_redis host=10.0.0.5 password=… ;   # tls://host для TLS
abuse_guard_zone  zone=clients:10m redis=on;

Укажите каждый узел на один Redis или Valkey, переключите redis=on, и блокировка, полученная на любом узле, распространяется на все. Значения по умолчанию: port=6379, db=0, prefix=ag_, timeout=100ms. Как это остается быстрым, будет в следующем разделе.

SELinux: на системах с принудительным режимом (RHEL, Rocky, AlmaLinux) ядро останавливает NGINX от открытия соединения с Redis, пока вы не разрешите это один раз — setsebool -P httpd_can_network_connect 1. Пропустите это, и репликация молча ничего не делает, в то время как локальное принуждение продолжается как обычно.

Одна блокировка, каждый узел — без замедления единственного запроса

За балансировщиком нагрузки блокировка на уровне сервера — это театр: злоумышленник просто попадает на другой узел. Abuse Guard закрывает этот разрыв без того, чтобы когда-либо ставить Redis на путь запроса.

Каждый узел принимает решение локально и считает локально. В тот момент, когда он выдает блокировку, он рассылает этот один факт кластеру и записывает долговечную копию. Каждый другой узел импортирует ее в течение миллисекунд, и любой узел, который был отключен, согласует данные в момент повторного подключения. Поскольку принуждение всегда обслуживается из собственного состояния в памяти каждого узла, запрос посетителя никогда не ждет сетевого раунда — единственная цена кластеризации в том, что только что заблокированный злоумышленник выключается по всему флоту на пульсацию позже, а не мгновенно.

Redis здесь — это односторонний сигнал тревоги, а не общий реестр, который запрашивается за каждый запрос — так что медленный или отсутствующий Redis никогда не может добавить задержку к вашему трафику. Запускайте его в частной сети и рассматривайте как привилегированный: все, что может записать в него, может выдавать блокировки.

Блокировки, которые переживают перезапуск

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

abuse_guard_zone zone=clients:10m
                 persist=/var/lib/nginx/abuse_guard/clients.state
                 persist_secret=00112233445566778899aabbccddeeff;

Снимок проверяется на целостность, записывается так, чтобы сбой никогда не оставлял поврежденный файл, и — с persist_secret — криптографически подписывается, так что поддельный файл отклоняется, а не доверяется. Сохраняйте директорию доступной только для рабочего пользователя.

Смотрите все, что он решает

Три переменные открывают вердикт Abuse Guard для ваших журналов и конфигурации:

Переменная Значение
$abuse_guard_status BYPASSED · PASSED · COUNTED · BLOCKED · DRY_RUN
$abuse_guard_count Ошибки, в настоящее время приписанные этому клиенту.
$abuse_guard_blocked_until Время Unix, когда блокировка снимается, или 0.
log_format guard '$remote_addr "$request" $status '
                 'guard=$abuse_guard_status count=$abuse_guard_count';

Ключевание за CDN или прокси? Никогда не доверяйте сырому X-Forwarded-For. Позвольте realip сначала определить реального клиента, а затем ключевать по $binary_remote_addr:

set_real_ip_from 10.0.0.0/8;
real_ip_header   X-Forwarded-For;
real_ip_recursive on;

Нужна логика освобождения на уровне запроса? Любой запрос, чей key разрешается в пустую строку, игнорируется — так что map позволяет вам, например, отслеживать анонимных посетителей по IP, оставляя аутентифицированных пользователей нетронутыми.

Спроектировано для доверия в производстве

Abuse Guard соответствует стандарту, который значительно выше "он компилируется." Каждое изменение проходит через проверки AddressSanitizer, UndefinedBehaviorSanitizer, Valgrind, статический анализ и непрерывное фуззирование его парсеров и формата на диске. Его опциональные зависимости — кластеризация и подписанные снимки — по сути являются наилучшей попыткой: если Redis или диск ведут себя неправильно, принуждение тихо продолжается из локальной памяти. Ваш трафик никогда не будет удерживаться в заложниках из-за зависимости.

Получите Abuse Guard

Abuse Guard — это коммерческий модуль NGINX от GetPageSpeed LLC, предоставляемый с постоянными обновлениями и поддержкой через подписку GetPageSpeed.

© GetPageSpeed LLC. Все права защищены.