Установка и настройка Fail2Ban на Linux VPS

11 мин чтения·Matthieu·ubuntudebianufwnftablesnginxsshsecurityfail2ban|

Настройте Fail2Ban для блокировки brute-force атак на SSH и Nginx. Рассмотрены действия бана через UFW и nftables, пользовательские jail, эскалация recidive и тестирование фильтров на Ubuntu 24.04 и Debian 12.

Fail2Ban отслеживает лог-файлы на предмет повторных ошибок аутентификации и блокирует IP-адреса нарушителей через файрвол. Он останавливает brute-force атаки до того, как они увенчаются успехом. Свежеразвёрнутый VPS обычно получает попытки SSH-входа в течение нескольких минут после запуска. Fail2Ban — стандартная защита.

Это руководство охватывает установку на Ubuntu 24.04 и Debian 12, настройку jail для SSH и Nginx, оба бэкенда действий бана (UFW и nftables), jail recidive для рецидивистов и тестирование фильтров с помощью fail2ban-regex. Каждое изменение конфигурации сопровождается шагом проверки.

Необходимые условия: VPS с Ubuntu 24.04 или Debian 12, доступ root или sudo. Файрвол должен быть уже активен, SSH должен быть уже настроен. Это руководство — часть серии безопасность Linux VPS.

Как установить Fail2Ban на Ubuntu 24.04 и Debian 12?

Установите Fail2Ban через apt. Пакет есть в стандартных репозиториях обоих дистрибутивов. Ubuntu 24.04 поставляет версию 1.0.2, Debian 12 тоже. На Debian 12 дополнительно нужен python3-systemd, чтобы Fail2Ban мог читать journal systemd.

sudo apt update && sudo apt install -y fail2ban

На Debian 12 установите Python-привязки для systemd:

sudo apt install -y python3-systemd

Включите и запустите сервис:

sudo systemctl enable --now fail2ban

Флаг enable настраивает автозапуск Fail2Ban при загрузке. Флаг --now запускает его немедленно. Проверьте, что он работает:

sudo systemctl status fail2ban

В выводе должно быть Active: active (running). Если статус показывает failed, смотрите journal:

journalctl -u fail2ban -n 20 --no-pager

В чём разница между jail.conf, jail.local и jail.d/?

jail.conf — конфигурационный файл по умолчанию, поставляемый с пакетом. Обновления пакета перезаписывают его. Никогда не редактируйте jail.conf напрямую. Ваши изменения пропадут при следующем apt upgrade.

jail.local — традиционный файл переопределений. Fail2Ban сначала читает jail.conf, затем накладывает настройки из jail.local. Это работает, но файл разрастается в монолит, который сложно поддерживать.

Каталог jail.d/ — лучший подход. Размещайте один .conf-файл на каждый jail. Fail2Ban загружает их в алфавитном порядке после jail.conf и jail.local. Каждый сервис изолирован, и добавлять или удалять jail можно не трогая остальные конфигурации.

В этом руководстве используются drop-in файлы в jail.d/. Проверьте, что каталог существует:

ls /etc/fail2ban/jail.d/

Он уже должен быть на месте. Если видите файлы вроде defaults-debian.conf — это нормально. На Ubuntu 24.04 этот файл включает jail sshd и задаёт banaction = nftables как действие бана по умолчанию. На Debian 12 он включает jail sshd. Поскольку Fail2Ban загружает файлы из jail.d/ в алфавитном порядке, любой пользовательский файл настроек должен сортироваться после defaults-debian.conf, чтобы переопределить его параметры. Поэтому в руководстве используется zz-defaults.conf.

Как настроить SSH jail в Fail2Ban?

SSH jail отслеживает логи аутентификации и банит IP, которые слишком часто ошибаются при входе. На Ubuntu 24.04 и Debian 12 jail sshd включён по умолчанию через /etc/fail2ban/jail.d/defaults-debian.conf. Но значения по умолчанию мягкие (5 попыток, бан на 10 минут). Ужесточите их.

Создайте drop-in конфигурацию:

