Зачем вообще делать SSH hardening на VDS
На публичном сервере SSH почти сразу попадает под сканирование и перебор. Даже если пароль «сложный», атаки создают шум в логах, увеличивают нагрузку на аутентификацию и повышают риск человеческих ошибок (например, оставленная тестовая учётка или лишний метод входа).
SSH hardening — это не один «секретный тумблер», а набор мер, которые усиливают друг друга: ключи вместо паролей, минимизация доступных учёток, ограничения по источникам, понятные исключения через Match и автоматическая реакция на брутфорс уровня Fail2ban/sshguard.
Дальше — практичный чеклист с рабочими примерами: доступ админам, доступ CI, SFTP для подрядчика и проверки, которые помогают не словить локап.
Базовая стратегия: уменьшаем поверхность атаки
Весь hardening удобно разложить на четыре слоя:
Кто может логиниться: ограничиваем пользователей и группы (ключи:
AllowUsers,AllowGroups).Как логиниться: отключаем парольную аутентификацию и root-вход, используем ключи (в идеале — аппаратные).
Откуда логиниться: по возможности ограничиваем источники фаерволом и/или настройками SSH.
Что делать при переборе: баним агрессоров (Fail2ban или sshguard) и уменьшаем окно для угадывания.
Смена порта сама по себе не «защита», но может быть частью снижения шума. Основу всё равно делают ключи и строгая политика доступа.
Если вы только выбираете площадку под проекты, берите сервер, где есть консоль/рескью и быстрые снапшоты: это существенно снижает риск при hardening. Для рабочих окружений обычно удобнее VDS, где вы полностью контролируете фаервол и системные политики.

