Server Warden
РУКОВОДСТВО ПО БЕЗОПАСНОСТИ СЕРВЕРА

Настройка Fail2ban: автоматическое предотвращение вторжений

Fail2ban — это инструмент предотвращения вторжений, который сканирует логи и отслеживает такие сервисы, как SSH и веб-серверы, на предмет повторяющихся неудачных попыток входа, после чего автоматически блокирует IP-адрес нарушителя на межсетевом экране на заданный период. При правильной настройке разумных jail'ов, фильтров и параметров бана он превращает часы ручного анализа логов в автоматизированную защиту, работающую непрерывно в фоновом режиме.

Быстрый результат (10 минут)

  • Выполните sudo apt install fail2ban (Debian/Ubuntu) или sudo dnf install fail2ban (RHEL/Alma/Rocky), если он ещё не установлен.
  • Скопируйте /etc/fail2ban/jail.conf в /etc/fail2ban/jail.local, чтобы ваши изменения сохранялись при обновлениях пакета.
  • Добавьте свой статический IP-адрес в ignoreip в разделе [DEFAULT], прежде чем что-либо включать.
  • Включите jail sshd с параметрами maxretry = 4 и bantime = 1h, затем выполните sudo systemctl restart fail2ban.
  • Убедитесь, что он работает, с помощью sudo fail2ban-client status sshd.

Как на самом деле работает fail2ban

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

Каждый защищаемый сервис определяется в конфигурации fail2ban как «jail». Jail объединяет три компонента: путь к логу, который нужно отслеживать, фильтр (набор regex-шаблонов, распознающих неудачную попытку в данном формате лога) и действие (что делать при превышении порога неудач — обычно это добавление правила межсетевого экрана через iptables, nftables или ufw). Когда fail2ban-client status показывает jail как активный, это означает, что демон отслеживает этот лог-файл практически в реальном времени и проверяет каждую новую строку по шаблонам фильтра.

Поскольку fail2ban работает на уровне логов, он не зависит от конкретного сервиса. Любой демон, который при неудачной аутентификации записывает в лог отличимую строку — будь то sshd, модуль аутентификации веб-сервера, почтовый сервер или пользовательское приложение — можно защитить, написав или переиспользовав для него фильтр. Именно поэтому проект «из коробки» поставляется с десятками готовых фильтров, как указано в официальном репозитории fail2ban на GitHub.

Установка fail2ban и подход с jail.local

Установите fail2ban через пакетный менеджер вашего дистрибутива, а затем создайте файл jail.local, вместо того чтобы редактировать jail.conf напрямую, поскольку обновления пакета перезаписывают jail.conf и незаметно отбрасывают ваши настройки.

# Debian / Ubuntu
sudo apt update && sudo apt install fail2ban

# RHEL / AlmaLinux / Rocky Linux
sudo dnf install epel-release
sudo dnf install fail2ban

