linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Безопасность/ssh-hardening

kb/security ── Безопасность ── intermediate

SSH hardening - закрытие сервера

SSH hardening: ключи only (PasswordAuthentication no), отключить root-login, AllowUsers/AllowGroups, MaxAuthTries, fail2ban-jail на sshd. Опционально - нестандартный порт + Match-блоки для гостей.

view as markdownaka: ssh-secure, sshd-hardening, openssh-hardening

Зачем

SSH, основной вектор атак на Linux-сервера. Бот-сети брутфорсят его круглосуточно: на любом publicly-routable IP с открытым 22 портом через сутки в auth.log, тысячи попыток. Дефолтная конфигурация OpenSSH для прода слишком открытая:

  • Разрешён root-login по паролю
  • Пароли разрешены в принципе
  • Все пользователи могут подключаться
  • Нет rate-limit на попытки
  • X11 forwarding включён

Этот документ, рецепты "по умолчанию выключить".

Минимальный hardening, что менять в sshd_config

/etc/ssh/sshd_config (или drop-in /etc/ssh/sshd_config.d/00-hardening.conf):

ini
# ===== Аутентификация =====
PermitRootLogin no                         # никогда root напрямую
PasswordAuthentication no                   # только ключи
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey            # только ключ; для 2FA: publickey,keyboard-interactive
# ===== Кто пускается =====
AllowUsers alice bob carol                 # whitelist
# ИЛИ через группу
AllowGroups ssh-users
# ===== Ограничение попыток =====
MaxAuthTries 3
MaxSessions 5
LoginGraceTime 30                          # отключить если не аутентифицировался за 30s
# ===== Идентификация сервера =====
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# ===== Cipher / KEX =====
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com
# ===== Forwarding =====
X11Forwarding no
AllowAgentForwarding no                    # включить только где надо
AllowTcpForwarding no                      # для bastion-host'ов yes
PermitTunnel no
GatewayPorts no
# ===== Прочее =====
PermitEmptyPasswords no
ClientAliveInterval 300
ClientAliveCountMax 2                      # 10 минут idle = disconnect
Banner /etc/issue.net                       # legal warning
PrintLastLog yes
UseDNS no                                   # ускоряет login (не делать reverse-DNS)

Применить:

bash
sshd -t                                    # синтаксис-чек
systemctl reload sshd

Не закрывай сразу свою активную сессию! Открой второй SSH-терминал и проверь, что новые подключения проходят.

Ключи only

Сгенерируй сильный ключ:

bash
ssh-keygen -t ed25519 -a 100 -C "alice@laptop"
# ed25519 - современный, короткий, быстрый
# -a 100 - 100 KDF rounds для защиты passphrase'ом

Скопируй на сервер:

bash
ssh-copy-id alice@server                   # автоматически
# или вручную:
cat ~/.ssh/id_ed25519.pub | ssh alice@server 'cat >> ~/.ssh/authorized_keys'

Права обязательно:

bash
ssh -o LogLevel=DEBUG alice@server         # покажет если authorized_keys mode 644 + group/other = drop
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

SSH Certificate Authority, масштабирование ключей

Раздавать ключи 100 серверам каждому юзеру, не масштабируется. SSH-CA подписывает короткоживущие сертификаты:

bash
# На CA-машине (изолированной)
ssh-keygen -t ed25519 -f ssh_ca_key
# Раздать публичный ключ CA на все сервера в /etc/ssh/ca.pub
# В sshd_config:
TrustedUserCAKeys /etc/ssh/ca.pub
# Подписать ключ юзера
ssh-keygen -s ssh_ca_key -I "alice-2026-05-01" -n alice -V +1d ~/.ssh/id_ed25519.pub

▸создаст id_ed25519-cert.pub

Сервера принимают любого, чей ключ подписан CA. Срок действия встроен в сертификат. Revocation через RevokedKeys.

Используется в Facebook, Netflix, Uber. Для 1-2 серверов overkill, для 100+, must-have.

