25 правил SSH, которые ITfresh применяет — стандарт 2026
SSH-ключ с 25 точками-правилами безопасности ed25519 SSH KEY 2026 standard 01 PermitRootLogin no 02 PasswordAuthentication no 03 PubkeyAuthentication yes 04 ed25519 keys only 05 MaxAuthTries 3 06 LoginGraceTime 30s 07 AllowUsers strict 08 Banner /etc/issue.net 09 LogLevel VERBOSE 10 X11Forwarding no 11 ClientAliveInterval 300 12 fail2ban + 5/10min 13 Match-blocks per group 14 Port hidden by FW 15 Centralized log → Wazuh 16 ChrootDirectory SFTP 17 ForceCommand internal-sftp 18 ProxyJump bastion 19 sshd -T audit 20 ssh-audit verify 21 Quarterly key rotation 22 No agent-forward home 23 2FA via TOTP 24 Strong KexAlgorithms 25 known_hosts pinning
25 точек безопасности SSH: от ключа ed25519 до квартальной ротации
· 19 мин чтения · Семёнов Е.С., руководитель ITfresh

25 правил SSH, которые ITfresh применяет у каждого клиента — стандарт 2026

25 правил SSH, которые ITfresh применяет у каждого клиента — стандарт 2026

Был у нас клиент — бухгалтерская фирма из ЦАО, 22 рабочих места. После новостей о взломе одного известного провайдера их директор всерьёз занервничал насчёт собственных серверов. Мы пришли, провели аудит по внутреннему чек-листу SSH — и нашли 14 нарушений. Четырнадцать. На, казалось бы, небольшой конторе. Ниже я выкладываю этот чек-лист полностью: 25 правил, которые мы прогоняем у каждого клиента начиная с первой же настройки сервера. Будут реальные команды, конфиг sshd_config и объяснение того, где именно всё ломается — особенно когда правила применяют формально, не разбираясь, зачем они вообще нужны.

Зачем вообще нужен жёсткий стандарт SSH

SSH — это входная дверь к серверу. Если она из картона или просто не заперта — никакой firewall, никакой WAF, никакой антивирус не спасёт. Просто не спасёт, и всё. По нашей статистике, примерно 6 из 10 серверов в небольших компаниях при первом подключении имеют хотя бы одно из двух критичных нарушений: либо разрешён логин root по паролю, либо PasswordAuthentication стоит в yes. Этого вполне хватает, чтобы за 2–3 недели в логах накопилось от 100 000 до 5 миллионов попыток брутфорса — боты лезут со всего мира, непрерывно, методично.

Хорошая новость: привести SSH в порядок — это 1–2 часа работы инженера на сервер. Плохая: без чёткого чек-листа что-нибудь обязательно выпадет. Именно поэтому мы формализовали всё в список из 25 пунктов, разбитых на 4 группы — ключи и аутентификация, конфиг sshd, сетевая часть, аудит и эксплуатация.

Группа A: ключи и аутентификация (правила 1-7)

Правило 1. Только ed25519, никаких RSA-1024 и DSA

В 2026 году для SSH-ключей нормален ровно один алгоритм — ed25519. Быстрый, компактный, без задокументированных бэкдоров. Команда генерации:

ssh-keygen -t ed25519 -C "semenov@itfresh-ws01-2026q2" -f ~/.ssh/id_ed25519
# Обязательно с парольной фразой!
# При вопросе passphrase — вводим длинный пароль из менеджера паролей

RSA-2048 ещё проходит там, где нужна совместимость со старым железом — например, Cisco IOS до 15-й версии или совсем древние кастомные SSH-серверы. RSA-1024 и DSA — убираем везде. Они взломаны и формально, и практически.

Правило 2. PasswordAuthentication no

Аутентификация по паролю — запрещена. Без исключений. В sshd_config:

PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no

Забыл загрузить ключ перед командировкой? Это проблема инженера, а не повод открывать парольный вход. Для экстренных ситуаций у нас есть отдельная break-glass-процедура — о ней в правиле 7.

Правило 3. PermitRootLogin no

Логин под root — закрыт. Все инженеры заходят под именными учётками и поднимают привилегии через sudo. Благодаря этому в auth.log всегда видно, кто именно и что делал — а не просто «кто-то зашёл как root».

PermitRootLogin no

Правило 4. AllowUsers и AllowGroups — белый список