# Copy the shipped defaults into a file fail2ban treats as an override
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Fail2ban сначала считывает jail.conf, а затем применяет поверх него jail.local, поэтому всё, что задано в jail.local, переопределяет настройки по умолчанию, не затрагивая исходный файл. Такой подход задокументирован в собственных конфигурационных файлах fail2ban, включая поставляемый jail.conf на GitHub, который явно инструктирует администраторов использовать jail.local для локальных изменений. То же разделение применяется и к отдельным файлам фильтров и действий, если вам когда-либо потребуется их настроить (filter.d/*.local, action.d/*.local).

После любого изменения в jail.local примените его командой sudo systemctl restart fail2ban и убедитесь, что демон запустился корректно, с помощью sudo systemctl status fail2ban. Синтаксическая ошибка в jail.local не даст сервису запуститься, поэтому всегда проверяйте статус после перезапуска, а не полагайтесь на предположение, что всё сработало.

Основные настройки: bantime, findtime, maxretry

Bantime задаёт, как долго IP-адрес остаётся заблокированным, findtime задаёт скользящее окно, за которое fail2ban анализирует события, а maxretry задаёт, сколько неудач в пределах этого окна приводят к бану. Эти три значения, заданные в разделе [DEFAULT] файла jail.local и опционально переопределяемые для каждого jail'а отдельно, определяют, насколько агрессивно или мягко работает fail2ban.

Значения по умолчанию, поставляемые с fail2ban, — это bantime в 10 минут (600 секунд), findtime в 10 минут и maxretry в 5 неудачных попыток. Временные значения можно указывать в виде обычных секунд или в сокращённом формате, например 10m, 1h или 1d, который fail2ban понимает нативно. Для SSH, доступного из интернета, большинство администраторов значительно ужесточают эти значения по сравнению с настройками по умолчанию, поскольку 10 минут почти не замедляют автоматизированный сканер, который просто повторит попытку после истечения бана.

[DEFAULT]
# how long an IP stays banned
bantime  = 1h

# the rolling window used to count failures
findtime = 10m

# failures allowed within findtime before a ban
maxretry = 4

# ban time grows the more often an IP re-offends
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 1w

Опцию bantime.increment стоит включить: она увеличивает продолжительность бана каждый раз, когда один и тот же IP-адрес повторно нарушает правила после истечения предыдущего бана, поэтому сканер, который продолжает возвращаться, получает всё более длительный бан вместо одного и того же фиксированного окна каждый раз. Отрицательное значение bantime означает постоянный бан, что больше подходит для jail'а recidive (рассматривается ниже), чем для jail'а первого уровня защиты, поскольку временный бан уже останавливает большинство автоматизированных инструментов подбора паролей, не блокируя навсегда IP-адрес, который позже может быть переназначен легитимному пользователю.

Настройка ignoreip, чтобы не заблокировать самого себя

Ignoreip — это белый список адресов и CIDR-диапазонов, которые fail2ban никогда не забанит, и в него всегда должен входить ваш собственный управляющий IP-адрес, прежде чем вы включите какой-либо jail. Задайте его в разделе [DEFAULT] файла jail.local, чтобы он автоматически применялся ко всем jail'ам.

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.42/32

Согласно собственной документации по конфигурации fail2ban, ignoreip принимает список IP-адресов, CIDR-масок или DNS-имён хостов, разделённых пробелами, и любое соединение с соответствующего адреса освобождается от всех действий бана независимо от того, сколько неудачных попыток оно вызывает. Если вы управляете сервером с постоянного офисного или домашнего IP-адреса, добавьте его сюда. Если ваш IP-адрес меняется, рассмотрите использование VPN или bastion-хоста со стабильным адресом, вместо того чтобы оставлять ignoreip открытым для широкого диапазона — это создало бы брешь, которой мог бы воспользоваться злоумышленник, если бы когда-либо получил доступ к этому диапазону IP-адресов.

Прежде чем полагаться на эту настройку, стоит её протестировать: подключитесь по SSH из нового окна терминала, намеренно допустив несколько неудачных попыток аутентификации с адреса, который вы контролируете, и убедитесь, что ваша основная сессия ни разу не сбрасывается с адреса из белого списка. Блокировка на удалённом VPS из-за неправильно настроенного ignoreip — распространённая и полностью предотвратимая ошибка, а для восстановления обычно требуется доступ к консоли через внеполосный канал у вашего хостинг-провайдера.

Настройка распространённых jail'ов: sshd, nginx, recidive

Jail'ы, которые вам действительно нужны, зависят от того, какие сервисы открыты наружу, но sshd, jail для веб-аутентификации и jail recidive покрывают наиболее распространённую поверхность атаки на типичном VPS с SSH и веб-сервером. Каждый jail — это секция в квадратных скобках в jail.local, называющая защищаемый сервис.

Jail sshd

SSH — самый стабильно атакуемый сервис на любом Linux-сервере, доступном из интернета, поскольку автоматизированные сканеры постоянно прощупывают порт 22 в поисках слабых учётных данных. Ужесточённый jail sshd — самая ценная настройка fail2ban, которую вы можете сделать.

[sshd]
enabled  = true
port     = ssh
filter   = sshd
backend  = systemd
logpath  = %(sshd_log)s
maxretry = 4
findtime = 10m
bantime  = 1h

В дистрибутивах на базе systemd задайте backend как systemd, чтобы fail2ban читал данные напрямую из журнала, а не из файла лога — это надёжнее в дистрибутивах, которые по умолчанию направляют логи sshd через journald. Дополнительные меры, такие как полное отключение аутентификации по паролю, которые снижают саму нагрузку, доходящую до этого jail'а, смотрите в нашем руководстве по усилению защиты SSH.

Jail nginx-http-auth

Если nginx обслуживает что-либо за HTTP basic-аутентификацией или вы используете его как фронтенд для админ-панели, включите соответствующий jail, чтобы подбор учётных данных для этого входа отслеживался так же, как и перебор паролей SSH.

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

Для конфигураций nginx, которые обслуживают формы входа или страницы администрирования CMS, а не HTTP basic-аутентификацию, как правило, требуется пользовательский или сторонний фильтр, настроенный под конкретный формат лога этого приложения, поскольку fail2ban может сопоставлять только те шаблоны, для которых у него есть фильтр.

Jail recidive (повторные нарушители)

Jail recidive отслеживает собственный лог fail2ban, а не лог сервиса, и банит IP-адреса, которые уже несколько раз были забанены другими jail'ами, усиливая реакцию на настойчивых злоумышленников.

[recidive]
enabled  = true
filter   = recidive
logpath  = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime  = 1w
findtime = 1d
maxretry = 3

Такой многоуровневый подход — короткие баны за первое нарушение с эскалацией до недельного бана после трёх отдельных банов за 24 часа — не затрагивает легитимных пользователей, которые просто опечатались при вводе пароля, но делает устойчивый перебор паролей нецелесообразным. Обратите внимание на действие banaction_allports, которое блокирует IP-адрес нарушителя на всех портах, а не только на том, на котором он был изначально пойман, поскольку повторный нарушитель уже явно продемонстрировал злонамеренные намерения.

Не уверены, какие jail'ы действительно нужны вашему серверу?

Бесплатная проверка сервера в режиме только чтения покажет, что открыто на вашем VPS, и укажет на пробелы прежде, чем их найдёт злоумышленник.

Получить бесплатную проверку сервера Связаться с инженером по безопасности

Как работают фильтры и действия

Фильтр — это набор регулярных выражений, с которыми fail2ban сопоставляет новые строки лога, чтобы распознать неудачную попытку аутентификации, а действие определяет команду межсетевого экрана, которая выполняется при срабатывании бана или разбана. Оба хранятся соответственно в /etc/fail2ban/filter.d/ и /etc/fail2ban/action.d/, а jail'ы ссылаются на них по имени.

Для распространённых сервисов вам редко нужно писать фильтр с нуля, поскольку fail2ban поставляется с готовыми фильтрами для sshd, нескольких шаблонов аутентификации веб-серверов, почтовых серверов и других сервисов. Пользовательские фильтры действительно нужны для логов, специфичных для конкретного приложения, например для собственной формы входа, которая пишет своё сообщение об ошибке. В этом случае возьмите за основу существующий фильтр и протестируйте своё регулярное выражение на реальных строках лога с помощью fail2ban-regex, прежде чем включать jail — это позволяет проверить фильтр на реальном или тестовом лог-файле, не рискуя запустить в продакшн неудачное правило бана.

# test a filter against the real log before trusting it
sudo fail2ban-regex /var/log/nginx/error.log /etc/fail2ban/filter.d/nginx-http-auth.conf

Действие бана по умолчанию для большинства jail'ов добавляет правило межсетевого экрана (через iptables, nftables или ufw — в зависимости от того, что fail2ban обнаруживает на хосте), которое отбрасывает или отклоняет трафик с забаненного IP-адреса. Поскольку действие является подключаемым модулем, можно также написать собственное действие, обращающееся к API облачного межсетевого экрана вместо локального или в дополнение к нему — это важно, если сетевой межсетевой экран вашего провайдера находится перед хостом и одного локального правила iptables недостаточно, чтобы остановить трафик до того, как он до него дойдёт.

Проверка статуса, разбан и логи

Используйте fail2ban-client, чтобы проверить, что работает, и вручную разбанить IP-адрес, а также проверяйте /var/log/fail2ban.log для получения полной истории всех событий бана и разбана. Это команды, к которым вы будете обращаться чаще всего после запуска fail2ban.

# list all active jails
sudo fail2ban-client status

# check a specific jail's ban count and currently banned IPs
sudo fail2ban-client status sshd

# manually unban an IP (useful if you locked out a legitimate user)
sudo fail2ban-client set sshd unbanip 203.0.113.77

# tail the log to watch bans happen in real time
sudo tail -f /var/log/fail2ban.log

Стоит еженедельно проверять fail2ban-client status или встроить эту проверку в систему мониторинга, поскольку jail, который незаметно не запускается (например, из-за изменения пути к логу после обновления сервиса), оставляет этот сервис без защиты без каких-либо очевидных признаков. Если у вас уже есть централизованный мониторинг логов, смотрите наше руководство по мониторингу сервера и анализу логов о том, как подключить собственный лог fail2ban к этому конвейеру, чтобы баны отображались вместе с другими событиями безопасности, а не оставались в изолированном файле.

Частые ошибки конфигурации, которых стоит избегать

Самые частые ошибки при работе с fail2ban — это оставить ignoreip пустым, использовать значения logpath, не соответствующие реальному расположению логов в дистрибутиве, и считать fail2ban достаточным сам по себе, а не одним из уровней более широкого плана усиления защиты. Каждая из этих ошибок незаметно сводит на нет работу инструмента без каких-либо сообщений об ошибке.

  • Неверный logpath или backend: В дистрибутивах systemd, где sshd пишет логи в журнал, а не в обычный файл, jail, настроенный с файловым logpath и без journal-backend, попросту никогда не увидит ни одной строки лога, и такой jail будет отображаться как включённый, но никогда никого не забанит.
  • Отсутствие перезапуска после изменения конфигурации: fail2ban не перезагружает jail.local автоматически «на лету»; для вступления изменений в силу требуется restart или reload, и пропуск этого шага — частая причина недоумения «почему это не работает».
  • Слишком высокое значение maxretry: maxretry, равное 10 или больше, для jail'а SSH, доступного из интернета, даёт автоматизированным инструментам десять бесплатных попыток без каких-либо последствий, чего часто достаточно, чтобы списки учётных данных подобрали слабый пароль.
  • Забыть про jail recidive: без него злоумышленник может просто пережидать каждый отдельный бан и бесконечно повторять попытки с одной и той же, не эскалирующейся частотой.
  • Восприятие fail2ban как полного решения: он снижает шум от перебора паролей, но не устраняет уязвимости, не останавливает целевую атаку с использованием одной корректной учётной записи и не заменяет базовые меры, описанные в нашем чек-листе безопасности VPS и в статье об основах усиления защиты сервера.

Если fail2ban развёрнут, но взлом всё же происходит через совершенно другой вектор, например через непропатченную уязвимость приложения, наличие заранее продуманного плана важнее любого отдельного инструмента. Наше руководство по реагированию на инциденты при взломе сервера описывает, что делать в первые часы после обнаружения компрометации.

Часто задаваемые вопросы

От чего на самом деле защищает fail2ban?

Fail2ban защищает от автоматизированных атак перебора паролей (brute-force) и подстановки учётных данных (credential stuffing), отслеживая в лог-файлах повторяющиеся неудачные попытки аутентификации и временно блокируя IP-адрес нарушителя на уровне межсетевого экрана. Он не защищает от единичного удачно подобранного пароля, распределённых атак, охватывающих множество IP-адресов, или уязвимостей в самом приложении.

Заменяет ли fail2ban полноценное усиление защиты SSH?

Нет. Fail2ban — это уровень обнаружения и реагирования, а не замена аутентификации по ключу, отключения входа под root или смены порта SSH по умолчанию. Лучше всего он работает в сочетании с этими мерами, а не вместо них.

В чём разница между bantime, findtime и maxretry?

Findtime — это скользящее временное окно, за которое fail2ban анализирует события. Maxretry — это количество неудачных попыток, допустимых в пределах этого окна, прежде чем сработает бан. Bantime — это продолжительность результирующего бана.

Может ли fail2ban заблокировать меня на моём же сервере?

Да, если ваш собственный IP-адрес не указан в списке ignoreip и вы допустите достаточно неудачных попыток аутентификации, fail2ban забанит вас так же, как и любого другого. Чтобы этого избежать, добавьте свой статический IP-адрес или управляющую сеть в ignoreip до включения jail'ов.

Баны должны быть постоянными или временными?

Для большинства jail'ов следует использовать временный bantime, измеряемый минутами или часами, с эскалацией через jail recidive для повторных нарушителей. Постоянные баны обычно применяются только для jail'а recidive или для IP-адресов, подтверждённо являющихся вредоносными.

Работает ли fail2ban с межсетевыми экранами облачных провайдеров, или только с iptables?

Действия бана по умолчанию в fail2ban используют iptables, nftables или ufw на локальном хосте, но его также можно настроить с помощью пользовательских скриптов действий, обращающихся к API межсетевого экрана облачного провайдера. Для большинства конфигураций с одним VPS-сервером локального действия межсетевого экрана достаточно.

Как узнать, действительно ли fail2ban что-то блокирует?

Выполните fail2ban-client status, чтобы увидеть список активных jail'ов, и fail2ban-client status sshd, чтобы увидеть текущее количество банов и список забаненных IP-адресов. Лог /var/log/fail2ban.log также фиксирует каждое событие бана и разбана.

Достаточно ли одного fail2ban для защиты VPS?

Ни один отдельный инструмент не является достаточным сам по себе. Fail2ban следует применять вместе с усилением защиты SSH, правильно настроенным межсетевым экраном, своевременным патчингом и мониторингом логов как часть многоуровневого подхода, а не как самостоятельную защиту.

Не уверены, в каком состоянии ваш сервер?

Получите бесплатную проверку безопасности в режиме только чтения или поговорите с инженером по безопасности об управляемой защите.

Получить бесплатную проверку сервера Связаться с инженером по безопасности