Коротко: fail2ban читает access-лог nginx и банит IP-адреса, которые ведут себя как боты: перебирают служебные пути (wp-login.php, .env), приходят с User-Agent скриптов или без него. Ниже готовые фильтры, jail и настройки nginx, которые мы проверили на тестовом логе командой fail2ban-regex и конфигом через nginx -t.
Если по разбору access-лога вы нашли ботов, следующий вопрос: как перестать пускать их автоматически. Самый доступный способ на своём сервере это fail2ban: он следит за логом и временно блокирует адреса по правилам. Он не заменяет полноценную защиту, но снимает основную массу простых сканеров.
Как это работает и чего ждать
- fail2ban читает лог уже после того, как запрос обработан. Он не блокирует первый запрос, а банит адрес после нескольких срабатываний (параметр
maxretry) за период (findtime). - Бан ставится на уровне файрвола сервера (iptables или nftables) на заданное время (
bantime). - Правила описываются регулярными выражениями в файлах фильтров. Ошибка в выражении может забанить своих посетителей, поэтому каждое правило проверяйте командой
fail2ban-regexдо включения.
Фильтр 1: сканеры и служебные пути
Файл /etc/fail2ban/filter.d/nginx-bots.conf. Реагирует на запросы к служебным адресам, которые закончились ошибкой или отказом:
[Definition]
failregex = ^<HOST> .* "(GET|POST|HEAD) [^"]*(wp-login\.php|xmlrpc\.php|\.env|phpmyadmin|\.git/|wp-admin/setup-config\.php)[^"]*" (400|403|404|405|444)
ignoreregex =
Статус ответа в правиле важен: обычная страница входа WordPress отвечает 200 и под правило не попадёт, а сканер, который ищет несуществующий /.env, получает 404 и попадёт. Если на вашем сайте нет WordPress, любые обращения к wp-login.php это разведка.
Фильтр 2: скриптовые User-Agent и пустая строка
Файл /etc/fail2ban/filter.d/nginx-badua.conf:
[Definition]
failregex = ^<HOST> .* ".*" \d{3} \S+ ".*" "(python-requests|curl|Go-http-client|Scrapy|-)[^"]*"$
ignoreregex =
Правило ловит запросы, у которых User-Agent начинается с названия скриптового клиента или состоит из прочерка (пустая строка в логе). Осторожно: этими же клиентами могут пользоваться ваши собственные сервисы мониторинга и интеграции. Добавьте их адреса в белый список (ниже) и не делайте этот фильтр жёстким в первые дни.
Jail: что и как банить
Файл /etc/fail2ban/jail.local:
[nginx-bots]
enabled = true
port = http,https
filter = nginx-bots
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 ::1 ВАШ_IP
[nginx-badua]
enabled = true
port = http,https
filter = nginx-badua
logpath = /var/log/nginx/access.log
maxretry = 20
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 ::1 ВАШ_IP
Для сканеров достаточно 3 срабатываний за 10 минут. Для скриптовых User-Agent порог выше (20), чтобы не зацепить единичные запросы. Подставьте в ignoreip свой адрес и адреса мониторинга. Включите fail2ban командой systemctl restart fail2ban и смотрите состояние: fail2ban-client status nginx-bots.
Сначала проверьте, потом включайте
Перед запуском прогоните фильтр по реальному логу, чтобы увидеть, кого он забанит:
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-bots.conf
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-badua.conf
В выводе нужна строка Lines: ... matched. Посмотрите примеры совпавших строк: в них не должно быть ваших пользователей и поисковых ботов. Мы проверили оба фильтра на тестовом логе из девяти строк: фильтр сканеров совпал с четырьмя запросами сканеров (wp-login.php, .env, xmlrpc.php, phpmyadmin с ответом 4xx), а фильтр User-Agent с пятью запросами скриптов (python-requests, curl, Go-http-client, пустой User-Agent). Обычный браузер на странице входа (ответ 200) и Googlebot не совпали.
Что добавить на стороне nginx
fail2ban реагирует с задержкой, поэтому часть правил лучше выполнять в самом nginx. Проверенный конфиг (пример для nginx.conf, адреса и пути замените своими):
http {
# скриптовые User-Agent и пустая строка
map $http_user_agent $bad_ua {
default 0;
"" 1;
~*(python-requests|scrapy|go-http-client|libwww-perl|java/) 1;
}
# ограничение частоты запросов на IP
limit_req_zone $binary_remote_addr zone=perip:10m rate=5r/s;
server {
# служебные пути, которых на сайте нет
location ~* (wp-login\.php|xmlrpc\.php|/\.env|/\.git/|phpmyadmin) {
return 444;
}
location / {
if ($bad_ua) { return 403; }
limit_req zone=perip burst=20 nodelay;
# ... ваши настройки сайта ...
}
}
}
Код 444 это особый ответ nginx: он закрывает соединение без ответа, что отнимает у сканера время. Ограничение limit_req подбирайте под нагрузку: пять запросов в секунду с одного адреса достаточно для обычных посетителей, но может не хватить для интенсивного API.
Типичные ловушки
- Сайт за CDN или обратным прокси. Если в логе адрес прокси, а не посетителя, fail2ban забанит прокси и «положит» весь сайт. Сначала настройте передачу реального IP (модуль
realipи заголовок от CDN) и убедитесь, что в логе настоящие адреса. - Общие адреса (NAT, офис, мобильный оператор). Бан по IP зацепит всех, кто сидит за этим адресом. Поэтому начинайте с короткого
bantimeи порогов повыше. - Поисковые боты. Не банить «по User-Agent вслепую»: подлинность Googlebot и Яндекса проверяется по IP, см. как проверить, настоящий ли это Googlebot.
- Боты за жилыми прокси. Каждый запрос идёт с нового адреса, поэтому бан по IP их не остановит.
Когда fail2ban недостаточно
fail2ban хорош для простых сканеров и перебора. Он не видит поведение, заголовки браузера, подлинность поисковых ботов, ротацию адресов и рекламный трафик. Для постоянной защиты нужен сервис, который проверяет каждый запрос на лету: Bot Guard делает это по User-Agent, IP, заголовкам и поведению, а подключается к WordPress плагином и к 1С-Битриксу модулем. Общие принципы ограничения частоты описаны в статье про rate limiting, а разобрать свой лог можно в бесплатном анализаторе.
Частые вопросы
Что такое fail2ban и для чего он нужен на сервере с nginx?
Это программа, которая читает журналы сервера и временно блокирует IP-адреса, ведущие себя как атакующие: перебирают пароли, ищут уязвимые страницы, шлют слишком много запросов. Для nginx ей нужен фильтр (регулярное выражение для строки лога) и jail (настройки: сколько срабатываний, на какое время банить).
Как проверить фильтр fail2ban, не рискуя забанить своих?
Запустите fail2ban-regex ЛОГ ФИЛЬТР: команда покажет, сколько строк лога совпало, и ничего не заблокирует. Добавьте свои адреса в ignoreip и начните с короткого времени бана.
Почему fail2ban не банит ботов сразу?
Он читает лог после запроса и банит адрес только после нескольких срабатываний за заданный период. Для мгновенных ответов используйте правила nginx: return 444 для служебных путей и limit_req для ограничения частоты.
Можно ли банить по User-Agent?
Можно, но только для явных скриптов и пустой строки, и с белым списком своих сервисов. Поисковых ботов по User-Agent банить нельзя: сначала проверяйте IP.
fail2ban заменяет защиту от ботов?
Нет. Он справляется с простыми сканерами. Боты за прокси, имитация браузера, поддельные поисковые боты и накрутка рекламы требуют проверки каждого запроса по нескольким признакам.
Защитите свой сайт от ботов прямо сейчас
Подключение занимает несколько минут — вставьте один PHP-сниппет, и Bot Guard начнёт фильтровать ботов, скрейперов и попытки SQL-инъекций автоматически.