Не «все, кроме запрещённых», а «только разрешённые». В конфиге явно перечисляем конкретные учётки или группы:

AllowGroups ssh-users itfresh-engineers
# Альтернатива:
AllowUsers semenov ivanov ansible deploy

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

Правило 5. Парольная фраза на каждом приватном ключе

Приватный ключ без парольной фразы — это пароль, лежащий открытым текстом. Украли ноутбук — и у злоумышленника мгновенно есть доступ к админским правам на всех серверах. Поэтому каждый наш ключ защищён длинной парольной фразой, сгенерированной в менеджере паролей. Чтобы не вводить её вручную при каждом подключении, используем ssh-agent или 1Password CLI:

# macOS / Linux
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519

# Windows 11 — встроенный OpenSSH agent
Set-Service -Name ssh-agent -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

Правило 6. Один ключ — одна цель

У инженеров ITFresh не один ключ на всё подряд — у каждого несколько, под разные классы задач. Один для административных серверов клиентов, второй для собственных production-сервисов, третий для GitHub. Если один ключ скомпрометирован — меняем именно его, не трогая остальное. Никакой паники на всю инфраструктуру.

# ~/.ssh/config
Host clients-*
    IdentityFile ~/.ssh/id_ed25519_clients
    IdentitiesOnly yes

Host github.com
    IdentityFile ~/.ssh/id_ed25519_github
    IdentitiesOnly yes

Host production-*
    IdentityFile ~/.ssh/id_ed25519_prod
    IdentitiesOnly yes

Правило 7. Break-glass-учётка с физическим хранением ключа

Одна учётка break-glass с длинным паролем, ключ к которой лежит на USB-токене в сейфе у директора заказчика. Логин разрешён только с консоли (через VPN или через iLO/iDRAC). Используется в ситуациях, когда отвалилось всё остальное.

Группа B: конфигурация sshd (правила 8-15)

Правило 8. MaxAuthTries 3 и LoginGraceTime 30s

Боты не должны бесконечно перебирать ключи. И полуоткрытые соединения не должны висеть часами. Решается это парой параметров с таймаутами:

MaxAuthTries 3
MaxStartups 10:30:60
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2

MaxStartups 10:30:60 работает так: после 10 одновременных неаутентифицированных подключений новые соединения начинают отбрасываться с вероятностью 30%, после 60 — все без исключения. Это прямая защита от DoS.

Правило 9. LogLevel VERBOSE

Дефолтный уровень логирования INFO — почти бесполезен при разборе инцидента. VERBOSE — другое дело: он пишет все попытки аутентификации и fingerprint каждого ключа. Когда что-то идёт не так, именно это позволяет понять, что произошло и откуда пришли.

LogLevel VERBOSE
SyslogFacility AUTH

Правило 10. Match-блоки для разных групп пользователей

Не все пользователи равны. Разработчику нужен полный shell — это понятно. Бухгалтеру достаточно SFTP к конкретной папке, а бэкап-скрипту вообще только rsync. Match-блоки решают это чисто и без лишних движений:

Match Group sftp-only
    ChrootDirectory %h
    ForceCommand internal-sftp -l VERBOSE
    AllowTcpForwarding no
    X11Forwarding no
    PermitTunnel no

Match Group backup-only
    ForceCommand /usr/local/bin/rrsync -ro /backup/source
    AllowTcpForwarding no
    X11Forwarding no

Match User semenov,ivanov
    PermitTTY yes
    AllowAgentForwarding yes

Правило 11. Запрет X11/TCP-форвардинга по умолчанию

X11 не нужен? Отключаем глобально. Нужен туннелированный доступ к внутренним сервисам — разрешаем точечно, прямо через Match-блок:

X11Forwarding no
AllowTcpForwarding no
GatewayPorts no
PermitTunnel no
AllowAgentForwarding no

Правило 12. Современные KexAlgorithms, Ciphers, MACs

Старые алгоритмы шифрования и обмена ключами нельзя просто «оставить на потом». Их нужно явно отключать. Актуальный набор на 2026 год выглядит так:

KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,sntrup761x25519-sha512@openssh.com,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256
PubkeyAcceptedAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256

Результат проверяем через ssh-audit — подробнее об этом в правиле 19.

Правило 13. Только ed25519 и rsa-2048+ host keys

Дефолтные ключи DSA и ECDSA удаляем. Оставляем только ed25519 и RSA:

cd /etc/ssh
rm -f ssh_host_dsa_key* ssh_host_ecdsa_key*
ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" < /dev/null
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key -N "" < /dev/null

# В sshd_config
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# DSA и ECDSA hostkey-строки убираем

Правило 14. Banner и legal-предупреждение

Banner — это не про красоту. Это про юридическую чистоту. Если случится инцидент с попыткой несанкционированного доступа, banner послужит официальным уведомлением: система частная, любые попытки проникновения — нарушение. Без такого уведомления доказать злой умысел в суде куда сложнее:

# /etc/issue.net
*****************************************************************
   ВНИМАНИЕ! Это закрытая система ITfresh.
   Доступ только для авторизованных лиц.
   Все действия логируются и могут быть переданы
   в правоохранительные органы.
*****************************************************************

# В sshd_config
Banner /etc/issue.net

Правило 15. UseDNS no и StrictModes yes

UseDNS no                 # быстрее логин, нет зависимости от DNS
StrictModes yes           # проверка прав на authorized_keys
PermitUserEnvironment no  # запрет на ~/.ssh/environment
AcceptEnv LANG LC_*       # только нужные переменные среды

Группа C: сеть и обвязка (правила 16-21)

Правило 16. fail2ban с агрессивными правилами

fail2ban необязателен, но ключевую аутентификацию он усиливает хорошо. Конкретная конфигурация для SSH:

# /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
backend = systemd
maxretry = 3
findtime = 600
bantime = 86400
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 1209600
ignoreip = 127.0.0.1/8 10.0.0.0/8 192.168.0.0/16

Параметр bantime.increment двойной: первая блокировка — 24 часа, вторая для того же IP — 48 часов, потом 96 и так до максимума 14 дней. Это эффективно «выжигает» спамеров из логов.

Правило 17. Бастион-хост и ProxyJump

Мой принцип простой: продакшен-серверы не должны торчать напрямую в интернет. Только через jump-host, он же бастион. Вот что мы прописываем на клиентской стороне в ~/.ssh/config:

Host bastion
    HostName bastion.client.ru
    User semenov
    IdentityFile ~/.ssh/id_ed25519_clients
    IdentitiesOnly yes

Host prod-*
    User semenov
    IdentityFile ~/.ssh/id_ed25519_clients
    IdentitiesOnly yes
    ProxyJump bastion

Команда ssh prod-app01 подключается через бастион автоматически. На бастионе нет производственных данных — только логи всех проходов.

Правило 18. Файрвол с белым списком IP

На клиентском сервере SSH открыт исключительно для:

ufw default deny incoming
ufw allow from 10.20.0.0/16 to any port 22
ufw allow from 91.218.245.10 to any port 22  # ITfresh VPN exit
ufw allow from 91.218.245.11 to any port 22  # ITfresh standby
ufw enable

Правило 19. Регулярный аудит через ssh-audit

Раз в квартал я прогоняю утилиту ssh-audit по всем клиентским серверам:

pip install ssh-audit
ssh-audit prod.client.ru -p 22

# Ожидаемый результат: общая оценка A или A+
# Если ниже B — есть критические замечания, чинить

ssh-audit проверяет криптографические настройки и сравнивает их с актуальной базой уязвимостей. На нашей практике бывало: алгоритм тихо менял статус на устаревший, а без утилиты мы бы узнали об этом только из новостей — и не в лучший момент.

Правило 20. Квартальная ротация ключей пользователей

В ITfresh действует жёсткое правило: раз в три месяца каждый инженер перевыпускает свой клиентский ключ и обновляет authorized_keys на всех серверах через Ansible. Долго? Да, кропотливо. Но смысл именно в этом — даже если ключ где-то незаметно утёк, он физически не проживёт дольше квартала.

Правило 21. Pin known_hosts на всех клиентских машинах

HashKnownHosts yes — не просто опция в конфиге. Это защита от случайного раскрытия списка серверов, к которым подключается инженер. И отдельный момент, который нельзя игнорировать: предупреждение «host key changed» требует немедленного разбора. Это либо атака MITM, либо переустановка сервера — в обоих случаях молча кликнуть «продолжить» нельзя.

# ~/.ssh/config
Host *
    HashKnownHosts yes
    StrictHostKeyChecking ask
    VerifyHostKeyDNS no

Группа D: аудит и эксплуатация (правила 22-25)