sudo tee /etc/fail2ban/jail.d/sshd.conf > /dev/null << 'EOF'
[sshd]
enabled = true
mode = aggressive
port = ssh
backend = systemd
maxretry = 3
findtime = 600
bantime = 3600
EOF

Что означает каждый параметр:

Параметр Значение Описание
enabled true Активирует этот jail
mode aggressive Ловит больше паттернов SSH-ошибок, включая ошибки аутентификации по ключу
port ssh Мониторит порт SSH (резолвится в 22 или ваш кастомный порт)
backend systemd Читает из journal systemd, а не из лог-файлов
maxretry 3 Бан после 3 неудачных попыток
findtime 600 Считает ошибки в окне 10 минут
bantime 3600 Бан на 1 час (3600 секунд)

Если вы сменили порт SSH (и правильно сделали), замените ssh на номер порта:

port = 2222

Перезапустите Fail2Ban для применения:

sudo systemctl restart fail2ban

Проверьте, что jail активен:

sudo fail2ban-client status sshd

Ожидаемый вывод:

Status for the jail: sshd
|- Filter
|  |- Currently failed:	0
|  |- Total failed:	0
|  `- Journal matches:	_SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned:	0
   |- Total banned:	0
   `- Banned IP list:

строка Journal matches подтверждает, что Fail2Ban читает из journal systemd, а не из файла. Для Ubuntu 24.04 и Debian 12 это правильно.

Как настроить Fail2Ban с UFW в качестве действия бана?

Если вы используете UFW как файрвол, настройте Fail2Ban на вставку правил бана через UFW. Это более простой путь, подходящий для большинства конфигураций.

Создайте файл настроек по умолчанию, задающий UFW как действие бана. Имя zz-defaults.conf выбрано намеренно: на Ubuntu 24.04 пакет поставляет defaults-debian.conf, который задаёт banaction = nftables. Ваш файл должен сортироваться по алфавиту после него, чтобы переопределить это значение.

sudo tee /etc/fail2ban/jail.d/zz-defaults.conf > /dev/null << 'EOF'
[DEFAULT]
banaction = ufw
banaction_allports = ufw
backend = systemd
EOF

Перезапустите и проверьте:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Когда Fail2Ban банит IP, он выполняет ufw insert 1 deny from <IP> to any. Проверьте правила UFW после бана:

sudo ufw status numbered

Вы увидите deny-правила Fail2Ban вверху списка.

Как настроить Fail2Ban на использование nftables вместо iptables?

Для продакшн-серверов, использующих nftables напрямую (без UFW), используйте действие бана nftables-multiport. Fail2Ban создаёт собственную таблицу nftables и управляет правилами бана в ней, не вмешиваясь в ваш существующий набор правил.

Создайте файл настроек по умолчанию. На Ubuntu 24.04 defaults-debian.conf уже задаёт banaction = nftables, так что этот шаг технически необязателен. Но явно указывать — хорошая практика. На Debian 12 этот файл обязателен.

sudo tee /etc/fail2ban/jail.d/zz-defaults.conf > /dev/null << 'EOF'
[DEFAULT]
banaction = nftables-multiport
banaction_allports = nftables[type=allports]
chain = input
backend = systemd
EOF

Перезапустите и проверьте:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Для подтверждения интеграции с nftables выведите список таблиц Fail2Ban:

sudo nft list tables

Должна быть таблица с именем inet f2b-table. После бана можно посмотреть её содержимое:

sudo nft list table inet f2b-table

Сравнение действий бана UFW и nftables

Аспект UFW (banaction = ufw) nftables (banaction = nftables-multiport)
Команда бана ufw insert 1 deny from <IP> Добавляет IP в nftables set
Где видны правила ufw status numbered nft list table inet f2b-table
Поддержка IPv6 Да (UFW управляет) Да (семейство inet)
Персистентность Правила UFW сохраняются при перезагрузке Fail2Ban применяет заново при старте
Производительность Линейный перебор правил Поиск по множеству (быстрее при большом числе записей)
Подходит для Простые настройки, один сервис Продакшн, много jail, большое число банов

Выберите один подход. Не смешивайте действия бана UFW и nftables на одном сервере.

Как добавить свой IP-адрес в белый список Fail2Ban?

