Сервер работает. Красиво. Тихо. И где-то в тёмном углу интернета сидит ботнет, который тысячу раз в час пробует root:123456, admin:admin и pi:raspberry через SSH. Без Fail2Ban — это сожжённые ресурсы и потенциальный взлом. С Fail2Ban — тишина и покой.
Проблема одна: стандартный интерфейс Fail2Ban — это CLI. В принципе нормально для опытного сисадмина в 3 часа ночи. Но когда нужно быстро проверить кого заблокировали, разбанить клиента или показать боссу «у нас всё под контролем» — fail2ban-client status sshd выглядит не очень презентабельно.
В этой статье пройдём весь путь: от голой установки fail2ban на Debian/Ubuntu, через настройку jail-ов для SSH и Nginx, до красивого веб-UI через Docker Compose, где список заблокированных IP выглядит как дашборд, а не выхлоп сломанного grep-а.
Что такое Fail2Ban и как он работает
Fail2Ban — это демон мониторинга логов с механизмом автоматической блокировки. Если совсем просто: он читает лог-файлы, ищет в них подозрительные паттерны (например, «неправильный пароль» 5 раз за 2 минуты) и даёт команду файрволу заблокировать этот IP.
Думайте о нём как о вахтёре в серверной. Обычный вахтёр записывает кто заходит. Fail2Ban — вахтёр, который молча смотрит как кто-то несколько раз подряд пробует чужой пропуск, и просто вносит нарушителя в чёрный список. Без лишних вопросов.
Архитектура в двух словах
Fail2Ban работает через три ключевых компонента:
- Фильтры (filters) — регулярные выражения, которые ищут события в логах. Например, строку «Failed password» в
/var/log/auth.log. - Jail-ы (тюрьмы) — правила: «для такого-то сервиса, из такого-то лога, при N нарушениях за X секунд — банить на Y секунд».
- Экшены (actions) — что делать при бане. По умолчанию — добавить правило в
iptablesилиnftables.
Fail2Ban не заменяет файрвол — он им управляет. Сам по себе трафик не режет. Он выдаёт команды iptables/nftables/ufw, а те блокируют пакеты на уровне ядра.
Какие сервисы защищает Fail2Ban
| Jail | Что мониторит | Лог-файл |
|---|---|---|
sshd |
Брутфорс SSH | /var/log/auth.log |
nginx-http-auth |
Неудачный HTTP Basic Auth | /var/log/nginx/error.log |
nginx-botsearch |
Сканирование URL ботами | /var/log/nginx/access.log |
postfix |
Спам-атаки на почтовый сервер | /var/log/mail.log |
vsftpd |
Брутфорс FTP | /var/log/vsftpd.log |
apache-auth |
Брутфорс Apache | /var/log/apache2/error.log |
mysql-auth |
Попытки входа в MySQL | /var/log/mysql/error.log |
Нужен VPS для своего сервера?
Выбирайте надёжный хостинг с быстрым SSD, защитой от DDoS и почасовой оплатой. Идеально для тестирования Fail2Ban и продакшна.
Установка Fail2Ban на Debian / Ubuntu
Установка fail2ban — дело пяти минут. Пакет есть в стандартных репозиториях Debian и Ubuntu, никаких PPA и ручных сборок не нужно.
Шаг 1. Обновляем пакеты и устанавливаем
apt update && apt upgrade -y
apt install fail2ban -y
На Ubuntu 20.04/22.04/24.04 и Debian 11/12 всё работает одинаково. Версия из репозитория немного отстаёт от upstream, но для большинства задач некритично.
Шаг 2. Включаем и стартуем сервис
systemctl enable fail2ban
systemctl start fail2ban
Шаг 3. Проверяем что работает
systemctl status fail2ban
Должны увидеть active (running) зелёным. Если нет — смотрим секцию «Типичные ошибки» ниже.
Шаг 4. Первый контакт с fail2ban-client
fail2ban-client status
Покажет список активных jail-ов. Сразу после установки увидите пустой список или только sshd — в зависимости от дистрибутива. Это нормально, сейчас настроим.
fail2ban-client version — покажет установленную версию. Всё выше 0.11 отлично: поддерживает nftables и bantime.increment.Базовая настройка Fail2Ban: jail.local
Важный момент, который пропускают 80% новичков: никогда не редактируйте jail.conf. Это дефолтная конфигурация, которая перезаписывается при обновлении пакета. Ваши настройки — только в jail.local.
Создаём jail.local
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Или создаём с нуля — это даже лучше, меньше мусора:
nano /etc/fail2ban/jail.local
Базовые глобальные настройки
[DEFAULT]
# Время бана в секундах (3600 = 1 час)
bantime = 3600
# Окно наблюдения: попытки считаются за этот период
findtime = 600
# Максимум неудачных попыток до бана
maxretry = 5
# Ваш IP — никогда не банить! (через пробел или запятую)
ignoreip = 127.0.0.1/8 ::1 YOUR_IP_HERE
# Backend для чтения логов
backend = systemd
Добавьте свой IP в
ignoreip ДО того, как настроите жёсткие правила. Иначе рискуете заблокировать самого себя. Спросите меня, как я это узнал. (Нет, не спрашивайте.)Настройка jail для SSH (sshd)
Самый важный jail для большинства серверов. SSH-брутфорс — топ-1 по популярности среди атак на VPS:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400
findtime = 300
Расшифровка: 3 неудачных попытки за 5 минут — и IP банится на 24 часа. Жёстко? Да. Эффективно? Абсолютно.
На современных системах с systemd лог
/var/log/auth.log может быть пустым. Используйте backend = systemd в секции [DEFAULT] — тогда logpath для sshd можно убрать совсем.Настройка jail для Nginx
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400
Применяем конфигурацию
systemctl restart fail2ban
fail2ban-client status
Главные команды fail2ban-client
Рано или поздно придёт письмо от разозлённого клиента: «вы заблокировали мой офисный IP». Вот тут и нужно знать команды.
Статус и мониторинг
# Список всех активных jail-ов
fail2ban-client status
# Подробный статус конкретного jail (кол-во банов, список IP)
fail2ban-client status sshd
# Статус nginx jail
fail2ban-client status nginx-http-auth
Управление банами
# Разбанить IP из конкретного jail
fail2ban-client set sshd unbanip 1.2.3.4
# Забанить IP вручную
fail2ban-client set sshd banip 5.6.7.8
# Разбанить IP из всех jail-ов сразу
for jail in $(fail2ban-client status | grep "Jail list" | sed "s/.*://;s/,//g"); do
fail2ban-client set $jail unbanip 1.2.3.4
done
Перезагрузка конфигурации
# Перезагрузить конфиг без рестарта демона
fail2ban-client reload
# Перезагрузить только один jail
fail2ban-client reload sshd
Тестирование фильтров
# Проверить сработает ли фильтр по реальному логу
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
Незаменимо при написании кастомных фильтров — проверяете regex до запуска в продакшн.
| Команда | Что делает |
|---|---|
fail2ban-client status |
Список всех jail-ов и их статус |
fail2ban-client status sshd |
Детали sshd jail: кол-во банов, список IP |
fail2ban-client set sshd unbanip IP |
Разбанить IP из sshd jail |
fail2ban-client set sshd banip IP |
Забанить IP вручную |
fail2ban-client reload |
Перезагрузить конфигурацию |
fail2ban-regex LOG FILTER |
Протестировать фильтр на реальном логе |
fail2ban-client ping |
Проверить что демон жив |
Где смотреть логи Fail2Ban
Логи Fail2Ban — главный источник истины. Там написано: кого заблокировали, когда, почему. И почему jail молчит, если что-то настроено не так.
Основной лог-файл
# Смотрим fail2ban log в реальном времени
tail -f /var/log/fail2ban.log
Примерный вывод:
2025-03-15 04:17:32 fail2ban.filter INFO [sshd] Found 185.220.101.45
2025-03-15 04:17:35 fail2ban.filter INFO [sshd] Found 185.220.101.45
2025-03-15 04:17:38 fail2ban.actions NOTICE [sshd] Ban 185.220.101.45
Found — событие зафиксировано. Ban — IP заблокирован. Много Found, но нет Ban? Ещё не достигнут maxretry или проблема с фильтром.
Логи через journalctl
# Логи fail2ban через systemd journal
journalctl -u fail2ban
# В реальном времени
journalctl -u fail2ban -f
# За последние 30 минут
journalctl -u fail2ban --since "30 min ago"
Список заблокированных IP
# Для конкретного jail
fail2ban-client status sshd | grep "Banned IP"
# Все забаненные IP из всех jail-ов
for jail in $(fail2ban-client status | grep "Jail list" | sed "s/.*://;s/,//g"); do
echo "=== $jail ==="; fail2ban-client status $jail | grep "Banned IP"
done
Проверьте настройку
logtarget в /etc/fail2ban/fail2ban.conf. Должно быть logtarget = /var/log/fail2ban.log или SYSTEMD-JOURNAL.Fail2Ban и firewall: iptables / UFW
Fail2Ban — не файрвол. Он — управляющий файрволом. Сам по себе не обрабатывает ни одного пакета. Только добавляет и удаляет правила в реальный файрвол.
Как работает связка fail2ban + iptables
По умолчанию Fail2Ban создаёт цепочку f2b-sshd в iptables и добавляет туда заблокированные IP:
# Смотрим правила fail2ban в iptables
iptables -L f2b-sshd -n --line-numbers
# Через nftables (современные системы)
nft list ruleset | grep -A5 fail2ban
Если используете UFW
UFW и Fail2Ban работают вместе, но требуют небольшой настройки. По умолчанию Fail2Ban использует iptables напрямую, что может конфликтовать с UFW. Создайте /etc/fail2ban/jail.d/ufw.conf:
[DEFAULT]
banaction = ufw
Теперь при бане Fail2Ban будет использовать ufw deny from IP вместо прямых iptables-правил.
# Проверить заблокированные IP в fail2ban цепочках
iptables -L -n | grep -E "f2b|fail2ban" | grep REJECT
Курс «Linux для DevOps»
Bash, systemd, networking, Docker — всё что нужно современному инженеру. Практические задания, живые стенды, сертификат.
Зачем нужен Fail2Ban UI — боль CLI в цифрах
Если вы один и умеете в консоль — можно обойтись без UI. Но есть ситуации, когда веб-интерфейс реально спасает:
- 🏢 Команда из нескольких человек: не каждый джун хочет возиться с SSH и помнить синтаксис fail2ban-client
- 📊 Надо показать статистику: «сколько атак за сутки» красивее выглядит в виде списка, а не grep-а
- 🔥 Оперативный разбан: в панике разбанить IP быстрее через UI, чем вспоминать точную команду
- 👁️ Мониторинг в реальном времени: живой список блокировок без постоянного
tail -f - 🏠 Домашний сервер/NAS: не всегда под рукой терминал, а браузер — всегда
Будем использовать образ crazymax/fail2ban — популярный open-source контейнер для Fail2Ban. Он подключается к сокету fail2ban (
/var/run/fail2ban/fail2ban.sock) и предоставляет браузерный интерфейс для управления и мониторинга.Установка Fail2Ban UI через Docker Compose
Это ключевой блок статьи. Разворачиваем за 10 минут.
Предварительные требования
- Docker 20.10+
- Docker Compose v2 (или compose plugin)
- Работающий Fail2Ban на хосте (не в Docker!)
- Доступ к
/var/run/fail2ban/fail2ban.sock
Fail2Ban должен работать на хосте, а не в контейнере. UI-контейнер только читает сокет и логи через volume mount. Это важно — fail2ban должен управлять iptables хостовой машины.
Проверяем что сокет существует
ls -la /var/run/fail2ban/fail2ban.sock
Должны увидеть что-то вроде:
srw-rw---- 1 root root 0 Mar 15 04:00 /var/run/fail2ban/fail2ban.sock
Если файла нет — fail2ban не запущен: systemctl start fail2ban
Устанавливаем Docker (если ещё нет)
# Быстрая установка через официальный скрипт
curl -fsSL https://get.docker.com | sh
# Добавляем пользователя в группу docker
usermod -aG docker $USER
# Проверяем
docker --version
docker compose version
Создаём директорию и docker-compose.yml
mkdir -p /opt/fail2ban-ui && cd /opt/fail2ban-ui
nano docker-compose.yml
version: '3.8'
services:
fail2ban-ui:
image: crazymax/fail2ban:latest
container_name: fail2ban-ui
restart: unless-stopped
ports:
- "8080:8080"
environment:
- TZ=Europe/Moscow
- F2B_LOG_TARGET=STDOUT
- F2B_LOG_LEVEL=INFO
- F2B_DB_PURGE_AGE=1d
volumes:
# Сокет fail2ban (только чтение)
- /var/run/fail2ban:/var/run/fail2ban:ro
# Логи системы (только чтение)
- /var/log:/var/log:ro
# Persistent данные UI
- ./data:/data
network_mode: host
Используем
network_mode: host, чтобы контейнер мог обращаться к сокету хостовой машины напрямую. Если нужна изоляция — уберите host networking и привяжите сокет явно через volume, как в следующем примере.Альтернативный вариант — явный bind сокета
version: '3.8'
services:
fail2ban-ui:
image: crazymax/fail2ban:latest
container_name: fail2ban-ui
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
volumes:
- /var/run/fail2ban/fail2ban.sock:/var/run/fail2ban/fail2ban.sock:rw
- /var/log/fail2ban.log:/var/log/fail2ban.log:ro
- /etc/fail2ban:/etc/fail2ban:ro
- ./data:/data
environment:
- TZ=Europe/Moscow
Запускаем
cd /opt/fail2ban-ui
docker compose up -d
# Проверяем
docker compose ps
docker compose logs -f fail2ban-ui
Открываем в браузере: http://YOUR_SERVER_IP:8080
Не оставляйте порт 8080 открытым для всего интернета. Привяжите к localhost и заходите через SSH-туннель (
ssh -L 8080:localhost:8080 user@server), либо закройте Nginx reverse proxy с Basic Auth.Reverse proxy через Nginx (рекомендуется)
Создаём /etc/nginx/sites-available/fail2ban-ui:
server {
listen 80;
server_name fail2ban.yourdomain.com;
auth_basic "Fail2Ban UI";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# Создаём пароль для Basic Auth
apt install apache2-utils -y
htpasswd -c /etc/nginx/.htpasswd admin
# Активируем сайт
ln -s /etc/nginx/sites-available/fail2ban-ui /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Как работать с Fail2Ban UI
После запуска контейнера открываете браузер — и перед вами дашборд. Разберём основные элементы.
Главная страница
- Статус демона — запущен/остановлен, версия
- Список активных jail-ов с количеством текущих банов
- Общая статистика — сколько IP забанено прямо сейчас
- Последние события — реальное время, кто и когда заблокирован
Управление jail-ами
Кликаете на любой jail — попадаете на страницу с текущими настройками (bantime, maxretry, findtime), списком заблокированных IP с временем бана и кнопкой «Unban» напротив каждого.
fail2ban список заблокированных — вместо grep-а
Вместо этого монстра:
for jail in $(fail2ban-client status | grep "Jail list" | sed "s/.*://;s/,//g"); do
fail2ban-client status $jail
done
Просто открываете браузер и видите всё в одном месте. Это то «качество жизни», ради которого и ставят UI.
5 практических кейсов
Кейс 1: Защита SSH с агрессивным режимом
[sshd]
enabled = true
port = ssh
filter = sshd
backend = systemd
maxretry = 3
findtime = 300
bantime = 86400
# Прогрессивный бан: каждый следующий бан длиннее предыдущего
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 604800 ; максимум 7 дней
С опцией bantime.increment бан растёт в прогрессии: первый — 24 часа, второй — 48, третий — 4 дня. Для упорных брутфорсеров — самое оно.
Кейс 2: Nginx — защита от ботов и сканеров
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400
[nginx-req-limit]
enabled = true
port = http,https
filter = nginx-req-limit
logpath = /var/log/nginx/error.log
maxretry = 10
findtime = 60
bantime = 7200
Для nginx-req-limit добавьте в конфиг Nginx:
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
}
}
Кейс 3: Скрипт быстрого разбана
Кладём в /usr/local/bin/f2b-unban:
#!/bin/bash
# Использование: f2b-unban 1.2.3.4
IP="$1"
if [ -z "$IP" ]; then
echo "Использование: $0 IP_ADDRESS"
exit 1
fi
echo "Снимаем бан для $IP во всех jail-ах..."
for jail in $(fail2ban-client status | grep "Jail list" | sed 's/.*://;s/,//g'); do
result=$(fail2ban-client set "$jail" unbanip "$IP" 2>/dev/null)
[ "$result" = "1" ] && echo "✅ Разбанен в jail: $jail"
done
echo "Готово!"
chmod +x /usr/local/bin/f2b-unban
f2b-unban 1.2.3.4
Кейс 4: Кастомный фильтр для своего приложения
Допустим, ваше приложение пишет в лог:
2025-03-15 04:17:12 [WARNING] Login failed for user 'admin' from 185.220.101.45
Создаём /etc/fail2ban/filter.d/myapp.conf:
[Definition]
failregex = ^.* Login failed for user '.*' from $
ignoreregex =
Добавляем jail в jail.local:
[myapp]
enabled = true
port = http,https
filter = myapp
logpath = /var/log/myapp/app.log
maxretry = 5
bantime = 3600
# Тестируем фильтр перед запуском
fail2ban-regex /var/log/myapp/app.log /etc/fail2ban/filter.d/myapp.conf
Кейс 5: Домашний сервер — минимальная защита с recidive
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
ignoreip = 127.0.0.1/8 192.168.0.0/16
[sshd]
enabled = true
[nginx-http-auth]
enabled = true
[recidive]
# Бан рецидивистов на 1 неделю
enabled = true
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime = 604800
findtime = 86400
maxretry = 3
Jail recidive смотрит в лог самого Fail2Ban и банит IP, которые были забанены 3+ раза за 24 часа — на целую неделю. Для особо упорных.
Типичные ошибки и их лечение
Ошибка 1: fail2ban не видит логи
Симптом: jail активен, атаки идут, банов нет, в fail2ban log тишина.
# Проверяем что лог существует
ls -la /var/log/auth.log
tail -20 /var/log/auth.log
# Проверяем что фильтр работает
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
Решение: На системах с systemd используйте backend = systemd в конфиге и уберите logpath для sshd.
Ошибка 2: Docker-контейнер не видит fail2ban.sock
Симптом: UI показывает «Connection refused» или «Socket not found».
# Проверяем права на сокет
ls -la /var/run/fail2ban/fail2ban.sock
# Проверяем что fail2ban запущен
systemctl status fail2ban
# Добавляем пользователя в группу fail2ban и перезапускаем
usermod -aG fail2ban www-data
docker compose restart fail2ban-ui
Ошибка 3: jail не активируется
Симптом: fail2ban-client status не показывает нужный jail.
# Смотрим ошибки
journalctl -u fail2ban | grep ERROR
# Проверяем синтаксис конфига
fail2ban-client -t
Частые причины: опечатка в имени jail, несуществующий logpath, неверное имя фильтра.
Ошибка 4: заблокировал сам себя
Классика жанра. Решение зависит от доступа:
# Если есть доступ к консоли сервера (не SSH):
fail2ban-client set sshd unbanip ВАШ_IP
# Временная остановка fail2ban (последний резерв):
systemctl stop fail2ban
# Заходим по SSH, добавляем свой IP в ignoreip, запускаем обратно
systemctl start fail2ban
ВСЕГДА добавляйте свой IP в
ignoreip до настройки жёстких правил. ВСЕГДА держите открытой вторую SSH-сессию во время изменения конфигурации. ВСЕГДА тестируйте на staging.Ошибка 5: iptables правила остаются после удаления fail2ban
# Смотрим остатки:
iptables -L -n | grep f2b
# Очищаем цепочки fail2ban:
iptables -F f2b-sshd 2>/dev/null
iptables -X f2b-sshd 2>/dev/null
Разборы ошибок, готовые скрипты, сравнения инструментов — каждую неделю в нашем Telegram-канале
Итог
За время этой статьи мы прошли весь путь:
- ✅ Установили и настроили Fail2Ban на Debian/Ubuntu с нуля
- ✅ Настроили защиту SSH с прогрессивным режимом банов
- ✅ Подключили защиту Nginx от сканеров и брутфорса
- ✅ Разобрали команды
fail2ban-clientдля ежедневной работы - ✅ Разобрались как читать fail2ban логи и что там искать
- ✅ Развернули Fail2Ban UI через Docker Compose
- ✅ Закрыли UI за Nginx с Basic Auth
- ✅ Разобрали 5 реальных кейсов и типичные ошибки
Fail2Ban — не серебряная пуля. Он не заменяет нормальный файрвол, не спасёт от распределённых атак с тысяч IP и не закроет дыры в коде приложения. Но это обязательный первый рубеж для любого публичного сервера. Дёшево, надёжно, эффективно.
А UI через Docker — это приятный бонус, который делает работу с инструментом чуть более человечной. Особенно в 2 часа ночи, когда очередной ботнет решил «познакомиться» с вашим сервером.
Настроили Fail2Ban? Следующий уровень — централизованный мониторинг через Grafana + Loki, или интеграция с Telegram-ботом для уведомлений о банах. Напишем об этом в следующей статье.
Пишите в комментарии или в наш Telegram-канал. Разберём ваш кейс — всё-таки мы IT-аптека, а не справочная служба погоды.
Оставайтесь на связи
Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.
Подписаться на IT-Аптеку →