Match-блоки

Условные правила:

ini
# SFTP-only юзеры
Match Group sftponly
    ChrootDirectory /var/sftp/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no
# Bastion: разрешить TCP-forwarding только из определённой сети
Match Address 10.0.0.0/24
    AllowTcpForwarding yes
    PermitTunnel yes
# Запретить login от deploy-юзера снаружи corp-сети
Match User deploy Address !10.0.0.0/8,!172.16.0.0/12
    DenyUsers *

Нестандартный порт, security through obscurity?

Изменение Port 22 → Port 2222 не делает SSH защищённее. Бот'ы сканируют все 65535 портов. Но уменьшает мусор в логах:

ini
Port 2222

Не забудь:

  • Открыть 2222 в фаерволе
  • Закрыть 22
  • Обновить SELinux на RHEL: semanage port -a -t ssh_port_t -p tcp 2222
  • Обновить fail2ban-jail
  • Сообщить клиентам (~/.ssh/config или Port 2222 в команде)

Я бы оставил 22 + fail2ban, а нестандартный порт, для bastion-host'ов где много автоматики.

fail2ban-jail для sshd

fail2ban читает auth.log, после N failed-попыток баннит IP в iptables/nftables.

/etc/fail2ban/jail.local:

ini
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
banaction = nftables
backend = systemd
[sshd]
enabled = true
port    = ssh
filter  = sshd
logpath = %(sshd_log)s
maxretry = 3
bash
systemctl restart fail2ban
fail2ban-client status sshd
fail2ban-client unban 1.2.3.4              # разбанить вручную

2FA через PAM

Сделать sshd требующим Google Authenticator или Yubikey помимо ключа. Внимание: baseline-конфиг выше отключает KbdInteractiveAuthentication и ChallengeResponseAuthentication. Для 2FA эти строки надо убрать (или поставить yes), иначе keyboard-interactive ступень не сработает:

ini
# sshd_config
AuthenticationMethods publickey,keyboard-interactive
KbdInteractiveAuthentication yes          # отменяет запрет из baseline
ChallengeResponseAuthentication yes
UsePAM yes

В /etc/pam.d/sshd:

auth required pam_google_authenticator.so nullok

И каждый юзер запускает google-authenticator для генерации QR.

Аудит существующего конфига

Утилиты:

bash
ssh-audit example.com                      # внешняя проверка cipher/kex/host-key
sshd -T                                    # эффективный конфиг (после Match)
sshd -T | grep -iE 'permitroot|password|kex|cipher|mac|maxauth'

Когда что-то пошло не так

  • Permission denied (publickey), ключ не в authorized_keys, либо неверные mode на ~/.ssh (нужно 700) и authorized_keys (600).
  • Закрыл себе SSH меняя конфиг, поставь второй активный SSH-сеанс ДО reload. Если уже поздно, console/IPMI/ILO/cloud-консоль. На облаках есть serial-console через CLI.
  • no matching host key type found, отключил RSA, у клиента только RSA. Добавь HostKey /etc/ssh/ssh_host_rsa_key обратно или попроси клиента обновить openssh.
  • no matching cipher found: client offers, старый клиент, cipher не в твоём whitelist. Проверь sshd -T | grep cipher.
  • fail2ban баннит самого себя, твой IP попал в jail. Whitelist через ignoreip = 127.0.0.1/8 10.0.0.0/24 my.public.ip/32.
  • GSSAPI/Kerberos handshake тормозит login, выключи GSSAPIAuthentication no если не используешь kerberos. Также UseDNS no.
  • Match-блок не применяется, Match parsed по порядку, первый match выигрывает. И Match-блок заканчивается следующим Match или EOF.

