Fail2ban: свой фильтр для сканеров nginx и проверка fail2ban-regex

0
8
Обложка статьи: Fail2ban: свой фильтр для сканеров nginx и проверка fail2ban-regex

Готовые фильтры Fail2ban закрывают типовые случаи, но сканеры чаще всего стучатся в одни и те же служебные пути: /.env, /.git/config, wp-config.php.bak, xmlrpc.php. Свой фильтр по журналу доступа nginx блокирует их после нескольких попыток. Главная сложность — не написать выражение, а убедиться, что оно срабатывает на плохом и молчит на нормальном трафике. Ниже фильтр, проверка на примерах до включения и порядок запуска.

Статья опирается на логику направления «Сетевая безопасность» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Проверка выполнена на Fail2ban 1.0.2 (Debian 12) командами fail2ban-regex и fail2ban-client -t с копией каталога настроек: работающая служба и её конфигурация не затрагивались. Установка и общие настройки: CrowdSec и Fail2ban.

Что должно получиться

Уровень Что это значит на практике
2. Гигиенический Публичные сервисы защищены от типовых атак, журналы ведутся и по ним действуют автоматические реакции

Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.

Фильтр

Файл /etc/fail2ban/filter.d/nginx-scan.conf. Он ищет в журнале запросы к «подозрительным» путям, закончившиеся отказом (коды 400, 403, 404, 405, 444).

# /etc/fail2ban/filter.d/nginx-scan.conf
# Сканеры уязвимостей: обращения к служебным файлам и типовым целям, закончившиеся отказом.
# Формат журнала nginx по умолчанию (combined): АДРЕС - - [время] "МЕТОД ПУТЬ HTTP/x" КОД РАЗМЕР "referer" "agent"
# Fail2ban вырезает время из строки перед сопоставлением, поэтому на месте [время] в выражении стоят пустые скобки \[\]
[Definition]
failregex = ^<HOST> - \S+ \[\] "(?:GET|POST|HEAD|PUT) /(?:\.env|\.git/|\.aws/|wp-config\.php(?:\.\w+)?|phpmyadmin|pma/|xmlrpc\.php|cgi-bin/|vendor/phpunit)[^"]*" (?:400|403|404|405|444) 
ignoreregex =

Ловушка: время вырезается из строки

Fail2ban находит в строке дату и убирает её до сопоставления с выражением. Поэтому на месте [12/Oct/2026:16:51:34 +0000] в выражении должны стоять пустые скобки \[\]. Первый вариант фильтра с \[[^\]]+\] не нашёл ни одной строки: 8 строк обработано, 0 совпадений, 8 пропусков. Если ваш фильтр «не работает», сначала проверьте именно это.

Проверка до включения

Образец журнала (8 строк: три запроса сканера с одного адреса, один с другого, обычный посетитель, страница 404 у посетителя, параметр .env в обычном запросе, прямое обращение к /.env с ответом 200):

203.0.113.5 - - [12/Oct/2026:16:51:34 +0000] "GET /.env HTTP/1.1" 403 146 "-" "Wget" "-"
203.0.113.5 - - [12/Oct/2026:16:51:35 +0000] "GET /.git/config HTTP/1.1" 404 146 "-" "curl/8" "-"
203.0.113.5 - - [12/Oct/2026:16:51:36 +0000] "POST /xmlrpc.php HTTP/1.1" 404 146 "-" "python-requests/2.31" "-"
198.51.100.9 - - [12/Oct/2026:16:52:01 +0000] "GET /wp-config.php.bak HTTP/1.1" 404 146 "-" "-" "-"
192.0.2.44 - - [12/Oct/2026:16:52:10 +0000] "GET / HTTP/1.1" 200 5120 "-" "Mozilla/5.0" "-"
192.0.2.44 - - [12/Oct/2026:16:52:11 +0000] "GET /blog/missing-page HTTP/1.1" 404 146 "-" "Mozilla/5.0" "-"
192.0.2.45 - - [12/Oct/2026:16:52:12 +0000] "GET /index.php?x=.env HTTP/1.1" 200 5120 "-" "Mozilla/5.0" "-"
192.0.2.46 - - [12/Oct/2026:16:52:13 +0000] "GET /.env HTTP/1.1" 200 20 "-" "Mozilla/5.0" "-"

Команда проверки на копии каталога настроек (рабочая конфигурация не затрагивается):

cp -a /etc/fail2ban /tmp/f2b
cp nginx-scan.conf /tmp/f2b/filter.d/nginx-scan.conf
fail2ban-regex -c /tmp/f2b access_sample.log nginx-scan --print-all-matched

Результат: Failregex: 4 total, Lines: 8 lines, 0 ignored, 4 matched, 4 missed. Совпали четыре запроса сканеров: три с адреса 203.0.113.5 (/.env с ответом 403, /.git/config и /xmlrpc.php с 404) и один с 198.51.100.9 (wp-config.php.bak). Не совпали: обычная главная страница, посетитель, наткнувшийся на несуществующую страницу блога, запрос с .env внутри параметра, и /.env с кодом 200.