Правило 22. Централизованный auth.log в Wazuh/Graylog

На каждом сервере rsyslog отправляет auth.log в наш центральный SIEM — Wazuh у большинства клиентов, Graylog у крупных. Там настроены правила:

cat > /etc/rsyslog.d/50-auth-to-wazuh.conf <<EOF
auth.*  @@10.20.99.5:514
EOF
systemctl restart rsyslog

Правило 23. 2FA через TOTP для критичных серверов

На бастион-хосте и серверах с боевой бухгалтерией одного ключа мало. Дополнительно — TOTP-код через Google Authenticator или Aegis. Подключается через pluggable-модуль libpam-google-authenticator:

apt install libpam-google-authenticator

# В /etc/pam.d/sshd
auth required pam_google_authenticator.so

# В /etc/ssh/sshd_config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

# Для каждого пользователя — настройка
google-authenticator -t -d -f -r 3 -R 30 -W

Получается двойная защита: ключ плюс код из приложения. Брутфорсить такую связку — пустая трата времени.

Правило 24. Sudo с записью команд через io-log

sudo сам по себе пишет в auth.log только одно: «пользователь вызвал команду X». Реальный shell-сеанс под sudo -i там не отражается никак. Если нужно зафиксировать всё, что инженер делал с правами root — буквально каждую команду — включаем sudo io-log. Тогда картина полная.

# /etc/sudoers.d/log-everything
Defaults log_input, log_output
Defaults iolog_dir=/var/log/sudo-io
Defaults iolog_user=root:root
Defaults iolog_group=root

Логи бьются по сессиям, потом проигрываются через sudoreplay. Бывает критично при разборе инцидента «кто удалил production-таблицу в 14:32».

Правило 25. Регулярная проверка sshd -T в CI

Финальное правило — автоматизация. Раз в день Ansible идёт по всем клиентским серверам и собирает sshd -T (выдача актуального состояния конфига), сравнивает с эталоном. Если что-то отличается — алерт.

# Снимок конфига
ssh prod-app01 "sudo sshd -T" | sort > /tmp/actual.txt
diff /opt/itfresh/baseline/sshd-prod-app01.txt /tmp/actual.txt

# Отрабатывает в Ansible через checksum-модуль
- name: Validate sshd live config
  command: sshd -T
  register: live_sshd
- assert:
    that:
      - "'permitrootlogin no' in live_sshd.stdout|lower"
      - "'passwordauthentication no' in live_sshd.stdout|lower"
      - "'pubkeyauthentication yes' in live_sshd.stdout|lower"

Полный sshd_config «по уму»

Чтобы каждый раз не собирать конфиг из разных источников по кусочкам, выкладываем наш рабочий референсный sshd_config 2026 года — тот самый, который мы накатываем на клиентские Ubuntu/Debian-серверы:

# /etc/ssh/sshd_config — ITfresh standard 2026
Port 22
AddressFamily inet
ListenAddress 0.0.0.0

HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# Crypto
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,sntrup761x25519-sha512@openssh.com,diffie-hellman-group16-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
PubkeyAcceptedAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256

# Auth
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
MaxAuthTries 3
MaxSessions 5
MaxStartups 10:30:60
LoginGraceTime 30
AuthorizedKeysFile .ssh/authorized_keys
AuthenticationMethods publickey

# Allow lists
AllowGroups itfresh-engineers app-deploy sftp-only

# Behaviour
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
AllowAgentForwarding no
GatewayPorts no
PrintLastLog yes
TCPKeepAlive no
ClientAliveInterval 300
ClientAliveCountMax 2
UseDNS no
StrictModes yes
PermitUserEnvironment no
AcceptEnv LANG LC_*
Subsystem sftp internal-sftp

# Logging
LogLevel VERBOSE
SyslogFacility AUTH

# Banner
Banner /etc/issue.net

# Match blocks
Match Group sftp-only
    ChrootDirectory %h
    ForceCommand internal-sftp -l VERBOSE
    AllowTcpForwarding no
    X11Forwarding no

Match Group itfresh-engineers
    AllowAgentForwarding yes
    AllowTcpForwarding yes

Контр-нарратив: где SSH-харденинг — это перебор