Чек-лист

  • PermitRootLogin no
  • PasswordAuthentication no
  • AllowUsers/Groups whitelist
  • MaxAuthTries ≤ 3
  • X11Forwarding no (если не нужен)
  • fail2ban-jail включён
  • ed25519 host-key и client-key
  • Modern KEX/Cipher/MAC, без legacy
  • Banner с legal-warning
  • sshd -T → проверка эффективной конфигурации
  • Сертификаты SSH-CA если 5+ серверов
  • auditd-watch на sshd_config

§ команды

bash
sshd -t

Синтаксис-проверка конфига перед reload - всегда ДО systemctl

bash
sshd -T | grep -iE 'permitroot|password|kex'

Эффективный конфиг с учётом Match-блоков и defaults

bash
ssh-keygen -t ed25519 -a 100 -C 'alice@laptop'

Сгенерить современный ключ с защитой passphrase'ом 100 раундов

bash
ssh-copy-id -i ~/.ssh/id_ed25519.pub alice@server

Скопировать pub-ключ в authorized_keys с правильными mode

bash
fail2ban-client status sshd

Кто сейчас в бане - для отладки 'не могу войти после смены IP'

bash
ssh-keygen -s ca_key -I 'alice-$(date +%F)' -n alice -V +24h pubkey.pub

Подписать ключ юзера CA на сутки - SSH-CA workflow

bash
journalctl -u sshd --since '10 min ago'

Логи sshd - failed-попытки, ключевые события, GSSAPI-ошибки

§ см. также

  • sshSSH - secure shellSSH - зашифрованный канал к удалённому хосту: shell, копирование файлов, port-forwarding. Стандартный порт 22, аутентификация по ключам или паролю.
  • fail2banfail2ban - автобан по логамfail2ban читает логи (sshd, nginx, postfix), регэкспом ловит N неудачных попыток за окно, добавляет IP в правила firewall'а на bantime. Главный инструмент против brute-force на SSH.
  • pamPAM - Pluggable Authentication ModulesPAM - фреймворк аутентификации в Linux. Программы (sudo, login, sshd) не проверяют пароли сами, а вызывают PAM, который через стек модулей в `/etc/pam.d/<service>` решает: пускать или нет.
  • auditdauditd - syscall и file auditauditd пишет события ядра в /var/log/audit/audit.log: file watches (-w), syscall rules (-a), exec'и. ausearch для поиска, aureport для отчётов. Основа compliance (PCI-DSS, HIPAA, ФЗ-152).
  • kerberosKerberos - сетевой single sign-onKerberos - SSO-система с тикетами на временной криптографии. Один раз вводишь пароль (`kinit`), получаешь TGT, дальше KDC выдаёт service tickets в обмен. Основа AD и FreeIPA.
  • tls-certificatesTLS-сертификаты - X.509, цепочка доверия, Let's EncryptTLS cert - X.509 объект с public key + identity (CN/SAN) + подписью CA. Цепочка: leaf → intermediate → root (доверенный OS). Let's Encrypt = бесплатный CA через ACME (HTTP-01/DNS-01 challenge). В k8s - cert-manager.
  • secrets-managementУправление секретами - Vault, k8s Secrets, sealed-secretsСекреты не в git, не в env-vars в коде. Опции: HashiCorp Vault (универсал, dynamic creds), k8s Secrets (base64, нужен encryption- at-rest), sealed-secrets (commit-friendly), external-secrets (sync из cloud-vault).
  • cis-benchmark-hardeningCIS Benchmark и system hardening (lynis, OpenSCAP)CIS Benchmark - стандарт hardening Linux. Lynis - быстрый локальный audit со скором, OpenSCAP - формальный с XCCDF-профилями и SCAP- репортом. ansible-lockdown - remediate. Audit и remediate раздельно.
  • gpg-pgpGPG/PGP - подпись, шифрование, web of trustGPG = open-source реализация OpenPGP. Пара ключей (RSA/ECDSA), публичный для verify/encrypt, приватный для sign/decrypt. keyring локально, web-of-trust между людьми. Используется в git-commit signing, package-signing (apt/rpm), email.
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.