lenec ru

← все посты

Fail2ban на Ubuntu 24: настройка против brute force

14K

Fail2ban — простой и надёжный инструмент против перебора паролей. Я ставлю его на каждый VPS первым же шагом после базовой настройки. На Ubuntu 24.04 он работает без сюрпризов, но есть нюансы конфигурации, которые знают не все. Расскажу, что у меня настроено по умолчанию.

Что делает Fail2ban

Идея простая: парсит логи сервисов (по regex), считает количество неудачных попыток с одного IP за окно времени, и если их слишком много — блокирует IP в файрволе на заданное время. Вернее всего работает на SSH, на nginx-ручках логина, на любых endpoint-ах, которые пишут в лог факт неуспешного входа.

Установка

sudo apt update
sudo apt install -y fail2ban
sudo systemctl status fail2ban

На Ubuntu 24.04 ставится свежая версия (1.0.x), которая умеет работать с nftables и systemd-journal без лишних плясок.

Базовая конфигурация

Никогда не редактируй /etc/fail2ban/jail.conf напрямую. Он перезаписывается при обновлениях. Все свои настройки кладём в /etc/fail2ban/jail.local.

sudo tee /etc/fail2ban/jail.local >/dev/null <<'EOF'
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
backend  = systemd
banaction = iptables-multiport
# белый список — твоя сеть, чтобы случайно не забанить себя
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 192.168.0.0/16

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

[nginx-http-auth]
enabled = true
port    = http,https
logpath = /var/log/nginx/error.log

[nginx-limit-req]
enabled = true
port    = http,https
logpath = /var/log/nginx/error.log
findtime = 10m
maxretry = 10
EOF

sudo systemctl reload fail2ban

Что важно:

  • bantime = 1h: первый бан на час. На повторных нарушениях у меня recidive jail продлевает.
  • findtime = 10m, maxretry = 5: 5 неудач за 10 минут — бан.
  • backend = systemd: на Ubuntu 24 SSH пишет логи в journald, не в файл. Этот бэкенд читает journald напрямую.
  • ignoreip: добавь сюда свой статический IP, если он есть. Иначе случайная серия неудачных входов и сам себя залочишь.

Recidive jail — повторные нарушители

Полезный приём: банить надолго тех, кто уже банился несколько раз.

sudo tee -a /etc/fail2ban/jail.local >/dev/null <<'EOF'

[recidive]
enabled  = true
logpath  = /var/log/fail2ban.log
bantime  = 1w
findtime = 1d
maxretry = 3
EOF

sudo systemctl reload fail2ban

Логика: если IP попадал в любой бан 3 раза за день — кладём его в recidive jail на неделю. На моих серверах это срезает заметную долю атакующего трафика.

Защита nginx

Базовый nginx-jail из коробки ловит ошибки авторизации в стандартном формате. Если у тебя своё API с ручкой /api/auth/sign-in, имеет смысл добавить свой filter и jail.

Filter /etc/fail2ban/filter.d/myapp-auth.conf:

[Definition]
failregex = ^<HOST> .* "POST /api/auth/sign-in.* HTTP/.*" 401 .*$
            ^<HOST> .* "POST /api/auth/sign-in.* HTTP/.*" 429 .*$
ignoreregex =

Jail в jail.local:

[myapp-auth]
enabled  = true
port     = http,https
filter   = myapp-auth
logpath  = /var/log/nginx/myapp_access.log
findtime = 10m
maxretry = 8
bantime  = 30m

Проверяем regex:

sudo fail2ban-regex /var/log/nginx/myapp_access.log /etc/fail2ban/filter.d/myapp-auth.conf

Должно показать «matched ... lines», если в логе уже есть атаки. Если 0 совпадений — формат лога не такой, regex надо подправить.

Защита от ddos через limit_req

В nginx стоит limit_req_zone на чувствительные ручки. Каждый отказ пишется в error.log как limiting requests. Стандартный jail nginx-limit-req это ловит и банит на уровне файрвола.

Если правил limit_req много, легко наловить кучу банов. Контролируй maxretry и findtime: 10 нарушений за 10 минут с одного IP — нормальный потолок.

Проверка состояния

sudo fail2ban-client status
sudo fail2ban-client status sshd

Первая команда покажет список активных jail, вторая — детали по конкретному. В выводе видно, сколько IP сейчас забанено и список адресов.

Разбанить вручную:

sudo fail2ban-client set sshd unbanip 1.2.3.4

Или весь jail:

sudo fail2ban-client unban --all

Уведомления

По умолчанию fail2ban пишет в журнал, но не уведомляет тебя. Можно навесить email через action:

[DEFAULT]
destemail = admin@example.ru
sender = fail2ban@example.ru
mta = sendmail
action = %(action_mwl)s

action_mwl — стандартный action, который пишет email с whois и log-tail для забаненного IP. Удобно понимать, кто, откуда, и что именно делал.

Для уведомлений в Telegram я использую отдельный action-скрипт, который вызывает curl на бот. Не самое элегантное решение, но работает.

Подводные камни

Ipv6

Старые версии fail2ban плохо работали с IPv6. На Ubuntu 24 уже всё ок, но если в твоей конфигурации banaction = iptables-..., IPv6 может игнорироваться. Включай nftables:

[DEFAULT]
banaction = nftables-multiport
banaction_allports = nftables-allports

nftables работает и с v4, и с v6 одинаково.

Конфликт с ufw

fail2ban и ufw оба работают с iptables. Конфликта нет, но полезно понимать, какой инструмент за что отвечает: ufw держит «разрешено / запрещено», fail2ban добавляет ban-правила выше. Я никогда не отключаю ufw из-за fail2ban.

Неправильный formatter

Если nginx у тебя пишет в JSON или кастомный формат, стандартные filter-ы не сработают. Либо пиши свой filter под свой формат, либо переключи nginx на стандартный combined.

В рут-логе systemd

На Ubuntu 24 SSH лога /var/log/auth.log может не быть, всё едет в journald. Если у тебя backend = auto или file — fail2ban не найдёт лог. Используй backend = systemd.

За nginx в облаке

Если приложение за nginx, а тот за CloudFlare — в логе будет IP CloudFlare, а не пользователя. Файл log_format нужно настроить так, чтобы первым логировался $http_x_forwarded_for, и filter должен его ловить.

Whitelist своего CI

Если у тебя CI/CD дёргает API сервера и иногда промахивается с авторизацией, можно случайно забанить IP CI. Чтобы не страдать, добавляй адреса runner-ов в ignoreip:

ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 192.168.0.0/16 1.2.3.4/32

Где 1.2.3.4 — IP твоего CI или office-сети.

Что у меня всегда стоит на новом VPS

  • SSH с ключами, парольный вход выключен.
  • fail2ban с jails: sshd, nginx-http-auth, nginx-limit-req, recidive.
  • Свой jail на /api/auth/sign-in, если приложение есть.
  • action_mwl + email или Telegram-уведомления.
  • backend = systemd, banaction = nftables-multiport.

Это занимает 15 минут и закрывает 90% нагрузки от автоматических сканеров. Полностью защититься от ddos одним fail2ban не получится, но от тривиальных сканеров — отлично. Дальше уже идут полноценные WAF и CDN, но это совсем другая история.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.