Скажу вещь, которую многие не любят слышать. Один dev-сервер, на котором разработчик крутит тестовый WordPress, — это не то место, куда стоит тащить TOTP, бастион-хост и SIEM с алертами на изменение sshd_config. Бессмысленно. На dev достаточно отключить парольную аутентификацию и оставить только ключи. Остальное — операционные накладные расходы без реального выхлопа: сервер злоумышленнику неинтересен, а если что-то пойдёт не так — он поднимается заново из git за 20 минут.

По моему мнению, действительно жёсткие меры — пункты 22–25 — оправданы там, где компрометация SSH напрямую грозит потерей боевых данных или деньгами. Серверы с базой 1С, эквайринг, медицинские данные — вот где это обязательно. Тестовая VM разработчика? Там такой уровень защиты избыточен.

FAQ: что чаще всего спрашивают клиенты

Реально ли менять стандартный порт SSH с 22 на нестандартный?

Тема, вокруг которой копья ломают годами. Моя личная позиция: оставляю 22 порт, закрываю его файрволом, добавляю ключи и fail2ban. Перенос на 2222 убирает из логов 99% автоматических ботов — это факт. Но целевой атакующий просканирует все порты nmap-ом секунд за 30, и никакой нестандартный порт его не остановит. Именно поэтому для клиентских серверов с публичным IP мы переносим SSH на нестандартный порт исключительно ради тишины в логах. Не ради безопасности — давайте называть вещи своими именами.

Можно ли разрешить вход root по SSH, если ключ длинный?

PermitRootLogin no — это не про длину ключа. Это про разделение ответственности. На сервере должна быть именная учётка инженера — например, semenov — которая через sudo получает root по запросу, и каждый такой запрос пишется в auth.log. Когда 10 инженеров ходят под одной root-учёткой, концы найти невозможно. Регламент security audit в любой нормальной компании требует именно персональных учёток. Без вариантов.

Какой ключ выбрать — RSA 4096, ECDSA или ed25519?

Мой выбор — только ed25519. Исключение одно: если у вас жёсткие требования совместимости с совсем древними системами. RSA 4096 медленный и громоздкий. ECDSA построен на NIST-кривых, к которым у части аудиторов накопились исторические вопросы. ed25519 — современный, быстрый, компактный алгоритм с открытой криптографией и без каких-либо задокументированных бэкдоров. Все клиентские серверы, которые мы настраивали с 2024 по 2026 год, работают именно на нём.

Что делать, если не работает SSH-агент-форвардинг через jump-host?

ForwardAgent — небезопасная штука, и на практике он регулярно ломается на промежуточных хостах. Вместо него рекомендую ProxyJump в ~/.ssh/config. Схема простая: ssh client сначала коннектится к jump-host, а уже через него — к target. Ключ при этом остаётся на вашем локальном компьютере и никуда по цепочке не передаётся. На нашей практике такой подход и стабильнее, и безопаснее — без исключений.

Сколько стоит у ITfresh аудит SSH-настроек серверов?

Парк из 5–15 серверов — это 25–40 тысяч рублей и 1–2 рабочих дня нашего инженера. Что входит: проверка sshd_config по всем 25 пунктам, аудит ~/.ssh/authorized_keys на каждом сервере, проверка fail2ban, настройка централизованного auth.log в Wazuh или Graylog, отчёт с приоритезированными уязвимостями. Если параллельно делаем харденинг — ещё 1–2 дня, итоговая сумма 50–80 тысяч рублей.

Итог

SSH — не то место, где стоит экспериментировать. Те 25 правил, о которых я рассказал, — это стандарт, который мы отточили за 15 лет и применяем у каждого клиента без исключений. Была у нас бухгалтерская фирма из ЦАО: за один рабочий день инженер закрыл 14 уязвимостей, и количество попыток брутфорса в логах упало с 18 000 в сутки до 30. Тридцать. Если хотите такой же аудит — напишите, пришлю чек-лист и оценку работ.

Похожая задача в вашей компании?

Просто расскажите мне, какая у вас сейчас ситуация, и я обязательно пришлю вам план работ и оценку в течение одного рабочего дня.

Написать в Telegram  или  +7 903 729-62-41

Семёнов Е.С., руководитель ITfresh

Подпишитесь на рассылку ITfresh

Каждую неделю — практические гайды для IT-руководителя и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Письмо придёт в течение минутыНе нашли его во «Входящих» — загляните в папку «Спам» или «Промоакции» и нажмите «Не спам». Так все следующие выпуски будут приходить прямо в основную почту.
Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.