Чек-лист защиты SSH для Linux-серверов в интернете
Упорядоченный чек-лист для Linux-сервера, который обязан принимать SSH из интернета: что делать в первую очередь, в чём ошибаются большинство списков и что можно отложить.
Как пользоваться этим списком
Чек-листы по харденингу обычно проваливаются по одной причине: они упорядочены по темам, а не по риску. Люди идут сверху вниз и заканчивают время где-то на настройке баннера, так и не добравшись до аутентификации.
Этот — упорядочен. Раздел 1 убирает тот способ, которым Linux-серверы действительно захватывают. Если у вас есть только час — сделайте раздел 1 и остановитесь: он стоит больше, чем всё остальное вместе взятое.
Список предполагает сервер, который обязан принимать SSH с произвольных адресов. Если ваш не обязан — раздел 3 схлопывается в одно правило фаервола, и это хорошая новость.
1. Аутентификация
Захваты начинаются с действующих учётных данных гораздо чаще, чем с непропатченного демона. Этот раздел — вся игра.
- Полностью отключите парольную аутентификацию: PasswordAuthentication no. Это самая ценная строка во всём документе — когда подбирать нечего, атаки подбора не могут добиться успеха в принципе.
- Заодно поставьте KbdInteractiveAuthentication no. Пропустите — и PAM всё ещё предложит парольный запрос, то есть пароли продолжат работать и вы ничего не изменили. Проверяйте через sshd -T, а не чтением файла.
- Поставьте PermitRootLogin в prohibit-password или в no, если root никогда не подключается напрямую. Root — первое имя в любом атакующем списке.
- Защищайте приватные ключи парольной фразой и не держите их на общих машинах. Утёкший ключ ровно так же плох, как утёкший пароль, и утекает он теми же путями: украденный ноутбук, случайный коммит, окружение CI-раннера.
- Ротируйте ключи при уходе людей и проверяйте ~/.ssh/authorized_keys у каждой учётной записи. Старые ключи накапливаются молча, и их никто никогда не убирает.
- Задайте AllowUsers или AllowGroups явным списком. Даже при работе только по ключам это не даст свежесозданной служебной учётке случайно стать доступной снаружи.
2. Сократить доступное снаружи
Второй вопрос после «кто может войти» — «что ещё слушает». Каждый открытый порт — это служба, которую прямо сейчас кто-то проверяет.
- Составьте опись того, что реально слушает: ss -tlnp на хосте, затем проверка с другой сети, что из этого отвечает. Эти два списка совпадают редко.
- Привяжите к localhost те службы, которым не нужно быть удалёнными, — особенно базы. PostgreSQL или Redis на 0.0.0.0 — куда большая проблема, чем SSH когда-либо был.
- Держите фаервол в режиме default-deny: nftables или фронтенд дистрибутива, разрешающий только названное вами.
- Ограничьте адреса источников для SSH, если можете. Если множество легитимных адресов мало и постоянно, это самая дешёвая настоящая мера — и она перестаёт работать в тот момент, когда кто-то уехал.
- Рассмотрите переезд с порта 22 ради снижения шума, понимая, что это снижение шума, а не защита.
3. Автоматическая блокировка неудачных входов
Работа только по ключам убирает риск успешного подбора. Она не убирает трафик, и этот раздел — про трафик.
Боты не знают вашей конфигурации. Они продолжают подключаться, предлагать пароли и получать отказ — каждая попытка стоит TCP-соединения, форка sshd, строки в логе и куска процессора. Предоставленный сам себе открытый сервер поглощает тысячи в сутки, а лог ротируется достаточно быстро, чтобы потерять нужные вам события.
fail2ban — стандартный ответ и разумная отправная точка. Настройте его как следует: bantime -1, ignoreip со своими адресами и мониторинг числа банов, а не состояния службы, потому что отказывает он молча. Его структурные границы — бан отдельных адресов против ботнетов, перебирающих диапазоны; состояние, не переживающее пересборку; отсутствие общих знаний между вашими серверами.
SSH Protector делает ту же работу в виде управляемого агента: баны подсетей, постоянные и восстанавливаемые при загрузке, реальный порт SSH из конфигурации sshd, ваш адрес в белом списке с момента установки, общая репутация по всем защищённым серверам и консоль, отвечающая, работает ли оно.
4. Детали конфигурации sshd
Стоит выставить: по отдельности мелочи, вместе — меньшая поверхность атаки. После каждого изменения запускайте sshd -t и делайте reload, а не restart.
- MaxAuthTries 3 — меньше попыток учётных данных на одно соединение, так что боту нужно больше соединений на то же число догадок.
- Уменьшенные MaxSessions и MaxStartups — ограничивают, сколько неаутентифицированных соединений может быть в полёте одновременно, а именно это и потребляет поток.
- LoginGraceTime 30 — неаутентифицированное соединение не должно висеть открытым две минуты.
- X11Forwarding no и AllowAgentForwarding no, если что-то действительно их не требует. Форвардинг агента, в частности, позволяет скомпрометированной стороне воспользоваться вашим ключом.
- Только современные алгоритмы: уберите легаси-шифры, MAC и методы обмена ключами. Актуальные дистрибутивы имеют разумные значения по умолчанию, так что проверьте, прежде чем копировать сниппет харденинга десятилетней давности: несколько популярных теперь ломают больше, чем чинят.
5. Журналирование и обнаружение
Нельзя расследовать то, что вы не записали, а конфигурация по умолчанию хранит меньше, чем вы ожидаете.
- Убедитесь, что LogLevel у sshd не ниже INFO. В значении QUIET он не записывает отказы аутентификации вообще.
- Увеличьте срок хранения в journald или отправляйте логи за пределы хоста. Локальный журнал скомпрометированной машины — улики, которые атакующий может отредактировать; копия в другом месте — нет.
- Оповещайте о значимом, а не об объёме: успешный вход с незнакомого адреса, строка Accepted password на сервере, который должен работать только по ключам, новая запись в sudoers, новая запись в authorized_keys.
- Периодически и осознанно просматривайте успешные входы. Отказы — это шум; успех, который вы не можете объяснить, — это уже всё.
6. Обновления и восстановление
Последние два пункта, и порядок между ними важен меньше, чем то, что есть оба.
Держите sshd и ядро актуальными — включите автоматические обновления безопасности, если ваш процесс изменений это позволяет. У OpenSSH бывали уязвимости, срабатывающие до аутентификации, и будут ещё, а окно между раскрытием и массовой эксплуатацией сейчас измеряется днями.
Затем бэкапы, с одним свойством, которое важнее всех остальных: хотя бы одна копия, до которой сам сервер не может дотянуться и которую не может удалить. Операторы шифровальщиков ищут цель резервного копирования до того, как что-либо зашифровать, и точка монтирования, в которую скомпрометированный хост может писать, — это не бэкап, а вторая копия, ожидающая уничтожения. И восстановите одну: бэкап, который ни разу не восстанавливали, — это гипотеза, а не план.
FAQ
- Какой шаг защиты SSH самый важный?
- Отключение парольной аутентификации. При PasswordAuthentication no и KbdInteractiveAuthentication no подбирать нечего, поэтому весь класс атак на учётные данные становится не «сложнее», а невозможным. Ничто другое в чек-листе харденинга не даёт столько при таких затратах.
- Стоит ли менять порт SSH в рамках харденинга?
- Стоит ради снижения шума, а не ради защиты. Переезд с 22 обычно срезает объём неудачных входов более чем на 90% и снова делает лог читаемым, но SSH объявляет себя в баннере версии, поэтому любой сканер полного диапазона находит его сразу. Считайте это гигиеной логов, но никогда — мерой контроля.
- Входит ли fail2ban в нормальную защиту SSH?
- Это разумный базовый уровень и намного лучше, чем ничего. Выставьте bantime в -1, внесите свои адреса в ignoreip и мониторьте число банов, а не состояние службы: jail, у которого фильтр перестал совпадать после обновления дистрибутива, выглядит неотличимо от спокойной недели.
- Защищает ли MaxAuthTries от брутфорса?
- Лишь незначительно. Он ограничивает число попыток внутри одного соединения, так что атакующий просто открывает больше соединений; это чуть повышает его затраты, не меняя исхода. Выставить 3 стоит, но защитой это не является — трафик реально снижает блокировка источника на фаерволе.
