Короткий ответ
Соберите один поздний drop-in /etc/ssh/sshd_config.d/99-hardening.conf: PermitRootLogin no, PasswordAuthentication no, KbdInteractiveAuthentication no, PubkeyAuthentication yes, AllowUsers admin, MaxAuthTries 3, LoginGraceTime 30. Эффективность проверяйте sshd -T, не глазами. Второе окно ssh -o BatchMode=yes admin@10.0.20.10 до reload. Консоль BMC открыта. Это сборка политики; точечные инциденты — root SSH, боты, ключ.
Хост host.example.
Симптомы и как отличить
Нужна эта инструкция, если ставите baseline на новый узел или сверяете парк. Если SSH уже не принимает коннект — сначала доступность порта (сетевой раздел linux), не hardening.
Возможные причины «конфиг не тот»
50-cloud-init.confпозже/раньше по лексике.Matchв основном файле.- Include не подхватывает ваш файл (права, имя).
- Два sshd.
- ansible каждый раз перетирает.
Диагностика
sudo sshd -t
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|kbdinteractive|pubkeyauthentication|allowusers|allowgroups|maxauthtries|logingracetime|x11forwarding|allowtcpforwarding|clientalive|authenticationmethods|port'
ls -l /etc/ssh/sshd_config.d/
sudo grep -RniE '^(Match|PermitRootLogin|PasswordAuthentication|AllowUsers)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/
systemctl status ssh.service ssh.socket --no-pagerMatch-тест с адреса бота и с LAN:
sudo sshd -T -C user=admin,host=host.example,addr=10.0.20.11 | grep passwordauthentication
sudo sshd -T -C user=admin,host=host.example,addr=1.2.3.4 | grep passwordauthenticationРешение
1. Пользователь и ключ
admin в группе sudo, ключ в authorized_keys 600, каталог 700. Проверка BatchMode. Не начинайте с PasswordAuthentication no без ключа.
2. Drop-in
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
AllowUsers admin
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
ClientAliveInterval 30
ClientAliveCountMax 3
AuthorizedKeysFile .ssh/authorized_keys
EOF
sudo sshd -t && sudo systemctl reload sshAllowTcpForwarding no ломает ssh -L с этой машины. Если туннели нужны админам — yes или local. Не оставляйте forwarding «всем» без политики.
AllowUsers admin — единственное имя. Добавление deploy — явная правка.
3. Источник, не только sshd
UFW allow 22 с CIDR. Fail2Ban — слой: jail. Полный хост: baseline.
4. Banner и версия
Не полагайтесь на смену порта и DebianBanner no как защиту. Можно уменьшить шум, не модель угроз.
5. Откат
Консоль: rm 99-hardening.conf или вернуть из git, sshd -t, reload ssh. Снимок VM перед массовой выкладкой.
Дополнительные параметры, которые стоит явно зафиксировать (после проверки клиентов). PermitEmptyPasswords no — дефолт, но проверьте sshd -T. MaxSessions и MaxStartups режут наводнение соединений; слишком жёсткий MaxStartups на jump-хосте с автоматикой мешает ansible — подберите, не копируйте «10:30:60» вслепую без теста параллелизма.
DebianBanner no и кастомный Banner — юридический warning, не security control. Баннер не должен светить версию приложения.
TrustedUserCAKeys не включайте, пока нет процесса выдачи/отзыва сертификатов и KRL. Иначе получите вход по чужому CA с ноутбука подрядчика.
AuthorizedKeysCommand (sss, opk) — тогда файловые authorized_keys могут быть пусты; hardening всё равно нужен (PermitRootLogin, пароль, AllowUsers/AllowGroups). Сверьте sshd -T | grep authorizedkeyscommand.
Drop-in имена: 00- ранние, 99- поздние. Cloud-init любит 50-cloud-init.conf и 60-cloudimg-settings.conf. Ваш файл должен быть лексически последним среди тех, что задают те же ключи.
Проверка без lockout: sshd -t ловит синтаксис, не логику AllowUsers. Логику ловит вторая сессия. Держите старую, пока новая true.
Клиентский ~/.ssh/config для admin:
Host host.example
HostName 10.0.20.10
User admin
IdentityFile ~/.ssh/admin-host-example-2026
IdentitiesOnly yesИначе агент переберёт ключи и упрётся в MaxAuthTries.
Журналирование sshd: LogLevel VERBOSE даёт fingerprint ключа в Accepted — полезно для IR, чуть шумнее. На 22.04/24.04 это приемлемо для admin-хоста. Не DEBUG3 на проде постоянно: диск и секреты в логах handshake.
Subsystem sftp оставьте internal-sftp если нужен SFTP; chroot — отдельная задача. Не отключайте sftp «для hardening», если бэкапы им живут — ограничьте Match user backup.
Проверка Match Group vs AllowUsers: если оба заданы, должны пересекаться. Иначе вход нулевой. Тестируйте каждого пользователя из политики, не только admin.
Капча «сменили порт на 2222 и успокоились»: порт в drop-in Port 2222 требует UFW allow 2222 и обновления fail2ban port. Легко забыть и отрезать себя. Смена порта не в минимуме hardening, если не закрыли 22 в SG.
Документируйте эффективный sshd -T в git (без секретов). Diff при drift cloud-init.
На 24.04 после reload проверьте, что ssh.socket не держит старый Listen. ss -tlnp | grep ssh должен совпасть с Port в sshd -T. Если слушаете 22 и 2222 одновременно — это два входа, оба в UFW и в матрице, не «забытый дефолт».
Include в основном sshd_config должен быть Include /etc/ssh/sshd_config.d/*.conf. Не удаляйте его, иначе drop-in мёртв.
sshd -T на 24.04 всё ещё бинарь OpenSSH; не ищите ssh -T. Ошибки синтаксиса смотрите stderr sshd -t до reload.
Как проверить, что проблема устранена
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|allowusers|maxauthtries|authenticationmethods'
ssh -o BatchMode=yes admin@10.0.20.10 true
ssh -o BatchMode=yes root@10.0.20.10 true; echo root:$?
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no -o BatchMode=yes admin@10.0.20.10 true; echo pass:$?Ожидание: permitrootlogin no, passwordauthentication no, allowusers admin, maxauthtries 3. admin ключ 0. root и пароль — отказ.
Если не помогло
- Параметр не меняется: файл после
99-по алфавиту, или Match. AllowUsersотрезалubuntucloud — добавьте временно второе имя или консоль.- socket activation:
systemctl restart ssh.socketтолько если понимаете unit 24.04. - GSSAPI снова включает интерактив: выключите явно если не нужен Kerberos.
Профилактика
- Образ с 99-hardening и cloud-init disable_root.
- Мониторинг
sshd -Tvs эталон. - Ключи именные, отзыв в HR.
- Не править
/etc/ssh/sshd_configруками если есть Include.
FAQ
MaxAuthTries 3 и несколько ключей в агенте
Клиент перебирает ключи, каждый может считаться попыткой. IdentitiesOnly=yes и IdentityFile в ~/.ssh/config.
PermitRootLogin prohibit-password
Не цель. См. статью root login.
Ciphers/Kex
Можно сузить по доке OpenSSH вашей версии, после проверки клиентов (WinSCP, ansible). Не копируйте список 2016 года — отрежете себя. Не выдумывайте CVE в статье: смотрите changelog пакета.
ListenAddress 10.0.20.10
Хорошо если один NIC. Не забудьте IPv6 политику.
DebianBanner / VersionAddendum
Косметика. Ключи и AllowUsers важнее.