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).redis—on, чтобы реплицировать блокировки этой зоны по флоту (см. ниже); по умолчанию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— код, который получает заблокированный клиент, где угодно в диапазоне400–599(по умолчанию429).dry_run—on, чтобы наблюдать без принуждения: вердикт записывается, но никакая блокировка не записывается. По умолчанию отключено.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.
- Просмотрите полный каталог модулей NGINX → https://nginx-extras.getpagespeed.com/modules/
- Лицензирование, массовые развертывания или помощь в настройке → getpagespeed.com/contact-us
© GetPageSpeed LLC. Все права защищены.