защита ssh от брутфорса

OpenSSH PerSourcePenalties: встроенная защита от брутфорса SSH без Fail2Ban

С появлением PerSourcePenalties в OpenSSH 9.8 у администратора появилась встроенная в sshd защита от брутфорса: демон сам штрафует подозрительные адреса — без Fail2Ban, без парсинга логов и без правил firewall. Возникает закономерный вопрос: нужен ли теперь внешний баннер вообще.

Разбираем, как работает openssh persourcepenalties без fail2ban, чем он отличается от Fail2Ban и где его недостаточно, как настроить параметры и безопасно раскатать механизм на парке клиентских серверов — не заблокировав при этом самих себя.

Встроенная защита sshd от брутфорса SSH в OpenSSH без Fail2Ban

Использование openssh persourcepenalties без fail2ban снижает эксплуатационную нагрузку: sshd штрафует подозрительные адреса прямо в памяти процесса, без разбора логов в реальном времени и без внешних демонов, сохраняя эффективность защиты от брутфорса на уровне самого SSH-сервиса.

Содержание

Что такое PerSourcePenalties: встроенная защита sshd от брутфорса с OpenSSH 9.8

PerSourcePenalties — это механизм внутри самого демона sshd, который отслеживает «плохое поведение» подключающихся адресов и временно отказывает им в обслуживании, не привлекая ни внешних служб, ни межсетевого экрана. Демон читает свою конфигурацию из /etc/ssh/sshd_config либо из файла, заданного ключом -f, а учёт нарушений ведёт в памяти процесса-монитора: каждое подозрительное событие добавляет источнику штрафное время, в течение которого новые соединения с этого адреса просто не принимаются.

Ключевой момент — sshd сам классифицирует, что считать нарушением. К штрафуемым событиям относятся аварийное завершение соединения (crash), неудачная аутентификация (authfail), разрыв до прохождения аутентификации (noauth) и превышение grace-времени на вход. Каждая категория имеет собственный вес, а штрафы суммируются и накапливаются по адресу источника или по подсети, а не по конкретному пользователю. Именно поэтому переборщик, гоняющий словарь логинов с одного хоста, упирается в стену быстрее, чем успевает причинить вред.

В отличие от классической схемы «лог → парсер → правило firewall», здесь нет ни задержки на разбор журналов, ни промежуточных демонов. Решение принимает тот же процесс, который и обслуживает соединения, поэтому реакция мгновенная и не зависит от состояния iptables или nftables. Это снимает целый класс проблем с рассинхроном между банлистом и реальными правилами фильтрации.

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

Что такое PerSourcePenalties: встроенная защита sshd от брутфорса с OpenSSH 9.8

PerSourcePenalties vs Fail2Ban: что вы выигрываете и от чего отказываетесь

Сравнивать эти инструменты «в лоб» некорректно — они работают на разных уровнях. Fail2Ban читает журналы и банит адреса через firewall, охватывая любой сервис, который пишет логи: SSH, веб-сервер, почту, панели управления. PerSourcePenalties живёт внутри sshd и закрывает ровно одну поверхность — аутентификацию по SSH. Поэтому правильный вопрос не «что лучше», а «какую задачу мы решаем».

КритерийPerSourcePenaltiesFail2Ban
Где работаетвнутри демона sshdотдельная служба + firewall
Зона покрытиятолько SSHлюбой сервис с логами
Зависимостинетпарсер логов, правила firewall
Реакциянемедленная, в памятипосле разбора журнала
Точка отказаотсутствует, пока жив sshdсломанный фильтр = тихая дыра

Что мы выигрываем при подходе openssh persourcepenalties без fail2ban: исчезает целый слой инфраструктуры. Не нужно следить за тем, что регулярные выражения фильтров совпадают с форматом логов после обновления пакета, не нужно держать актуальными правила firewall, не нужно отлаживать взаимодействие со встроенным экраном на хостингах с урезанными правами. Конфигурация защиты живёт там же, где и конфигурация самого сервиса.

