abuse-guard: Автоматическая блокировка злоумышленных клиентов по частоте ошибочных ответов
Установка
Вы можете установить этот модуль в любом дистрибутиве на основе 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 v2.1.0, выпущенный 03 сентября 2026 года.
Ваш журнал ошибок — это признание. Abuse Guard читает его в реальном времени и блокирует злоумышленников.
Каждый сканер, фаззер и бот для подбора учетных данных оставляет один и тот же след:
шквал 404 в поисках скрытых путей, 403 от запертых дверей, бесконечная череда
неудачных запросов. Abuse Guard отслеживает коды состояния, которые ваш сервер
фактически возвращает, определяет клиентов, чей трафик состоит в основном из ошибок, и
блокирует их — решение принимается внутри рабочего процесса NGINX, непосредственно для запроса, за несколько
микросекунд. Никаких сайдкаров. Никаких сборщиков логов. Никакого скриптового слоя. Просто скомпилированный C,
выполняющий одну задачу исключительно хорошо.
Технические характеристики
| Триггер | Частота ошибочных ответов на клиента, которую вы выбираете (по умолчанию 403/404) |
| Действие | Блокировка на время — жесткий бан на фиксированный период, а не ограничение скорости |
| Точка принятия решения | Фаза preaccess в NGINX, до выполнения любого обработчика или обращения к апстриму |
| Модель памяти | Фиксированное количество байт на клиента, не зависящее от порога → масштаб ботнета |
| Режим кластера | Опциональная репликация банов между узлами через Redis / Valkey |
| Устойчивость | Опциональные снапшоты при выходе сохраняют активные баны между перезапусками |
| Занимаемые ресурсы | Один автономный модуль; по умолчанию ноль зависимостей во время выполнения |
| Платформы | RHEL / AlmaLinux / Rocky / CentOS Stream / Oracle / Amazon Linux |
| ## |
Проблема, которую он устраняет
Легитимные посетители почти никогда не создают шквал ошибок. Злоумышленники создают
почти ничего, кроме них — эта асимметрия и есть вся суть. Сканер уязвимостей, обходящий
ваше дерево каталогов, — это стена 404. Бот, проверяющий админ-эндпоинты, — это стена 403.
Брутфорс — это стена неудач.
Ограничители скорости относятся к такому трафику как к любому другому: они замедляют всех по объему запросов и впускают нарушителя обратно в ту же секунду, как только он снижает интенсивность. Abuse Guard делает наоборот. Он полностью игнорирует корректный трафик и резервирует свой единственный ответ — реальный, ограниченный по времени бан — для клиентов, определяемых их ошибками.
Используйте ограничитель скорости для управления нагрузкой. Используйте Abuse Guard для изгнания злоупотреблений.
Как принимается решение о бане
Три движущиеся части, все внутри рабочего процесса:
1 · Протекающий счетчик, на каждого клиента. Каждая идентичность клиента несет одно небольшое
число в разделяемой памяти. Каждая подходящая ошибка добавляет одно очко по умолчанию или
вес, который вы назначаете этому статусу; счетчик непрерывно убывает со скоростью
порог ÷ интервал в секунду. Короткая, резкая вспышка переваливает за линию;
медленная капель — никогда. Важно, что этот счетчик — одна запись фиксированного размера, независимо
от того, насколько высоко вы установили порог, поэтому одна зона с комфортом отслеживает
десятки тысяч различных исходных адресов, которые ботнет обрушивает на вас.
2 · Жесткий дедлайн. В момент, когда счетчик пересекает ваш порог, клиент
получает временную метку blocked_until. До этого момента он просто исчезает — каждый запрос
отклоняется на фазе preaccess, до того как NGINX потратит цикл на маршрутизацию,
файлы или апстримы. Отказ — это самый дешевый из возможных исходов.
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— ответы, которые добавляют к счетчику. Простой код или диапазон имеет вес 1, сохраняя исходный синтаксис:statuses=403,404,500-599. Добавьте:вес, чтобы ответ потреблял больше того же бюджета, напримерstatuses=404,401:5,500-599:2. Веса — целые числа от 1 до 1024, и диапазон применяет свой вес к каждому статусу, который он покрывает. Повторение или пересечение статуса с тем же весом безвредно; конфликтующие веса вызывают ошибкуnginx -t. По умолчанию остается403,404.interval— окно, в течение которого счетчик затухает (по умолчанию300s). Всплеск внутри него вызывает бан; медленная капель, растянутая шире, никогда не накапливается.threshold— сколько очков счетчика в этом окне пересекают линию, до 1024 (по умолчанию100). Тяжелый ответ может израсходовать оставшийся бюджет и вызвать бан немедленно.block— как долго сработавший клиент остается заблокированным (по умолчанию60m).inactive— как долго бездействующий клиент задерживается в памяти перед удалением (по умолчаниюmax(1h, interval, block); любое явное значение должно быть не меньше, чем обаintervalиblock).redis—onдля репликации банов этой зоны по кластеру (см. ниже); по умолчаниюoff.persist— путь к файлу, куда активные баны выгружаются при чистом выходе рабочего процесса и загружаются при запуске.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— код, который получает забаненный клиент, в диапазоне400–599(по умолчанию429).dry_run—onдля наблюдения без применения: вердикт записывается в журнал, но бан не выписывается. По умолчанию выключен.log_level— насколько подробно журналировать каждое решение:info,notice(по умолчанию),warnилиerror.
Развертывайте без страха с dry_run=on. Он записывает каждый бан, который выдал бы,
не затрагивая состояние, так что вы можете откалибровать пороги на живом трафике — даже
рядом с применяющим location в той же зоне — а затем переключить в боевой режим.
Освобождение хороших — 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 никогда не добавит задержку вашему трафику. Запускайте его в частной сети и относитесь к нему как к привилегированному: любой, кто может писать в него, может выдавать баны.
Баны, переживающие перезапуск
Укажите зоне путь к файлу, и активные баны будут выгружены при чистом выходе рабочего процесса, а затем восстановлены при запуске. Перезагрузки и штатные перезапуски сохраняют текущие баны без запуска периодического писателя всей зоны. Внезапный сбой процесса или машины может потерять баны, выданные с момента последнего чистого выхода; применение по-прежнему работает в режиме fail-open.
abuse_guard_zone zone=clients:10m
persist=/var/lib/nginx/abuse_guard/clients.state
persist_secret=00112233445566778899aabbccddeeff;
Компактный снапшот содержит только дайджесты идентичностей и сроки банов. CRC32
обнаруживает повреждения, а атомарное переименование не позволяет частичным записям попасть в
рабочий путь. Сборки с поддержкой подписанных снапшотов могут дополнительно аутентифицировать его с помощью
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, статический анализ и непрерывный фаззинг его парсеров и формата на диске. Его опциональные зависимости — кластеризация и подписанные снапшоты — по замыслу работают по принципу best-effort: если Redis или диск ведут себя некорректно, применение тихо продолжается из локальной памяти. Ваш трафик никогда не находится в заложниках у зависимости.
Получите Abuse Guard
Abuse Guard — это коммерческий модуль NGINX от GetPageSpeed LLC, поставляемый с постоянными обновлениями и поддержкой через подписку GetPageSpeed.
- Просмотрите полный каталог модулей NGINX → https://nginx-extras.getpagespeed.com/modules/
- Лицензирование, массовые развертывания или помощь в настройке → getpagespeed.com/contact-us
© GetPageSpeed LLC. Все права защищены.