Добавьте свой IP в ignoreip, чтобы не забанить самого себя. Это важно. Если вы трижды ошибётесь с паролем, Fail2Ban забанит ваш собственный IP. Вы потеряете доступ по SSH.

Добавьте свой IP в настройки по умолчанию:

sudo tee /etc/fail2ban/jail.d/01-whitelist.conf > /dev/null << 'EOF'
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 YOUR_IP_HERE
EOF

Замените YOUR_IP_HERE на ваш реальный публичный IP. Узнать его можно командой curl -4 ifconfig.me на локальной машине. Несколько IP указываются через пробел.

Перезапустите и проверьте, что белый список загружен:

sudo systemctl restart fail2ban
sudo fail2ban-client get sshd ignoreip

В выводе перечислены все IP и диапазоны из белого списка. Убедитесь, что ваш IP в списке.

Внимание: если вы подключаетесь с динамического IP, добавление его в белый список даёт ограниченную защиту. Держите под рукой альтернативный способ доступа (консоль через панель хостинг-провайдера) на случай бана.

Как защитить Nginx с помощью пользовательских jail Fail2Ban?

Fail2Ban поставляется с несколькими фильтрами для Nginx. Самые полезные — nginx-http-auth для brute-force на HTTP Basic аутентификации и nginx-botsearch для сканеров, прощупывающих несуществующие пути. Можно также писать собственные фильтры под специфику приложения.

Jail nginx-http-auth

Этот jail банит IP, которые многократно проваливают HTTP Basic аутентификацию. Он читает лог ошибок Nginx.

sudo tee /etc/fail2ban/jail.d/nginx-http-auth.conf > /dev/null << 'EOF'
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
findtime = 600
bantime = 3600
EOF

Jail nginx-botsearch

Этот jail ловит ботов, сканирующих уязвимые пути (/wp-admin, /phpmyadmin, /.env). Он читает лог доступа Nginx на предмет ответов 404.

