Безопасность серверов

Fail2ban: защита SSH, Nginx и Apache от перебора паролей

Как включить jail Fail2ban для SSH и веб-приложения, выбрать источник журналов, проверить бан, разблокировать IP и настроить ignoreip.

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

Сохраните доступ до включения бана

Перед изменением jail оставьте открытую административную сессию и подготовьте независимый аварийный канал доступа: консоль, BMC, VPN или bastion host. Добавляйте свой адрес в allowlist только если это действительно необходимо. Ошибка в порогах, журнале или action может временно заблокировать администратора.

Как устроен Fail2ban: jail, фильтр и action

Fail2ban уменьшает эффект brute force: служба читает уже записанные события, а не перехватывает пакеты на сетевом интерфейсе. Если служба не записала неудачный вход, строка имеет неожиданный формат либо в ней нет адреса клиента, Fail2ban не сможет принять корректное решение о блокировке.

КомпонентНазначениеЧто настраивают
JailСвязывает источник событий, фильтр, пороги и действие для одной службы.enabled, filter, backend, logpath, maxretry, findtime, bantime, action.
Фильтр Fail2banНабор регулярных выражений failregex, распознающих строки нарушения и адрес <HOST>.Готовый фильтр из filter.d или собственный локальный фильтр.
BackendСпособ чтения записей: systemd journal или файл.backend = systemd либо файловый backend, например polling; для файлов нужен logpath.
ActionКоманда на ban и unban; обычно добавляет и удаляет правило firewall.Подходящий action из action.d, совместимый с iptables, nftables, firewalld или другим фактическим стеком.

maxretry задаёт число распознанных неудач от одного адреса, после достижения которого в пределах окна findtime запускается ban. bantime задаёт длительность блокировки. Значения выбирают по реальному трафику: агрессивный порог может заблокировать администратора, мониторинг, пользователей за общим NAT или обратный прокси.

Имена и состав файлов зависят от пакета

Состав штатных jail, фильтров и action зависит от дистрибутива и версии пакета Fail2ban. Конкретные пути журналов, unit systemd, поля journal и параметры action также зависят от способа установки и настройки служб. Перед применением сверяйте установленную конфигурацию и официальное руководство Fail2ban, а для Nginx, Apache и приложения — их документацию.

Где размещать настройку: jail.local или jail.d