От чего мы отказываемся — от универсальности. PerSourcePenalties не увидит перебор на веб-форме входа, не среагирует на сканер по почтовым портам и не закроет панель управления. Адрес, наказанный за брутфорс SSH, по-прежнему свободно стучится во все остальные сервисы хоста. Это принципиальное ограничение зоны действия, а не недоработка.

По нашему опыту разумная стратегия — не противопоставлять, а разделять обязанности. На узлах, где из публично доступного только SSH (типовые управляющие и приложенческие серверы), встроенного механизма достаточно и он снимает эксплуатационную нагрузку. Там, где наружу торчат веб и почта, Fail2Ban остаётся необходимым, а PerSourcePenalties работает как дополнительный, не пересекающийся с ним рубеж именно для SSH.

PerSourcePenalties vs Fail2Ban: что вы выигрываете и от чего отказываетесь

Настройка PerSourcePenalties: параметры, рабочий конфиг и тюнинг порогов

Настройку мы всегда выносим в отдельный файл каталога drop-in, а не правим основной конфиг. Файлы /etc/ssh/sshd_config.d/*.conf подключаются в начале конфигурации и переопределяют значения из основного sshd_config, поэтому такой файл удобно раскатывать системой управления конфигурациями, не трогая то, что положил пакет. Помните, что имена ключей регистронезависимы, а их аргументы — чувствительны к регистру, а строки, начинающиеся с #, и пустые строки трактуются как комментарии.

Сам механизм управляется тремя сущностями. PerSourcePenalties включает учёт и задаёт веса по категориям событий — за аварийное завершение, за неудачную аутентификацию, за разрыв без аутентификации и за превышение grace-периода; есть также верхняя и нижняя границы штрафа и порог переполнения. PerSourceNetBlockSize определяет, насколько широко штраф распространяется на соседние адреса источника, а PerSourcePenaltyExemptList выводит доверенные сети из-под наказания целиком. Конкретные значения весов и таймингов поставляются вместе с OpenSSH; мы не подменяем их вслепую, а отталкиваемся от профиля нагрузки конкретного узла.

Тюнинг порогов сводится к балансу между агрессивностью и риском ложных срабатываний. На узлах с предсказуемым кругом администраторов веса можно повышать смело. Там, где за одним внешним адресом сидит много легитимных пользователей (NAT офиса, шлюз филиала), агрессивные настройки опасны: штраф по подсети накроет всех сразу. В таких случаях мы расширяем exempt-список, а не ослабляем общий порог.

После любой правки — обязательная проверка синтаксиса и контроль того, какие значения демон применит фактически:

По нашему опыту привычка прогонять sshd -t и sshd -T перед перезапуском экономит больше времени, чем кажется: опечатка в аргументе ловится за секунду, а не превращается в недоступный по SSH сервер.

				
					# /etc/ssh/sshd_config.d/60-itforprof-penalties.conf
# ключ регистронезависим, значение аргумента — нет (prefact_6)
PerSourcePenalties yes
# адреса/подсети, которые никогда не штрафуются
PerSourcePenaltyExemptList <ваша_управляющая_подсеть>
				
			

Как не забанить самого себя при удалённом администрировании парка серверов

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

Доверенные адреса нужно занести в PerSourcePenaltyExemptList ещё до включения механизма, а не после первого инцидента. В список идут управляющие подсети, узлы мониторинга, точки выхода VPN и адреса систем резервного копирования — всё, что обращается к SSH часто и автоматически. Файл исключений мы кладём в тот же drop-in каталог /etc/ssh/sshd_config.d/, чтобы он переопределял основной конфиг централизованно.

Полезно совместить штрафы с ограничением круга входящих. Директива AllowUsers принимает шаблоны имён пользователей, но не понимает числовые идентификаторы пользователей, а AllowGroups работает с именами групп и так же не распознаёт числовые идентификаторы групп. Поэтому списки доступа описываются именами, а не UID/GID — типичная ошибка при копировании правил из чужих шпаргалок.

Не раскатывайте PerSourcePenalties на весь парк одной командой без заранее проверенного exempt-листа — мы сталкивались с тем, что узел мониторинга, опрашивавший SSH по расписанию, сам набирал штраф и попадал под блокировку по подсети, а вместе с ним «слепли» проверки доступности на соседних адресах того же блока. Лечится это тривиально, но в момент инцидента выглядит как массовый отказ, и время уходит на поиск несуществующей сетевой проблемы.

Порядок безопасного развёртывания у нас неизменен: сначала exempt-лист, потом включение штрафов, потом sshd -t, reload и контрольный вход. На парке из десятков серверов этот же порядок просто оборачивается в роль системы управления конфигурацией.

				
					# страховка: вторая сессия открыта, проверяем вход в новой
ssh -o ConnectTimeout=5 admin@server 'echo ok'
# смотрим, не попал ли наш адрес под штраф
sudo sshd -T | grep -i 'persourcepenaltyexempt'
				
			

Когда PerSourcePenalties не заменяет Fail2Ban: защита только SSH, а не nginx, Postfix и панелей

Подход openssh persourcepenalties без fail2ban закрывает аутентификацию по SSH — и только её. Перебор учётных данных на форме входа nginx, попытки подбора по SMTP/IMAP в Postfix, брутфорс админок панелей управления остаются полностью вне зоны его видимости. Механизм встроен в sshd и про другие демоны не знает ничего, поэтому на узлах с публичным веб- и почтовым доступом он не отменяет внешний баннер, а лишь дополняет его на участке SSH.

Важно понимать и второе ограничение: PerSourcePenalties противодействует перебору, но не делает за вас базовое усиление SSH. Усиление — это отдельный набор директив, и здесь стоит держать в голове, что пакет openssh-server в Debian/Ubuntu выставляет ряд значений, отличных от апстрим-умолчаний sshd. В частности, по умолчанию задано KbdInteractiveAuthentication no, X11Forwarding yes и UsePAM yes — и эти значения нужно сознательно подтверждать, а не считать, что «там всё безопасно из коробки».

Отдельно проверяйте проброс соединений, который штрафы вообще не контролируют. По умолчанию включены AllowAgentForwarding, AllowStreamLocalForwarding и AllowTcpForwarding. Если на узле не нужен ни один из видов форвардинга, его стоит явно отключить; PerSourcePenalties здесь ничем не поможет, потому что речь не о переборе, а о возможностях уже аутентифицированной сессии.

Не забывайте и про передачу переменных окружения: переменная TERM принимается всегда, когда клиент запрашивает псевдотерминал, независимо от настроек AcceptEnv. Это нормальное поведение протокола, но при аудите оно регулярно вызывает вопросы — полезно знать заранее, что закрыть его настройкой AcceptEnv не получится.

Вывод, который мы доносим клиентам прямо: PerSourcePenalties — это рубеж против перебора по SSH, а не комплексная защита хоста и не замена усилению конфигурации. Там, где наружу смотрят несколько сервисов, нужны и Fail2Ban для остальных портов, и осознанная ревизия перечисленных умолчаний sshd.

Массовое внедрение на серверах клиентов: чек-лист для IT-аутсорсинга и мониторинг срабатываний

На парке клиентских серверов мы внедряем openssh persourcepenalties без fail2ban шаблоном системы управления конфигурацией, а не руками. Демон читает настройки из /etc/ssh/sshd_config, а наш шаблон кладёт отдельный файл в каталог drop-in, который подключается раньше и переопределяет основной конфиг. В шаблоне держим заголовочный комментарий — строки с # и пустые строки трактуются как комментарии — чтобы по нему было видно версию политики и дату раскатки.

Наш чек-лист перед массовым включением выглядит так:

  • собрать единый exempt-список управляющих сетей, мониторинга, VPN и систем резервного копирования и проверить, что он попал на каждый узел;
  • сгенерировать drop-in файл из шаблона; помнить, что ключи регистронезависимы, а значения аргументов чувствительны к регистру, — это критично при подстановке переменных;
  • прогнать sshd -t на каждом хосте до перезапуска;
  • применять через reload, а не restart, и иметь канал доступа в обход SSH (консоль провайдера) на случай ошибки;
  • раскатывать волнами, начиная с пилотной группы, а не на весь парк сразу.

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

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

Финальный штрих эксплуатации — регулярная ревизия. Раз в цикл обслуживания мы сверяем фактически применённые значения через sshd -T с эталоном в репозитории конфигураций: дрейф настроек на отдельных узлах ловится именно так, а не в момент инцидента.

				
					# срабатывания PerSourcePenalties за сутки
sudo journalctl -u ssh -g 'penalty' --since today
# сколько уникальных источников оштрафовано
sudo journalctl -u ssh -g 'penalty' -o cat | sort -u | wc -l
				
			

Первоисточники и документация

Для углубления и самостоятельной проверки параметров:

— официальное описание директив PerSourcePenalties, PerSourceNetBlockSize и PerSourcePenaltyExemptList — в man-странице sshd_config (Ubuntu);

— эталонная реализация механизма штрафов — в исходных кодах OpenSSH (openssh-portable);

— базовый протокол аутентификации SSH задан в RFC 4252.

Итог

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

Ответы на часто задаваемые вопросы по теме статьи.

Основное преимущество — в простоте и надёжности. Fail2Ban читает системные логи и выполняет внешние команды (iptables/nftables), то есть зависит от парсера и правил файрвола. PerSourcePenalties живёт внутри самого sshd и ведёт учёт нарушений в памяти процесса, без задержки на разбор журналов и без промежуточных демонов — меньше движущихся частей, меньше точек отказа.
PerSourcePenalties доступен начиная с OpenSSH 9.8, поэтому в Ubuntu он есть с версии 24.10 и новее (в 24.04 LTS с OpenSSH 9.6 этого механизма ещё нет — там опираются на ключи и ограничение доступа). Создайте отдельный файл в /etc/ssh/sshd_config.d/, например 60-penalties.conf, добавьте PerSourcePenalties yes и при необходимости PerSourcePenaltyExemptList для доверенных подсетей. Файлы из этого каталога подключаются раньше основного sshd_config и переопределяют его. После правки проверьте синтаксис sshd -t, примените через systemctl reload ssh и убедитесь, что вход работает из второй сессии.
Только если наружу смотрит только SSH. PerSourcePenalties закрывает перебор только по SSH, поэтому на узлах с публичным веб- или почтовым доступом Fail2Ban остаётся нужен для остальных портов. Если же из публичного только SSH и вы отключили парольный вход (PasswordAuthentication no, только ключи) — встроенного механизма достаточно, а Fail2Ban можно оставить разве что как источник алертов для SIEM, а не как основной механизм блокировки.
Штрафуются четыре класса событий: аварийное завершение соединения (crash), неудачная аутентификация (authfail), разрыв до прохождения аутентификации (noauth) и превышение grace-времени на вход. Категории имеют разные веса, штрафы суммируются по адресу источника или по подсети (параметр PerSourceNetBlockSize), а доверенные сети выводятся из-под наказания через PerSourcePenaltyExemptList.

Константин Тютюнник — ведущий инженер DevOps в IT For Prof. Специализируется на харденинге Linux-серверов и архитектуре безопасного удалённого доступа. Имеет более 10 лет опыта в защите высоконагруженных систем от брутфорс-атак и DDoS.

Наши инженеры помогут аудировать текущую конфигурацию SSH и внедрить современные методы защиты. Закажите администрирование серверов под ключ для повышения отказоустойчивости вашей инфраструктуры.