sudo tee /etc/fail2ban/jail.d/nginx-botsearch.conf > /dev/null << 'EOF'
[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime = 7200
EOF

Пользовательский фильтр: бан за чрезмерные 4xx-ошибки

Для приложений за Nginx вы можете захотеть банить IP, генерирующие слишком много 4xx-ошибок. Это ловит credential stuffing, злоупотребление API и перебор путей. Встроенные фильтры это не покрывают, поэтому создайте собственный фильтр.

Создайте файл фильтра:

sudo tee /etc/fail2ban/filter.d/nginx-4xx.conf > /dev/null << 'EOF'
[Definition]
failregex = ^<HOST> - \S+ \[.*\] "[A-Z]+ .+" (400|401|403|404|405) \d+
ignoreregex = ^<HOST> - \S+ \[.*\] "[A-Z]+ /favicon\.ico
              ^<HOST> - \S+ \[.*\] "[A-Z]+ /robots\.txt
EOF

failregex совпадает со строками лога доступа Nginx, где ответ — код состояния 4xx. ignoreregex исключает типичные ложные срабатывания: запросы favicon.ico и robots.txt.

Создайте jail:

sudo tee /etc/fail2ban/jail.d/nginx-4xx.conf > /dev/null << 'EOF'
[nginx-4xx]
enabled = true
port = http,https
filter = nginx-4xx
logpath = /var/log/nginx/access.log
maxretry = 20
findtime = 600
bantime = 3600
EOF

Повышенный maxretry в 20 не даёт забанить легитимных пользователей, которые при обычном сёрфинге наткнулись на пару 404.

Перезапустите Fail2Ban и проверьте, что все jail загружены:

sudo systemctl restart fail2ban
sudo fail2ban-client status

Ожидаемый вывод со всеми активными jail:

Status
|- Number of jail:      4
`- Jail list:   nginx-4xx, nginx-botsearch, nginx-http-auth, sshd

Подробнее о защите Nginx на уровне приложения см. руководство по rate limiting и защите от DDoS в Nginx.

Как тестировать фильтры Fail2Ban с помощью fail2ban-regex?

Перед активацией jail протестируйте его фильтр на реальных логах. Утилита fail2ban-regex прогоняет фильтр по лог-файлу и сообщает о совпадениях. Это предотвращает выкатку фильтра, который ничего не ловит (бесполезен) или ловит всё подряд (банит легитимных пользователей).

Протестируйте пользовательский фильтр nginx-4xx:

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf

Пример вывода:

Running tests
=============

Use   failregex filter file : nginx-4xx, basedir: /etc/fail2ban
Use         log file : /var/log/nginx/access.log
Use         encoding : utf-8

Results
=======

Failregex: 42 total
|-  #) [# of hits] regular expression
|   1) [42] ^<HOST> - \S+ \[.*\] "[A-Z]+ .+" (400|401|403|404|405) \d+
`-

Ignoreregex: 3 total

Date template hits:
...

Lines: 1842 lines, 0 ignored, 42 matched, 1800 missed

вывод показывает 42 совпадения из 1842 строк. Это разумное соотношение. Если фильтр совпал с 90% строк — regex слишком широкий. Если с 0 строк — либо regex неправильный, либо в логе пока нет 4xx-ошибок.

Посмотреть совпавшие строки:

sudo fail2ban-regex --print-all-matched /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf

Посмотреть несовпавшие строки (полезно для тюнинга):

sudo fail2ban-regex --print-all-missed /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf

Протестировать встроенный фильтр sshd против journal systemd:

sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf

Как настроить jail recidive для рецидивистов?

Jail recidive следит за собственным логом Fail2Ban. Когда IP банится несколько раз в любом jail, recidive применяет более длительный бан. Это эскалация: первое нарушение — 1 час, рецидивисты — 1 неделя.

На нагруженном продакшн-сервере именно jail recidive реально держит упорных атакующих на расстоянии.

sudo tee /etc/fail2ban/jail.d/recidive.conf > /dev/null << 'EOF'
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
maxretry = 3
findtime = 86400
bantime = 604800
EOF
Параметр Значение Описание
logpath /var/log/fail2ban.log Резервный путь к логу. С backend = systemd Fail2Ban вместо этого читает свои записи из journal (фильтр recidive имеет встроенную директиву journalmatch)
maxretry 3 Срабатывает после 3 банов от других jail
findtime 86400 Смотрит на 24 часа назад (86400 секунд)
bantime 604800 Бан на 1 неделю (604800 секунд)
banaction %(banaction_allports)s Блокирует все порты, а не только тот, что вызвал бан

Фильтр recidive поставляется с Fail2Ban в /etc/fail2ban/filter.d/recidive.conf. Создавать его не нужно.

Перезапустите и проверьте:

sudo systemctl restart fail2ban
sudo fail2ban-client status recidive

Как мониторить баны и разбанить IP-адрес?

Fail2Ban предоставляет fail2ban-client для всех задач мониторинга и управления. Эти команды работают вне зависимости от бэкенда действий бана.

Проверить общий статус

sudo fail2ban-client status

Выводит все активные jail и их счётчики банов.

Проверить конкретный jail

sudo fail2ban-client status sshd

Показывает текущие забаненные IP, общее число банов и текущие ошибки.

Забанить IP вручную

sudo fail2ban-client set sshd banip 203.0.113.50

Разбанить IP

sudo fail2ban-client set sshd unbanip 203.0.113.50

Если IP был забанен jail recidive, разбаньте его и там:

sudo fail2ban-client set recidive unbanip 203.0.113.50

Проверить, какое действие бана использует jail

sudo fail2ban-client get sshd actions

Перезагрузить конфигурацию без перезапуска

sudo fail2ban-client reload

Читать лог Fail2Ban

journalctl -u fail2ban -f

Это отслеживает лог сервиса Fail2Ban в реальном времени. Вы увидите события бана и разбана по мере их возникновения.

Лог приложения Fail2Ban с деталями банов:

sudo tail -f /var/log/fail2ban.log

Справочник команд fail2ban-client

Команда Назначение
fail2ban-client status Вывести все jail
fail2ban-client status <jail> Показать детали jail и забаненные IP
fail2ban-client set <jail> banip <IP> Забанить IP вручную
fail2ban-client set <jail> unbanip <IP> Разбанить IP
fail2ban-client reload Перезагрузить всю конфигурацию
fail2ban-client reload <jail> Перезагрузить один jail
fail2ban-client get <jail> bantime Показать длительность бана
fail2ban-client get <jail> findtime Показать окно подсчёта ошибок
fail2ban-client get <jail> maxretry Показать порог попыток
fail2ban-client get <jail> ignoreip Показать IP в белом списке
fail2ban-client get <jail> actions Показать используемое действие бана

Сквозная проверка: спровоцировать бан и убедиться, что всё работает

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

Шаг 1: С другой машины (не с вашего IP из белого списка) попробуйте SSH-входы с неверным паролем. После 3 неудач (в соответствии с maxretry) соединение должно быть отклонено.

Если второй машины нет, симулируйте бан через fail2ban-client:

sudo fail2ban-client set sshd banip 198.51.100.25

Шаг 2: Убедитесь, что бан зафиксирован:

sudo fail2ban-client status sshd

Забаненный IP должен появиться в Banned IP list.

Шаг 3: Убедитесь, что правило файрвола создано.

Для UFW:

sudo ufw status numbered | grep 198.51.100.25

Для nftables:

sudo nft list table inet f2b-table

IP должен быть в set внутри таблицы.

Шаг 4: Разбаньте и проверьте удаление:

sudo fail2ban-client set sshd unbanip 198.51.100.25
sudo fail2ban-client status sshd

IP больше не должен быть в списке банов. Проверьте файрвол снова, чтобы убедиться, что правило удалено.

Справочник параметров конфигурации Fail2Ban

Параметр По умолчанию Рекомендуемое Описание
bantime 10m 1h или 3600 Длительность бана
findtime 10m 10m или 600 Окно подсчёта ошибок
maxretry 5 3 для SSH, 5-20 для веба Ошибок до бана
ignoreip 127.0.0.1/8 ::1 Добавьте свой IP IP, которые никогда не банятся
banaction nftables (Ubuntu 24.04), iptables-multiport (upstream) ufw или nftables-multiport Команда файрвола для выполнения
backend auto systemd Источник логов (journal systemd на современных дистрибутивах)
destemail root@localhost Ваш email Получатель уведомлений
action %(action_)s %(action_mwl)s для email-уведомлений Действие при бане

Что-то пошло не так?

Fail2Ban не запускается: проверьте синтаксические ошибки в файлах jail. Пропущенная скобка или невалидное значение помешают запуску.

sudo fail2ban-client -t

Это тестирует конфигурацию без запуска сервиса. Исправьте обнаруженные ошибки.

Jail показывает 0 совпадений, хотя атаки идут: скорее всего, неправильный backend. На Ubuntu 24.04 и Debian 12 используйте backend = systemd. Если стоит backend = auto и в системе нет /var/log/auth.log, Fail2Ban ничего не читает.

Забаненный IP всё ещё может подключаться: действие бана не соответствует вашему файрволу. Если используете UFW — banaction = ufw. Если nftables напрямую — banaction = nftables-multiport. Проверьте, что правило файрвола действительно создаётся после бана.

Вы забанили себя: зайдите на сервер через веб-консоль хостинг-провайдера (VNC/KVM). Оттуда:

sudo fail2ban-client set sshd unbanip YOUR_IP

Или остановите Fail2Ban полностью:

sudo systemctl stop fail2ban

Затем исправьте конфигурацию ignoreip и перезапустите.

Fail2Ban потребляет слишком много памяти: на серверах с большими лог-файлами Fail2Ban может съедать память. Задайте dbpurgeage для ограничения размера базы данных:

sudo tee /etc/fail2ban/jail.d/99-performance.conf > /dev/null << 'EOF'
[DEFAULT]
dbpurgeage = 7d
EOF

Авторское право 2026 Virtua.Cloud. Все права защищены. Данный контент является оригинальным произведением команды Virtua.Cloud. Воспроизведение, повторная публикация или распространение без письменного разрешения запрещены.

Готовы попробовать?

Защитите ваш Linux VPS с помощью Fail2Ban.

Смотреть тарифы VPS
Установка и настройка Fail2Ban на Linux VPS