Почему Fail2ban не блокирует перебор SSH
Если Fail2ban не блокирует SSH, проверьте всю цепочку: записывает ли sshd ошибку, читает ли её нужный jail, совпадает ли строка с фильтром и закрывает ли firewall фактический порт. Ни переезд SSH с 22, ни сама запись в журнале не объясняют проблему без этой проверки. Дальше — порядок диагностики.
Что именно должен сделать Fail2ban
Fail2ban не перехватывает SSH-сессию на сетевом уровне и не анализирует каждый пакет. Он получает журналируемое событие об ошибке аутентификации, сопоставляет строку с фильтром, считает совпадения для источника и запускает действие блокировки. В этой цепочке четыре отдельные точки отказа: jail выключен; выбран не тот источник журнала; строка не подошла фильтру; правило firewall применилось не к тому порту или интерфейсу. Поэтому строка «Failed password» в журнале доказывает только то, что попытка дошла до sshd и была записана. Она не доказывает, что jail прочитал эту запись или что firewall заблокировал соединение. Я разбираю этапы по очереди, иначе легко принять работающий процесс за работающую защиту. Это не повод объявлять Fail2ban бесполезным: сначала надо назвать звено, которое не сработало.
Первым делом выясните, куда sshd пишет сообщения именно на этом сервере. На одних системах это файл вроде /var/log/auth.log или /var/log/secure, на других — systemd journal; расположение и название службы зависят от дистрибутива и настройки. У Fail2ban есть файловые backend и systemd; для backend systemd документация отдельно говорит, что logpath не задают, потому что источник — журнал. Если jail следит за файлом, которого нет или в который sshd уже не пишет, совпадений не будет. Если jail читает journal, но фильтр выбирает не те записи, эффект тот же. Проверяйте фактический поток событий, а не привычный путь из старого руководства. Гадать по знакомому пути — диагностика с плохой точностью. И не объясняйте обычное несовпадение формата «нестандартной кодировкой», пока не увидели конкретную строку и результат проверки фильтра.
- Проверьте, включён ли jail sshd.
- Сверьте источник журнала с backend.
- Сопоставьте реальные записи с фильтром.
- Проверьте действие firewall отдельно.
Нестандартный порт: фильтр тут ни при чём
В условном примере для ООО «Тополь Групп» sshd слушает TCP-порт 2222, а действие jail настроено на стандартную службу ssh. Это учебный сценарий, а не отчёт о клиентском инциденте. Ошибка здесь не в том, что фильтр «видит только порт 22»: фильтр sshd распознаёт сообщения sshd, а настройка port задаёт порт для действия блокировки. Если firewall rule закрывает стандартный порт, а демон принимает соединения на другом, в журнале могут появляться совпадения и срабатывать jail, но повторное подключение к фактическому порту останется доступным. В базовой конфигурации Fail2ban для jail sshd указан port = ssh; при нестандартном порте надо проверить, что действие использует тот же порт, который задан параметром Port в конфигурации sshd. Именно это я проверяю в первую очередь, когда счётчик срабатываний растёт, а доступ не пропадает.
Есть ещё ловушка в самих сообщениях: число после слов from … port обычно обозначает исходный порт клиента, а не порт sshd на сервере. Подставить его в конфигурацию firewall — значит закрывать не ту сторону соединения. Для условного примера изменение только нужной настройки jail выглядит так: ``ini\n[sshd]\nenabled = true\nport = 2222\n`` Это фрагмент для проверки, а не универсальная готовая конфигурация: надо сверить синтаксис и включение jail в установленной версии, используемый backend и тип действия. Правило должно ограничить новые подключения к серверному порту sshd. После изменения я проверяю не только вывод Fail2ban, но и правило firewall, а затем повторяю контрольную проверку с отдельного источника, который не находится в списке исключений. Административную сессию при этом сохраняю. Если нужен дополнительный контекст по настройке фильтров на других службах, см. разбор правил Fail2ban для Zimbra.
Почему редкий перебор ускользает от порога
Три настройки jail часто путают между собой. maxretry задаёт число распознанных ошибок до блокировки; findtime — окно, в котором они считаются; bantime — срок блокировки. Fail2ban банит источник, если тот набрал установленное число ошибок за заданное окно. Если попытки одного адреса приходят реже, чем позволяет это окно, порог не будет достигнут. Поэтому совет «уменьшить интервал между попытками» бессмысленен: администратор не управляет интервалом атакующего. Увеличение findtime может помочь обнаруживать редкие попытки с одного источника, но при этом возрастает шанс накопить обычные ошибки легитимного пользователя. Я выбираю значения по журналам и последствиям ложной блокировки, а не копирую числа из чужого jail.local. Универсального набора для всех серверов нет.
Блокировка тоже привязана к тому источнику, который видит журнал. Если перебор распределён между множеством адресов и каждый делает меньше попыток, чем maxretry, jail не объединит их автоматически в одного «бота». Так устроено ограничение по источнику, и Fail2ban не заменяет глобальный анализ трафика. Отдельный случай — вход с уже украденным ключом или известными учётными данными: успешная аутентификация не равна серии ошибок, поэтому jail не обязан заблокировать такой сеанс. Это не означает, что любой медленный или распределённый сценарий непременно пройдёт; это означает, что нельзя оценивать защиту только по числу банов. Я смотрю, какие источники и события вообще попадают в журнал, и сопоставляю это с политикой доступа.
- `maxretry` — порог ошибок.
- `findtime` — временное окно.
- `bantime` — длительность блокировки.
Как проверить jail и совпадения фильтра
Начните со статуса службы и конкретного jail: sudo fail2ban-client status, затем sudo fail2ban-client status sshd. Вторая команда показывает состояние jail и его текущие счётчики; нулевое число банов само по себе не объясняет причину. Если jail отсутствует, ищите проблему в его включении или разборе конфигурации. Если jail есть, но число ошибок не растёт, переходите к источнику событий и фильтру. Проверить, как фильтр сопоставляет реальные строки файла, можно командой sudo fail2ban-regex /путь/к/журналу sshd, заменив пример пути на фактический файл. Если используется журнал systemd, у fail2ban-regex есть источник systemd-journal; такая проверка зависит от поддержки systemd в установленном пакете. Это диагностика распознавания строк, а не доказательство, что firewall action отработал.
Дальше разбирайте конкретный образец: виден ли в нём адрес источника, совпала ли запись с фильтром, попала ли она в период findtime, достигнут ли maxretry. Для журнала и файла проверяйте корректность времени и ротации, но не предполагайте, что любая ротация автоматически оставляет Fail2ban на пустом файле. Важны выбранный backend, реальное расположение источника и настройки конкретного дистрибутива. После совпадения проверьте статус jail повторно и убедитесь, что нужное действие firewall появилось для фактического порта SSH. Если действие запускается без ошибки, но соединение всё ещё принимается, уже изучайте правила firewall, порядок их применения и возможный внешний сетевой фильтр. Так я отделяю ошибку чтения логов от ошибки блокировки, вместо того чтобы наугад переписывать регулярное выражение. Проверьте и список исключений ignoreip: адрес из этого списка Fail2ban не банит, это штатное поведение. Если контроль идёт с адреса администратора, такой тест ничего не скажет о работе блокировки. Не добавляйте широкие диапазоны «на всякий случай»: это исключит из реакции и другие адреса внутри диапазона. Сначала выясните, какой источник sshd записал в журнал; за NAT это может быть адрес шлюза. Список исключений — решение о доверии, а не способ исправить фильтр.
- `fail2ban-client status sshd` — состояние jail.
- `fail2ban-regex` — тест фильтра на журнале.
- Firewall — отдельная проверка действия.
Что защищает SSH помимо Fail2ban
Fail2ban полезен как автоматическая реакция на повторные ошибки, но его задача узкая. Он не проверяет, кому вы выдали ключ, не запрещает слабые учётные записи и не подтверждает личность после успешной аутентификации. Я начинаю укрепление SSH с учётных записей и способа входа: персональные аккаунты вместо общей учётки, отдельный учёт действий, проверенные ключи и закрытый парольный вход там, где ключевой доступ уже настроен и испытан. Не выключайте парольную аутентификацию по одному примеру из статьи: сначала откройте вторую проверенную сессию и убедитесь, что есть запасной способ доступа. В OpenSSH доступны директивы PasswordAuthentication, PermitRootLogin, AllowUsers и AuthenticationMethods, но их сочетание зависит от вашей схемы входа. Двухфакторную схему надо настраивать и проверять как отдельный механизм; один Fail2ban её не включает.
Ограничение SSH на firewall по доверенным адресам снижает число доступных источников подключения, если адреса действительно стабильны и вы предусмотрели удалённое администрирование. Для смены правил нужен проверенный путь восстановления: иначе администратор может заблокировать собственный доступ быстрее любого переборщика. Затем включите обновление sshd и ОС по принятому графику, храните журналы достаточно долго для разбора и следите за успешными входами, а не только за неудачными. Внутри сайта есть отдельный разбор проверки SSH host key, а здесь фокус уже: почему Fail2ban не банит и как проверить его цепочку от записи до firewall. Так вы не требуете от одного инструмента решать задачи управления ключами, учётными записями и сетевыми правилами сразу. И не называете защиту надёжной, пока не проверили реальный результат. Для небольшой инфраструктуры важнее регулярно разбирать необычные успешные входы, чем собирать десяток несвязанных средств мониторинга. Назначьте ответственного и понятный порядок реакции: проверить учётную запись, отозвать скомпрометированный ключ, сохранить журнал и изменить доступ. Автоматический бан этих действий не отменяет.
Частые вопросы
Почему Fail2ban видит ошибки SSH, но не банит?
Проверьте, что jail включён, читает нужный журнал и распознаёт записи. Затем проверьте порог и действие firewall на фактическом серверном порту.
Нужно ли менять фильтр, если SSH слушает нестандартный порт?
Не обязательно. Обычно проверяют порт в действии блокировки и источник журнала; стандартный фильтр sshd распознаёт сообщения sshd.
Как Findtime влияет на редкий перебор?
Ошибки одного источника считаются в окне findtime. Если порог maxretry не достигнут в этом окне, блокировки не будет.
Чем проверить фильтр Fail2ban?
Командой fail2ban-regex на фактическом файле журнала или на systemd journal, если пакет поддерживает этот источник.
Защищает ли Fail2ban от входа с украденным ключом?
Сам по себе — нет: успешный вход не является серией ошибок для jail. Нужны управление ключами, учётными записями и проверка успешных входов.
Источники
- Fail2Ban: jail.conf — Проверены параметры maxretry, findtime и bantime, backend systemd, значение port в jail sshd и правило не задавать logpath для systemd backend. https://github.com/fail2ban/fail2ban/blob/master/config/jail.conf
- Fail2Ban: fail2ban-regex(1) — Проверены синтаксис команды, имя фильтра sshd и источники журнала: файл или systemd-journal. https://github.com/fail2ban/fail2ban/blob/master/man/fail2ban-regex.1
- Fail2Ban: fail2ban-client(1) — Проверена команда status <JAIL> для получения состояния конкретного jail. https://github.com/fail2ban/fail2ban/blob/master/man/fail2ban-client.1
- Fail2Ban: фильтр sshd — Проверены шаблоны распознавания ошибок sshd, захват адреса источника и примечания к режиму фильтра. https://github.com/fail2ban/fail2ban/blob/master/config/filter.d/sshd.conf
- OpenBSD: sshd_config(5) — Проверены директивы Port, PasswordAuthentication, PermitRootLogin, AllowUsers и AuthenticationMethods. https://man.openbsd.org/sshd_config



