Fail2ban SSH – це практичний спосіб відсікати брутфорс по логах, не лізучи одразу в важкі IDS або зовнішні WAF. Для homelab цього часто достатньо: SSH не засипає логін-спробами, а Nginx чи Apache не тримають нескінченний шум із кількох адрес. Нижче – робоча схема для SSH і веб-сервісів, перевірка блокувань і місця, де конфіг зазвичай ламається.
Fail2ban читає логи сервісів, шукає збіги через фільтри і тимчасово додає бан у фаєрвол. Суть проста, але реальна користь залежить від двох речей: чи пише сервіс коректні логи і чи бан застосовується саме в той стек фаєрволу, який реально активний на хості.
На невеликому сервері це рішення працює добре. Але якщо перед веб-сервісом стоїть reverse proxy, CDN або окремий load balancer, банити можна не клієнта, а проксі. Це один із найчастіших промахів: Fail2ban налаштований формально правильно, а блокує не того.
Коли Fail2ban SSH реально дає результат
Fail2ban SSH дає результат там, де атака йде напряму на хост, а логи містять реальну IP-адресу джерела. Для SSH це типовий сценарій. Для веб-сервісів – лише якщо access log і error log налаштовані без втрати клієнтського IP.
Для SSH інструмент закриває найбанальніший, але постійний шум: підбір паролів, повторні спроби входу, перебір користувачів. Якщо використовується автентифікація по ключах і парольний вхід вимкнено, користь все одно є – логи стають чистішими, а зайві сесії не висять без кінця.
Для веба все тонше. Брутфорс на /wp-login, /xmlrpc, панель адміністрування або Basic Auth Fail2ban відловлює нормально. Але проти розподілених спроб із великої кількості IP ефект обмежений. По суті, це локальний механізм реакції, а не повноцінний рівень антибот-захисту.
Як налаштувати Fail2ban SSH і веб-сервіси
Оптимальний підхід – не редагувати базові файли пакета, а працювати через локальний конфіг. Так оновлення проходять спокійніше, а власні правила не затираються. Для Debian/Ubuntu типовий шлях простий: встановити пакет, увімкнути сервіс і створити локальні jail.
- Встановити пакет і запустити сервіс.
- Створити локальний конфіг для jail.
- Увімкнути окремо SSH і потрібний веб-сервіс.
- Перезапустити службу і перевірити статус.
sudo apt update sudo apt install fail2ban sudo systemctl enable --now fail2ban sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Далі варто мінімізувати конфіг і лишити тільки потрібні секції. Для SSH базового jail зазвичай вистачає.
[sshd] enabled = true port = ssh logpath = %(sshd_log)s backend = systemd maxretry = 5 findtime = 10m bantime = 1h
Для Nginx або Apache має сенс вмикати лише ті jail, які відповідають реальній проблемі. Не треба активувати все підряд. Інакше буде багато хибних спрацювань, особливо якщо в логах змішуються редіректи, health-check і авторизаційні запити.
[nginx-http-auth] enabled = true logpath = /var/log/nginx/error.log maxretry = 5 findtime = 10m bantime = 1h [apache-auth] enabled = true logpath = /var/log/apache2/error.log maxretry = 5 findtime = 10m bantime = 1h
Якщо використовується UFW, зазвичай достатньо стандартної дії бану. Якщо на хості вже все сидить на nftables або iptables напряму, треба переконатися, що action збігається з реальною схемою фаєрволу. Тут часто і ховається проблема: Fail2ban вважає, що бан спрацював, а в мережі нічого не змінилося.
Які логи і фільтри потрібні для SSH та веба
Fail2ban SSH працює тільки тоді, коли шаблон збігається з реальним форматом логів. Якщо система перейшла на journald, а jail читає старий файл, банів не буде. Та сама історія з веб-сервісами: лог є, але потрібний рядок пишеться не туди, куди дивиться jail.
Для SSH на сучасних дистрибутивах часто доречний backend systemd. Це прибирає залежність від окремого текстового логу. Для Nginx чи Apache зазвичай працюють звичні logpath, але після кастомізації форматів логів фільтр може перестати збігатися навіть при валідних помилках авторизації.
Нетипова, але часта проблема в homelab – сервіси за reverse proxy. Якщо на вході стоїть Traefik, Nginx Proxy Manager або Cloudflare, у локальному журналі backend-сервісу може бути IP проксі, а не клієнта. У такій схемі fail2ban ssh для SSH лишається корисним, але для веба треба спочатку привести до ладу real IP, а вже потім вішати бан.
Як перевірити, що Fail2ban SSH справді блокує атаки
Перевірка має бути подвійною: спочатку статус jail, потім реальна наявність правила у фаєрволі. Лише статусу Fail2ban недостатньо. Служба може показувати banned IP, але правило не потрапить у той стек, який обробляє трафік.
sudo fail2ban-client status sudo fail2ban-client status sshd sudo iptables -L -n sudo nft list ruleset sudo ufw status
Для SSH перевірка проста: кілька невдалих спроб входу з тестової адреси мають збільшити лічильник failed і потім додати IP у banned. Для веба краще дивитися одночасно лог сервера і статус jail. Якщо рядки в логах є, а jail мовчить, проблема майже завжди у фільтрі або logpath.
Ще один корисний тест – ручне розбанення після перевірки.
sudo fail2ban-client set sshd unbanip 192.0.2.10
Якщо команда відпрацьовує, але доступ із тієї адреси все одно не повернувся, значить бан висить не лише в Fail2ban. Таке буває, коли поверх нього працюють окремі правила UFW, crowdsec або зовнішній reverse proxy з власним блокуванням.
Де Fail2ban ламається найчастіше
Найчастіше Fail2ban ламається не в самих jail, а на стику логів, проксі і фаєрволу. Конфіг може виглядати акуратно, сервіс запущений, але захисту по факту немає. Саме тому fail2ban ssh треба перевіряти не по YAML-подібній красі файлів, а по фактичному бану конкретної адреси.
Баниться адреса проксі, а не клієнта
Це класика для self-hosted стеків із reverse proxy. Поки веб-сервер не отримує реальний client IP через X-Forwarded-For або аналогічний механізм trusted proxy, блокування не має великого сенсу. У гіршому випадку можна відрізати власний проксі.
Jail читає не той лог
Після переходу на journald, контейнеризації або кастомного logrotate шлях до файлу часто вже не той. Fail2ban запускається без помилок, але матчів нуль. Це підступна поломка, бо зовні все виглядає штатно.
Неправильний action для фаєрволу
На частині систем одночасно присутні UFW, nftables і залишки старих iptables-правил. Якщо не зрозуміти, хто реально фільтрує трафік, бан може записуватися в порожній шар. На практиці це одна з головних причин, чому Fail2ban вважають марним.
Занадто агресивні таймінги
Низький maxretry і довгий bantime добре виглядають лише до першого власного блокування. Для SSH це терпимо. Для веб-панелей, де логін через SSO, MFA або погано написаний клієнт, хибні бани трапляються частіше.
Де Fail2ban SSH уже замалий
Fail2ban SSH добре працює як локальний захист одного вузла або кількох невеликих серверів. Але при розподіленому брутфорсі, великій кількості веб-додатків або складній проксі-схемі його межа швидко стає видимою. Тоді потрібне або винесення захисту на edge-рівень, або інший підхід до кореляції подій.
У homelab межа зазвичай не в продуктивності, а в керованості. Коли на одному хості сидять SSH, кілька панелей, reverse proxy і ще контейнери з власними логами, список jail росте швидше, ніж реальна користь від них. У цей момент краще скоротити набір до кількох критичних точок входу, а решту закривати нормальною автентифікацією, VPN-доступом або обмеженням публічної експозиції.
Окремо варто тверезо оцінювати роль Fail2ban для SSH, якщо парольний вхід уже вимкнений. Він тоді не замінює hardening, а лише добирає шум і робить атаку дорожчою. Це корисно, але не той шар, на який варто покладати всю модель захисту.
Що лишити в робочому конфігу
Для більшості homelab-серверів достатньо трьох речей: fail2ban ssh для SSH, один точковий jail для веб-авторизації і нормальна перевірка через реальний бан. Без цього все перетворюється на декоративний конфіг.
Якщо сервер стоїть напряму в інтернеті, Fail2ban закриває базовий шум швидко і без зайвої складності. Якщо ж трафік іде через кілька проксі, CDN або контейнерний стек із кривими логами, спочатку треба відновити видимість реального клієнта. Інакше блокування виглядає надійно тільки в статусі сервісу.