Подготовка: аварийный «парашют» перед изменениями
Перед правками SSH на удалённой машине держите возможность отката. Минимальный набор:
Откройте вторую SSH-сессию и не закрывайте, пока не проверите вход заново.
Убедитесь, что у вас есть доступ к консоли/рескью-режиму в панели сервера.
Сделайте копию
/etc/ssh/sshd_configи (если есть) файлов в/etc/ssh/sshd_config.d/.
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F-%H%M)
Почти на всех системах можно валидировать конфиг без рестарта демона:
sudo sshd -t
И полезно посмотреть «эффективную» конфигурацию с учётом include и дефолтов:
sudo sshd -T | head
Если вы параллельно планируете ограничивать доступ по сетям, загляните в отдельный материал про практичную связку SSH и фаервола: как ограничить SSH фаерволом без само-блокировки.
Ключи вместо пароля: отключаем password authentication
Запрос disable password authentication часто ищут как «серебряную пулю». Это действительно одна из самых сильных мер против массового брутфорса, но только при условии, что у вас уже настроены ключи и есть аварийный доступ (консоль/второй админский ключ).
1) Генерируем ключ и добавляем на сервер
На клиенте (рабочей машине):
ssh-keygen -t ed25519 -a 64 -f ~/.ssh/id_ed25519_vds
Добавьте публичный ключ в ~/.ssh/authorized_keys нужного пользователя на сервере. Если используете ssh-copy-id:
ssh-copy-id -i ~/.ssh/id_ed25519_vds.pub user@server
2) Ужесточаем sshd_config
Типовой базовый блок (проверяйте совместимость с вашей схемой PAM/2FA):
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
PubkeyAuthentication yes
AuthenticationMethods publickey
PermitRootLogin no— root больше не точка входа; права повышаем через sudo.PasswordAuthentication no— выключает парольный вход.KbdInteractiveAuthentication no— обычно отключает интерактивные методы, которые часто забывают закрыть.AuthenticationMethods publickey— фиксирует требование ключа, полезно при наличии дополнительных auth-модулей.
Если вы используете 2FA через PAM-модули, не переносите этот блок «как есть»: сочетание
UsePAM,KbdInteractiveAuthenticationиAuthenticationMethodsнужно согласовать с вашей схемой аутентификации, иначе можно отрезать доступ.
AllowUsers/AllowGroups: кто именно может входить
Ограничение пользователей — вторая «сильная» мера. Она делает невозможным вход под случайными/типовыми логинами и снижает риск, что забытая сервисная учётка станет входной дверью.
Пример строгой политики:
AllowUsers admin deploy
В более жёстком варианте можно привязать пользователя к источнику (IP):
AllowUsers admin@203.0.113.10 deploy@198.51.100.25
Если админов много, обычно проще управлять группой:
AllowGroups sshadmins
И добавлять людей в группу на уровне ОС (это удобнее, чем постоянно править конфиг SSH).
sshd_config Match: разные политики для админа, деплоя и SFTP
Match — один из самых недооценённых инструментов hardening: вы задаёте безопасные значения «по умолчанию», а затем точечно меняете поведение для конкретных ролей без ручного «комментирования туда-сюда».
Пример цели:
Админам — shell и (при необходимости) форвардинг.
Пользователю деплоя — ключи, без интерактивности и туннелей.
Подрядчику — только SFTP в chroot, без shell.
Базовый каркас
# Глобально
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
GatewayPorts no
# Админы: можно форвардинг (например, для доступа к внутренним сервисам)
Match User admin
AllowTcpForwarding yes
# Деплой: без форвардинга, без PTY (если интерактив не нужен)
Match User deploy
AllowTcpForwarding no
PermitTTY no
# SFTP-пользователь: только SFTP и изоляция
Match User contractor
ForceCommand internal-sftp
ChrootDirectory /srv/sftp/%u
AllowTcpForwarding no
X11Forwarding no
PermitTTY no
Критично: Match применяется сверху вниз, и параметры внутри блока действуют до следующего Match. Поэтому располагайте блоки аккуратно и избегайте слишком «широких» условий в начале.
Проверяем итоговые параметры для конкретного пользователя
Команда покажет «финальные» значения с учётом Match:
sudo sshd -T -C user=contractor,host=server,addr=203.0.113.10 | sed -n '1,120p'
Fail2ban vs sshguard на VDS: что выбрать
Оба инструмента решают одну задачу: автоматически блокируют IP, которые слишком активно ошибаются при логине. Разница в подходе и масштабе.
Fail2ban: гибкость и экосистема
Плюсы Fail2ban:
Много готовых jail’ов не только для SSH, но и для веб-сервисов и почты.
Гибкая настройка условий, таймингов, исключений, интеграций с фаерволом.
Хорошо подходит, если хотите единую политику блокировок для нескольких сервисов.
Минусы:
Чуть больше зависимостей и «площадь» конфигурации.
Нужно осмысленно настроить источник логов (journald или файлы), иначе легко получить ситуацию «не банит».
sshguard: проще и легче
Плюсы sshguard:
Обычно проще стартовая настройка, меньше сущностей.
Отличный вариант, если защищаете в основном SSH и не хотите «комбайн».
Минусы:
Меньше готовых сценариев для разных сервисов и более скромная экосистема правил.
Тонкая настройка иногда менее удобна, чем у Fail2ban (зависит от дистрибутива и фаервола).
Один сервер и главная боль — SSH-брутфорс: sshguard часто закрывает задачу быстро. Нужна единая политика банов для SSH плюс веб/почта: Fail2ban обычно практичнее.
Пример: минимальный Fail2ban для SSH
Во многих дистрибутивах достаточно включить jail для sshd и выставить разумные лимиты:
# /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
mode = aggressive
bantime = 1h
findtime = 10m
maxretry = 5
Проверка статуса:
sudo fail2ban-client status
sudo fail2ban-client status sshd
Если Fail2ban нужен не только для SSH, может пригодиться разбор типовых jail’ов для почтовых сервисов: Fail2ban для Postfix/Dovecot: какие jail включать и как не словить ложные баны.
Пример: sshguard и быстрые проверки
После включения sshguard проверьте, что блокировки реально появляются в логах:
sudo systemctl status sshguard
sudo journalctl -u sshguard --no-pager | tail -n 80
Если банов нет, чаще всего проблема в источнике логов (sshd пишет в journald, а sshguard ждёт файл) или в интеграции с механизмом фаервола.