Последняя строка важна по существу: ответ 200 на /.env означает, что файл с секретами отдаётся. Фильтр такие случаи не банит (бан пришёл бы слишком поздно): их нужно ловить оповещением и немедленно закрывать доступ. Закрытие служебных файлов в nginx: безопасная настройка nginx.

Настройка jail

# /etc/fail2ban/jail.d/nginx-scan.local
[nginx-scan]
enabled  = true
port     = http,https
filter   = nginx-scan
# путь к журналу доступа nginx на вашем сервере (для контейнера: каталог, куда смонтирован журнал)
logpath  = /var/log/nginx/access.log
maxretry = 3
findtime = 10m
bantime  = 1h
  • maxretry = 3 и findtime = 10m: три попытки за десять минут; для порога подберите значения по своему трафику.
  • bantime = 1h: для начала час; для повторных нарушителей используйте увеличивающийся срок (механизм recidive).
  • logpath: если nginx работает в контейнере, укажите каталог на хосте, куда смонтирован журнал (проверьте, что файл существует).

Проверка настройки без перезапуска и без изменения работающей службы:

cp nginx-scan.local /tmp/f2b/jail.d/nginx-scan.local
fail2ban-client -c /tmp/f2b -t

Ожидаемый результат: OK: configuration test is successful. Если журнала по указанному пути нет, проверка выдаёт ошибку Have not found any log file for nginx-scan jail: исправьте logpath.

Включение

  1. Разместите файлы в /etc/fail2ban/filter.d/ и /etc/fail2ban/jail.d/.
  2. Выполните sudo fail2ban-client -t, затем sudo systemctl reload fail2ban (или fail2ban-client reload).
  3. Убедитесь, что jail активен: sudo fail2ban-client status nginx-scan.
  4. Проверьте работу реальным запросом со своего тестового адреса в списке игнорируемых до включения бана, затем с другого адреса (мобильный интернет): три запроса к /.env должны привести к бану этого адреса; снимите бан командой sudo fail2ban-client set nginx-scan unbanip АДРЕС.
  5. Добавьте адреса администраторов в ignoreip, чтобы не заблокировать себя.

Защита от ложных срабатываний

  • Не включайте в фильтр пути, которые реально используют ваши приложения (xmlrpc.php нужен части WordPress-интеграций: уберите его из выражения, если пользуетесь).
  • Ограничивайте коды ответов: бан по 404 для обычных страниц блога недопустим; список путей должен быть узким.
  • Перед включением прогоните фильтр по реальному журналу за неделю: fail2ban-regex -c /tmp/f2b /var/log/nginx/access.log nginx-scan. Просмотрите адреса в результатах: среди них не должно быть ваших пользователей и сервисов мониторинга.
  • Если перед nginx стоит прокси или CDN, в журнале будет адрес прокси: настройте передачу настоящего адреса клиента, иначе забанится прокси.
  • Связывайте блокировки с общей картиной: события бана видны в журналах и в правилах Wazuh.

Диагностика

Симптом Причина и что делать
0 совпадений на строках, которые должны подходить Время вырезано из строки: в выражении используйте \[\]. Проверьте формат журнала nginx (нестандартный log_format требует другого выражения)
Совпадают обычные посетители Слишком широкий шаблон пути или код. Сузьте выражение и повторите проверку на журнале
Have not found any log file Неверный logpath или журнал не доступен хосту. Укажите существующий путь
Бан не срабатывает на реальных сканерах Адрес в журнале не тот (прокси) или jail не активен. Проверьте fail2ban-client status и содержимое журнала
Заблокировали сами себя Нет адреса в ignoreip. Снимите бан и добавьте адреса администраторов

Где это в модели зрелости

Материал относится к направлению «Сетевая безопасность» (материалы направления, карта зрелости). Автоматическая реакция на типовые атаки на публичные сервисы входит в требования к уровню 2; проверка фильтров на примерах делает эти реакции предсказуемыми.

Как проверить

  1. На образце журнала fail2ban-regex находит строки сканеров и не находит нормальный трафик.
  2. Фильтр прогнан по реальному журналу за неделю, ложных адресов нет.
  3. fail2ban-client -t проходит, jail активен, тестовый запрос с постороннего адреса приводит к бану, снятие бана выполнено на тесте.
  4. Адреса администраторов в ignoreip, ответы 200 на служебные файлы отслеживаются отдельным оповещением.

Источники

  • Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
  • Документация Fail2ban: fail2ban.readthedocs.io; руководства man fail2ban-regex, man jail.conf.
  • OWASP Top 10 (классы атак, на которые ориентированы сканеры): owasp.org. Международная практика, не российский норматив.

Комментарии закрыты.