Не изменяйте поставляемые пакетом jail.conf, файлы jail.d/*.conf и штатные фильтры напрямую: обновление может заменить их. Конфигурация jail читается в таком порядке: jail.conf, затем jail.d/*.conf в лексикографическом порядке, затем jail.local и после него jail.d/*.local в лексикографическом порядке. Более позднее значение переопределяет более раннее. Практичный вариант — создать собственный файл, например /etc/fail2ban/jail.d/10-local-sshd.local: его проще сопровождать и сравнивать со штатной конфигурацией.

/etc/fail2ban/jail.local также подходит для небольшого числа общих переопределений. Но отдельные файлы jail.d/*.local удобнее разделять по сервисам: SSH, приложение, исключения и дополнительные jail. Эффективную конфигурацию после изменения проверяйте запуском Fail2ban и статусом нужного jail, а не только содержимым одного файла.

Настройка Fail2ban для SSH

Включение jail sshd

Пример использует типичный jail sshd и штатный фильтр sshd. Сначала определите, куда ваша система записывает события SSH: в systemd journal или файл журнала аутентификации.

  1. 1
    Проверьте реальные неудачные входы
    В отдельной тестовой сессии создайте контролируемую неудачную попытку входа либо найдите уже существующую запись. В журнале должен быть исходный IP клиента. Если адреса нет, сначала исправьте журналирование или схему прокси: jail не сможет заблокировать нужный источник.
  2. 2
    Выберите источник журнала
    Если записи SSH доступны через journalctl, используйте backend = systemd, когда этот backend поддерживается установленной версией Fail2ban. Если sshd пишет в файл, используйте файловый backend и укажите фактический logpath. Не копируйте путь к auth.log или secure с другого дистрибутива без проверки.
  3. 3
    Создайте локальное переопределение
    Создайте файл в jail.d, включите jail, назначьте пороги и добавьте только необходимые доверенные адреса. Вариант для journald приведён ниже.
  4. 4
    Перезапустите службу и проверьте jail
    После перезапуска fail2ban-client status sshd должен показать jail без ошибок. Если jail не появился, проверьте журнал самой службы Fail2ban и синтаксис локального файла.
/etc/fail2ban/jail.d/10-local-sshd.local
[sshd]
enabled = true
filter = sshd
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1 198.51.100.25

Адрес 198.51.100.25 в примере — документационный, замените его только подтверждённым адресом аварийного доступа либо удалите строку. Синтаксис времени (10m, 1h) поддерживается современными версиями Fail2ban; при работе со старым пакетом сверяйте документацию именно его версии.

/etc/fail2ban/jail.d/10-local-sshd.local
[sshd]
enabled = true
filter = sshd
backend = polling
logpath = /фактический/путь/к/журналу-аутентификации.log
maxretry = 5
findtime = 10m
bantime = 1h

Второй вариант предназначен для файлового журнала. polling — файловый backend, не зависящий от уведомлений файловой системы, но способный создавать лишние обращения к журналу на нагруженной системе. Некоторые пакеты предлагают и другие файловые backend; выбирайте доступный в вашей версии. Не оставляйте шаблонный путь: Fail2ban должен читать существующий файл с записями sshd.

Перезапускает Fail2ban и выводит состояние jail `sshd`.
sudo systemctl restart fail2ban && sudo fail2ban-client status sshd
Вывод:
Обычно вывод содержит имя jail, число текущих и всех банов, а также список `Banned IP list`. Формат и состав полей могут различаться между версиями.

Защита SSH от перебора не заменяет настройку ключей, ограничение root-входа и проверенный аварийный доступ. Эти меры разобраны в статье «Безопасная настройка SSH: ключи, root и ограничение доступа».

Fail2ban для Nginx, Apache и веб-приложения

Nginx и Apache часто регистрируют HTTP-запрос в access log, но обычная строка access log сама по себе не всегда означает неудачную аутентификацию. Событие входа может записывать приложение, модуль аутентификации, PHP-FPM, reverse proxy или отдельный журнал ошибок. Выбирайте jail только после того, как нашли в журнале реальные строки неудачного входа и IP клиента.

Reverse proxy и адрес клиента

Если перед Nginx или Apache расположен reverse proxy, CDN либо балансировщик, в журнале веб-сервера может оказаться IP прокси, а не клиента. Тогда ban способен затронуть сам прокси или не дать ожидаемого эффекта. Сверьте документацию веб-сервера, прокси и приложения о доверии к заголовкам и журналировании; не включайте jail, пока не подтверждён источник адреса в строке.

Создание jail для событий входа в веб-приложение

Штатные jail для Nginx и Apache могут присутствовать в пакете, но их назначение и имена различаются. Для аутентификации конкретного приложения часто нужен отдельный фильтр.

  1. 1
    Зафиксируйте строку неудачного входа
    Возьмите несколько строк легитимной неудачной аутентификации из фактического журнала. Проверьте, что каждая содержит IP клиента и устойчивый признак ошибки входа, а не только HTTP-статус.
  2. 2
    Проверьте готовый фильтр или создайте локальный
    Сначала посмотрите фильтры, поставленные пакетом, и проверьте их через fail2ban-regex. Если формат приложения не совпадает, создайте новый файл в filter.d с уникальным именем, не меняя штатный фильтр.
  3. 3
    Создайте jail с фактическим logpath
    Свяжите jail с фильтром, включите файловый backend и укажите конкретный журнал приложения или веб-сервера. Подберите осторожные пороги по наблюдаемой активности.
  4. 4
    Проверьте распознавание до реального бана
    Запустите fail2ban-regex на журнале. Результат должен показывать найденные совпадения и адреса. Если совпадений нет или ловятся нормальные запросы, исправьте фильтр, а не снижайте порог.

Сначала определите, кто проверяет пароль. Для HTTP Basic Authentication, выполняемой самим веб-сервером, в поставке Fail2ban часто есть фильтры nginx-http-auth и apache-auth. Перед использованием проверьте наличие соответствующего файла в filter.d и совпадения на фактическом журнале ошибок. Если пароль проверяет форма входа приложения, эти фильтры обычно не подходят: используйте журнал и фильтр приложения, как в примере ниже.

/etc/fail2ban/jail.d/20-nginx-http-auth.local
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
backend = polling
logpath = /фактический/путь/к/журналу-ошибок-nginx.log
maxretry = 5
findtime = 10m
bantime = 1h
/etc/fail2ban/jail.d/20-apache-auth.local
[apache-auth]
enabled = true
filter = apache-auth
backend = polling
logpath = /фактический/путь/к/журналу-ошибок-apache.log
maxretry = 5
findtime = 10m
bantime = 1h
/etc/fail2ban/filter.d/myapp-auth.conf
[Definition]
# Пример предназначен только для строки точного вида:
# myapp-auth authentication failed client=192.0.2.10
# Замените весь шаблон на подтверждённый формат журнала приложения.
failregex = ^myapp-auth authentication failed client=<HOST>\s*$
ignoreregex =
/etc/fail2ban/jail.d/20-myapp-auth.local
[myapp-auth]
enabled = true
filter = myapp-auth
backend = polling
logpath = /фактический/путь/к/журналу-приложения.log
maxretry = 8
findtime = 15m
bantime = 1h

Шаблон фильтра синтаксически использует механизм Fail2ban, но выражение authentication failed и поле client не универсальны: замените их на подтверждённый формат вашего приложения. Пользовательские фильтры храните как новые файлы filter.d/*.conf или локальные переопределения .local, а не редактируйте пакетный фильтр.

Проверяет, какие строки журнала распознаёт пользовательский фильтр.
sudo fail2ban-regex /фактический/путь/к/журналу-приложения.log /etc/fail2ban/filter.d/myapp-auth.conf
Вывод:
Формат результата зависит от версии. Убедитесь, что число совпавших строк ненулевое, извлечены ожидаемые адреса и нормальные запросы не попали в совпадения. Нулевой результат означает, что путь, формат строки или регулярное выражение не совпадают.

Для journald вместо файла используйте backend = systemd, если этот backend доступен в установленном Fail2ban. Условия отбора journal обычно задаются через journalmatch в определении фильтра; подходящие unit и поля нужно брать из реальных записей конкретной службы. logpath для systemd backend не является источником событий. Если установленный fail2ban-regex поддерживает чтение journal, проверяйте фильтр непосредственно командой вида fail2ban-regex systemd-journal <имя-фильтра> и применяйте подходящие условия journalmatch по документации своей версии. Экспорт небольшого фрагмента через journalctl в файл полезен для отдельной проверки failregex, но не подтверждает работу journalmatch и отбора структурированных полей.

Как посмотреть Fail2ban status, banned IP и выполнить unban

Управляйте работающей службой через fail2ban-client. Команды ниже используют документированный интерфейс, но точный формат вывода может отличаться по версиям. Запускайте их с правами, достаточными для доступа к сокету Fail2ban.

Показывает общее состояние Fail2ban и список активных jail.
sudo fail2ban-client status
Показывает состояние jail `sshd`, включая счётчики и обычно список заблокированных адресов.
sudo fail2ban-client status sshd
Запрашивает список IP, находящихся в бане jail `sshd`.
sudo fail2ban-client get sshd banip
Снимает бан с одного IP в jail `sshd`. Замените документационный адрес на проверенный адрес и используйте фактическое имя jail.
sudo fail2ban-client set sshd unbanip 203.0.113.17
Повторно запрашивает список банов после unban.
sudo fail2ban-client get sshd banip
Вывод:
Разблокированный адрес не должен оставаться в списке этого jail. Если он остаётся, проверьте имя jail, формат адреса, права запуска команды и журнал Fail2ban.

Статус jail не доказывает блокировку трафика

IP в Banned IP list означает, что Fail2ban считает адрес заблокированным и выполнил action. Это не заменяет проверку фактического firewall: action может не соответствовать активному стеку, правила могут быть перезаписаны другим менеджером или не обрабатывать нужный IPv4/IPv6-трафик. Проверьте правила штатным инструментом выбранного стека и тестовым подключением из контролируемого источника.

Не используйте unban как постоянное решение: сначала определите, почему заблокирован легитимный адрес — неверный пароль, общий NAT, мониторинг, неверно распознанная строка или ошибочная сеть прокси. Политику firewall и порядок правил рассматривает статья «Firewall сервера: default deny, порядок правил и политика доступа».

Как настроить Fail2ban ignoreip без широких исключений

ignoreip исключает адреса и сети из обработки jail: для них не должен применяться бан. Это не общее правило доступа firewall, а исключение из реакции Fail2ban. Указывайте только loopback и минимально необходимые, документированные адреса — например, один стабильный адрес аварийного доступа, если его исключение действительно оправдано.

/etc/fail2ban/jail.d/00-local-ignoreip.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 198.51.100.25
  • Не добавляйте широкую корпоративную подсеть или весь VPN-диапазон только ради удобства: скомпрометированное устройство из этой сети не будет заблокировано Fail2ban.
  • Не добавляйте IP reverse proxy автоматически. Сначала подтвердите, что журнал содержит адреса клиентов и что jail не пытается блокировать сам прокси.
  • Зафиксируйте владельца, назначение и дату пересмотра каждого исключения. Удаляйте запись, когда аварийный маршрут или адрес перестал использоваться.
  • Если исключение нужно лишь одному сервису, задавайте его в соответствующем jail, а не в [DEFAULT].

Почему Fail2ban не блокирует IP: порядок диагностики

Проверка цепочки от события до firewall

Идите по цепочке последовательно. Переходить к следующему пункту имеет смысл только после подтверждения предыдущего.

  1. 1
    Убедитесь, что служба запущена
    Проверьте состояние службы Fail2ban. Ожидаемый результат — активная служба без ошибок запуска. При ошибке смотрите системный журнал службы: синтаксическая ошибка в локальном файле или отсутствующий action могут помешать загрузке.
  2. 2
    Проверьте включение jail
    Выполните fail2ban-client status и убедитесь, что нужный jail есть в списке. Затем выполните fail2ban-client status <jail>. Если jail отсутствует, проверьте enabled = true, имя секции и сообщения о загрузке конфигурации.
  3. 3
    Найдите исходное событие
    Проверьте фактический файл через просмотр последних строк либо записи journald через journalctl. Ожидаемый результат — реальная строка неудачного входа с IP клиента. Если события нет, проблема находится в сервисе, приложении или его журналировании, а не в Fail2ban.
  4. 4
    Проверьте фильтр на тех же событиях
    Для файлового источника запустите fail2ban-regex с тем же журналом и фильтром. Для journald используйте поддерживаемый установленной версией режим чтения systemd journal и те же условия journalmatch, что применяет фильтр. Экспорт записей в файл проверяет только текстовое регулярное выражение и не подтверждает отбор полей journal. Ожидаемый результат — совпадения только с нужными ошибками и извлечение адреса через <HOST>.
  5. 5
    Сверьте пороги и исключения
    Убедитесь, что число распознанных событий достигло maxretry в интервале findtime, а адрес не входит в ignoreip. Если нормальные пользователи достигают порога, пересмотрите значения на основании журналов, а не отключайте jail полностью.
  6. 6
    Проверьте action и firewall
    После появления IP в статусе jail проверьте, что выбранный action существует в установленном пакете и поддерживает ваш firewall-стек. Для iptables, nftables и firewalld применяются разные action и способы проверки. Не предполагайте, что один action работает на любом Linux-сервере.
  7. 7
    Подтвердите эффект контролируемым тестом
    Из тестового, не доверенного адреса создайте достаточное число безопасных неудачных попыток и проверьте статус jail, правила firewall и результат нового подключения. Не проводите такой тест с единственного административного IP.
Проверяет, запущена ли служба Fail2ban и есть ли недавние сообщения об ошибках запуска.
sudo systemctl status fail2ban --no-pager

Проблема

Jail включён, но бан не появляется

Возможные причины

  • Указан неверный `logpath`, файл недоступен или сервис пишет в journald.
  • Фильтр не соответствует фактическому формату строки.
  • В записи нет реального IP клиента.
  • События не достигли `maxretry` за `findtime` либо адрес исключён через `ignoreip`.

Решение

Проверьте источник записи, затем выполните fail2ban-regex на той же строке и фильтре. Исправьте путь или регулярное выражение, подтвердите IP клиента и только после этого меняйте пороги.

Как избежать

После обновления приложения, веб-сервера или схемы прокси повторно тестируйте фильтр на новых строках журналов.

Проблема

Fail2ban показывает бан, но адрес продолжает подключаться

Возможные причины

  • Action не соответствует активному firewall-стеку.
  • Другой инструмент управляет правилами и перезаписывает результат action.
  • Проверяется другой IP, IPv6 вместо IPv4 или трафик приходит через proxy.
  • Правило firewall находится в цепочке или порядке, не влияющем на нужный поток.

Решение

Проверьте имя action в эффективной конфигурации jail, его файл в action.d, правила активного firewall и фактический адрес источника. Выберите action, документированный для используемого стека, и повторите контролируемый тест.

Как избежать

На одном хосте определите источник управления firewall. Не смешивайте независимые правила UFW, firewalld, ручные iptables/nftables и action Fail2ban без понимания итогового набора правил.

Recidive: дополнительный jail для повторных банов

Jail recidive, если он поставляется вашим пакетом, учитывает повторные баны, записанные Fail2ban, и может назначать более длительную блокировку адресам, которые неоднократно попадают в бан одного или нескольких jail. Это дополнительный слой, а не обязательная настройка для каждого сервера. Его доступность, источник журнала, исходные пороги и action различаются между пакетами и версиями.

/etc/fail2ban/jail.d/30-local-recidive.local
[recidive]
enabled = true
# Перед включением сверить поставляемый filter, logpath/backend и action.
# Пороги подбирать по реальным банам и риску ложной блокировки.

До включения recidive проверьте, что журналы самого Fail2ban доступны, а обычные jail не создают ложных срабатываний. Особенно осторожно оценивайте его при общих NAT-адресах, VPN и прокси: длительный бан общего адреса может затронуть много легитимных пользователей.

Границы защиты от перебора

Fail2ban временно ограничивает повторяющиеся нарушения, уже попавшие в журнал. Он не устраняет уязвимость приложения, не заменяет надёжную аутентификацию и не предотвращает объёмный DDoS: трафик должен дойти до сервера или его канала до того, как локальный action применит блокировку. О защите канала, фильтрации у провайдера и действиях при перегрузке читайте в материале «Защита сервера от DDoS: возможности firewall, фильтрация у провайдера и действия при атаке».

Термины в статье

Allowlist — перечень разрешающих записей или правил: система допускает только те субъекты, объекты, действия или значения, которые им соответствуют.
Brute force — атака, при которой систематически проверяют варианты пароля, ключа или иного секрета через сервис либо по данным для автономной проверки.
Fail2Ban — средство автоматического реагирования на повторяющиеся события в журналах служб, выполняющее заданные действия, обычно временную блокировку IP-адреса, по настроенным фильтрам.
Jail Fail2ban — профиль защиты службы, связывающий фильтр журналов с условиями блокировки и действием, например добавлением адреса в firewall.
iptables — утилита Linux для управления правилами пакетной фильтрации Netfilter через таблицы, цепочки и цели; это не самостоятельный межсетевой экран.
nftables — подсистема Linux и интерфейс управления правилами Netfilter, использующие единый набор правил, выражения, множества и атомарное обновление конфигурации.
Виртуальный патч — компенсирующая защита, блокирующая попытки эксплуатации известной уязвимости правилами WAF, IPS, EDR или иного средства без изменения уязвимого кода.
Журнал аутентификации — набор записей о попытках подтверждения личности, их результатах и данных, необходимых для расследования и контроля доступа.
Межсетевой экран — средство контроля сетевого трафика, разрешающее или блокирующее его по правилам на границе или между сегментами сети.
Ограничение частоты запросов — механизм контроля нагрузки, ограничивающий число запросов от клиента или другого субъекта за заданный интервал.
Список блокировки — набор идентификаторов, адресов или признаков, для которых политика явно запрещает действие, например подключение, доставку сообщения или доступ к ресурсу.
Фильтр Fail2ban — набор регулярных выражений для выявления в журналах событий, учитываемых jail как неудачные попытки или иные нарушения.
Централизованное журналирование — сбор и хранение журналов разных систем в общем сервисе для унифицированного поиска, контроля целостности и анализа.

Вопросы по теме

Все вопросы и ответы

Почему Fail2ban не блокирует IP?

Проверяйте цепочку от события до блокировки. Сначала убедитесь, что служба Fail2ban запущена без ошибок через systemctl status fail2ban --no-pager. Затем выполните fail2ban-client status: нужный jail должен быть в списке, а fail2ban-client status <jail> должен показывать его состояние.

После этого найдите реальные записи неудачного входа в фактическом файле журнала или через journalctl. В строке должен присутствовать IP клиента. Для файлового источника проверьте тот же журнал и фильтр командой fail2ban-regex: совпадения должны относиться только к ошибкам аутентификации и извлекать адрес через <HOST>.

Если фильтр работает, сверьте maxretry, findtime и ignoreip: попыток может быть недостаточно либо адрес исключён. Когда IP появляется в списке банов, но доступ сохраняется, причина обычно в action, несовместимом с активным firewall, перезаписи правил другим инструментом, IPv4/IPv6 или неверно определённом адресе за прокси.

Что показывает команда fail2ban-client status sshd?

Команда показывает состояние jail sshd: его счётчики и обычно список заблокированных адресов. Она помогает убедиться, что jail загрузился после перезапуска и обрабатывается Fail2ban. Однако наличие IP в статусе означает только выполнение action со стороны Fail2ban, а не гарантированную блокировку трафика firewall.

Нужно ли добавлять VPN-подсеть в Fail2ban ignoreip?

Обычно нет. ignoreip исключает адреса и сети из обработки Fail2ban, поэтому скомпрометированное устройство из добавленной VPN-подсети не будет заблокировано. Добавляйте только минимально необходимый документированный адрес, например стабильный адрес аварийного доступа, и задавайте исключение в конкретном jail, если оно нужно лишь ему.

Как снять бан с IP в Fail2ban?

Используйте команду sudo fail2ban-client set sshd unbanip 203.0.113.17, заменив имя jail и документационный IP на фактические. Затем проверьте результат через sudo fail2ban-client get sshd banip. Не используйте unban как постоянное решение: выясните причину бана, например неверный пароль, общий NAT, ошибочный фильтр или прокси.

Как посмотреть список заблокированных IP в Fail2ban?

Выполните sudo fail2ban-client get sshd banip, указав фактическое имя jail вместо sshd. Также список обычно выводится в sudo fail2ban-client status sshd. Этот список показывает адреса, которые Fail2ban считает заблокированными, но для подтверждения эффекта нужно отдельно проверить правила активного firewall и тестовое подключение.

Можно ли читать события Fail2ban из systemd journal?

Да, если установленная версия Fail2ban поддерживает systemd backend. Для этого используют backend = systemd; logpath в таком режиме не является источником событий. Условия отбора обычно задают через journalmatch в фильтре, используя unit и поля из реальных записей конкретной службы.