Порт SSH, port knocking и безопасные альтернативы
Скрывать SSH «от всего интернета» хочется всем. Важно понимать: ни смена порта, ни port knocking не заменяют ключи и ограничения пользователей, но могут снизить шум и количество случайных попыток.
Смена порта: только как снижение шума
Если решаете менять порт, делайте это без потери доступа:
Сначала откройте новый порт в фаерволе и проверьте вход.
Только потом закрывайте старый.
Не забывайте про мониторинг: метрики и алерты могут быть завязаны на 22.
Port 2222
Почему port knocking часто не стоит сложности
Port knocking добавляет скрытность, но увеличивает сложность и количество движущихся частей. На VDS это нередко приводит к сюрпризам при смене IP, роуминге, NAT и при разборе инцидентов «почему я не могу зайти».
Практичные альтернативы port knocking
Ограничение источников фаерволом: разрешить SSH только с офисного IP, с VPN или с бастиона.
SSH bastion / jump host: один укреплённый вход, а дальше доступ во внутренний контур.
Временное окно доступа: открыть SSH из конкретного IP на короткий период по операционной процедуре, затем закрыть.
Дополнительные меры, которые реально помогают
Отключаем лишние возможности и ужесточаем сессии
Для большинства серверов не нужен X11 и часть «удобств», которые расширяют поверхность атаки:
X11Forwarding no
AllowAgentForwarding no
PermitUserEnvironment no
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 30
MaxAuthTries 3
MaxSessions 3
Если агент-форвардинг вам всё же нужен (часто бывает при jump host), включайте его точечно через Match для админов, а не глобально.
Криптополитики: закрепляем только при необходимости
OpenSSH по умолчанию обычно достаточно безопасен на свежих дистрибутивах. В старых системах иногда есть смысл явно закрепить алгоритмы, но это легко превращается в «сам себе DDoS», если у вас есть старые клиенты/автоматизации. Проверяйте совместимость заранее.
Посмотреть текущий effective-конфиг сервера:
sudo sshd -T | grep -E 'ciphers|macs|kexalgorithms|hostkeyalgorithms'
И поддерживаемые алгоритмы на клиенте:
ssh -Q cipher
ssh -Q kex
ssh -Q mac
ssh -Q key
Типовые рецепты Match для эксплуатации
1) CI/CD пользователь: ключи, без интерактива, без туннелей
Match User deploy
PasswordAuthentication no
PubkeyAuthentication yes
PermitTTY no
AllowTcpForwarding no
X11Forwarding no
Если деплой идёт через git+ssh, PTY обычно не нужен, но конкретные пайплайны бывают разными. Прогоните тест деплоя до закрытия «лишних» возможностей.
2) SFTP-only доступ для обмена файлами
Связка internal-sftp и ChrootDirectory надёжна, но требует корректных прав на каталоги: chroot обычно должен принадлежать root, а запись делайте в подкаталоги.
Match User sftpuser
ForceCommand internal-sftp
ChrootDirectory /srv/sftp/%u
AllowTcpForwarding no
X11Forwarding no
PermitTTY no
3) Админ-доступ только из фиксированного IP
Можно комбинировать с AllowUsers или использовать Match Address:
Match User admin Address 203.0.113.10
AllowTcpForwarding yes
Если IP нестабилен, чаще надёжнее решать задачу через VPN/бастион или фаервол с временными правилами.
Проверка после изменений: чтобы не словить локап
Практичный порядок после правок:
Провалидируйте конфиг:
sudo sshd -t.Сделайте reload (обычно безопаснее, чем restart при критичном доступе):
sudo systemctl reload ssh
На некоторых системах имя сервиса sshd:
sudo systemctl reload sshd
Проверьте новый вход отдельной сессией и посмотрите логи:
sudo journalctl -u ssh --no-pager | tail -n 80
sudo journalctl -u sshd --no-pager | tail -n 80
Если используете Fail2ban/sshguard, убедитесь, что вы сами не попали под бан во время тестов (особенно при смене порта или при подключении через NAT).
Короткий итог: минимум мер, максимум эффекта
Ключи и запрет паролей:
PasswordAuthentication noплюсAuthenticationMethods publickey.Запрет root-входа:
PermitRootLogin no.Ограничение учёток:
AllowUsersилиAllowGroups.Разные политики через
Match(admin, deploy, sftp-only).Автобан: Fail2ban или sshguard — по масштабу и привычкам.
Скрытность (порт/port knocking) — опционально для снижения шума, не основная защита.
Если внедрите хотя бы первые четыре пункта, риск и количество «случайных» проблем с SSH на VDS заметно снижаются, а сопровождение становится проще: правила прозрачные, исключения оформлены через Match, и вы точно знаете, кто и как может подключаться.


