Авторизация по SSH-ключу — настройка безопасного входа на сервер

1493
Авторизация по SSH-ключу — настройка безопасного входа на сервер

SSH-ключ заменяет передачу учетного пароля криптографическим доказательством владения приватным ключом. Сервер хранит публичную часть, клиент подписывает данные текущего сеанса, а приватная часть не покидает компьютер или аппаратный токен. Схема защищает от перебора паролей, но не спасает от украденного приватного файла, подмены сервера и бесконтрольного разрастания ключей.

Я настраиваю ключевой вход в четыре этапа. Сначала проверяю ключ хоста, затем создаю отдельную пару для конкретного устройства или задачи, проверяю вход во втором терминале и только после этого отключаю пароль. Главная ошибка администраторов не слабый алгоритм, а потерянный контроль над ключами и правами в authorized_keys.

Что SSH проверяет во время входа

Фраза «авторизация по ключу» привычна, но сначала SSH аутентифицирует пользователя. Авторизация начинается позже, когда система применяет права учетной записи, группы, sudo и политики доступа.

У SSH есть две категории ключей. Ключ хоста подтверждает личность сервера и сохраняется на клиенте в known_hosts. Пользовательский ключ подтверждает личность клиента, а публичная часть обычно находится на сервере в ~/.ssh/authorized_keys. Шифрование не помогает, если пользователь установил защищенный канал с машиной злоумышленника.

При первом подключении я сверяю отпечаток через консоль сервера, панель хостинга. ssh-keyscan только получает опубликованный сервером ключ и сам не доказывает его подлинность.

sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

После установки защищенного транспортного канала клиент предлагает публичный ключ. Сервер проверяет, разрешен ли ключ для выбранной учетной записи, после чего клиент создает подпись приватной частью. Подпись включает идентификатор текущего сеанса и параметры запроса, поэтому перехваченный ответ нельзя повторить в новом соединении. Формат описывает RFC 4252.

Парольная фраза не передается серверу. Она шифрует приватный файл на клиентском устройстве. Пустая фраза удобна для автоматики, но превращает украденный файл в готовый пропуск.

Создаем и устанавливаем ключ без риска потерять доступ

Для современной системы разумный выбор по умолчанию Ed25519. В upstream OpenSSH ssh-keygen без параметров уже создает такой ключ, но я указываю тип явно, поскольку системный пакет может быть старее. В средах с политикой FIPS Ed25519 иногда недоступен. Для совместимости подходит RSA длиной 3072 или 4096 бит с подписями SHA-2. Старый алгоритм подписи ssh-rsa использует SHA-1 и отключен в современных конфигурациях, хотя тот же RSA-ключ может работать через rsa-sha2-256 или rsa-sha2-512.

ssh-keygen -t ed25519 -a 64 
 -f ~/.ssh/id_ed25519_production_2026 
 -C "alex@workstation production 2026"

-a 64 увеличивает число раундов функции, которая защищает приватный файл. Параметр не усиливает сетевую подпись. Комментарий не участвует в криптографии, но помогает определить владельца и назначение ключа.

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

ssh-copy-id -i ~/.ssh/id_ed25519_production_2026.pub 
 admin@server.example.com

Если ssh-copy-id отсутствует, ключ можно добавить через уже разрешенный SSH-сеанс.

cat ~/.ssh/id_ed25519_production_2026.pub | 
 ssh admin@server.example.com 
 'umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys'

На сервере проверяем владельца и разрешения.

chmod 700 ~/.ssh
 chmod 600 ~/.ssh/authorized_keys
 chown -R "$USER":"$(id -gn)" ~/.ssh

При включенном StrictModes OpenSSH проверяет владельца и возможность записи в домашний каталог, .ssh и authorized_keys. В системах с SELinux после переноса файлов может потребоваться restorecon -Rv ~/.ssh.

Перед изменением серверной конфигурации открываем второй терминал и принудительно указываем новый ключ.

ssh -o IdentitiesOnly=yes 
 -i ~/.ssh/id_ed25519_production_2026 
 admin@server.example.com

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

Host production
     HostName server.example.com
     User admin
     IdentityFile ~/.ssh/id_ed25519_production_2026
     IdentitiesOnly yes
     StrictHostKeyChecking accept-new

IdentitiesOnly yes не дает агенту перебрать все загруженные ключи. Значение accept-new автоматически принимает только ранее неизвестные ключи хоста, но блокирует изменившиеся. Для критичных систем я использую StrictHostKeyChecking yes и заранее подготовленный known_hosts. Остальные параметры содержит руководство OpenSSH.

Отключаем пароли и ограничиваем возможности ключа

После успешного входа редактируем /etc/ssh/sshd_config или файл в /etc/ssh/sshd_config.d/.

PubkeyAuthentication yes
 PasswordAuthentication no
 KbdInteractiveAuthentication no
 PermitRootLogin no

PasswordAuthentication no отключает обычную проверку пароля. PAM может запросить пароль через keyboard-interactive, поэтому при входе только по ключам я отключаю и KbdInteractiveAuthentication.

Сервер с TOTP, Duo или другой MFA через PAM требует иной схемы.

PubkeyAuthentication yes
 PasswordAuthentication no
 KbdInteractiveAuthentication yes
 AuthenticationMethods publickey,keyboard-interactive:pam

OpenSSH также умеет требовать два разных публичных ключа через AuthenticationMethods publickey,publickey. Для особо ценных систем можно сочетать локальную пару и аппаратный FIDO-ключ.

Перед перечитыванием конфигурации проверяем синтаксис и итоговые значения.

sudo sshd -t
 
 sudo sshd -T -C user=admin,addr=203.0.113.10,host=server.example.com |
 grep -E 'pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin|authenticationmethods'

-C применяет подходящие блоки Match. Без параметра проверка может показать глобальное значение и скрыть правило для конкретного пользователя или адреса. Затем выполняем systemctl reload ssh на Debian и Ubuntu либо systemctl reload sshd в других распространенных дистрибутивах.

Автоматический ключ не должен получать полноценную оболочку.

restrict,command="/usr/local/sbin/run-backup" 
 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... backup@storage

restrict запрещает PTY, TCP-, X11- и agent-forwarding, а также запуск ~/.ssh/rc. command заменяет команду клиента заданной программой. Один command не блокирует туннели, поэтому без дополнительных ограничений ключ остается опаснее, чем кажется.

Временный доступ можно ограничить адресом и сроком.

from="203.0.113.0/24",expiry-time="20260801Z",restrict 
 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... contractor@laptop

Ограничение по IP снижает ущерб от кражи ключа, но ломается при динамических адресах и не заменяет отзыв. Для большой инфраструктуры лучше подходят SSH-сертификаты с коротким сроком действия. Сервер доверяет одному ключу центра сертификации, а не сотням бессрочных строк в пользовательских каталогах.

Агент, аппаратные ключи и диагностика отказов

ssh-agent хранит разблокированные идентификаторы в памяти и подписывает запросы. Приватный ключ не копируется на удаленный сервер, но пересылка агента открывает удаленной машине доступ к сокету подписи. Скомпрометированный промежуточный хост сможет использовать агент, пока соединение активно.

eval "$(ssh-agent -s)"
 ssh-add -t 1h ~/.ssh/id_ed25519_production_2026

Я не включаю ForwardAgent yes глобально и использую ProxyJump для перехода через bastion. При ProxyJump аутентификацию с конечным сервером выполняет локальный клиент, поэтому bastion не получает доступ к агенту.

ssh-keygen -t ed25519-sk -O verify-required 
 -f ~/.ssh/id_ed25519_sk_admin

У FIDO2-токена криптографический секрет остается внутри устройства, а подпись требует присутствия пользователя и, при поддержке токена, PIN. Файл-дескриптор ключа на диске обычно все равно нужен, если ключ не создан как resident.

OpenSSH 10.4 от 6 июля 2026 года получил экспериментальный ключ mldsa44-ed25519. Поддержка выключена по умолчанию, поэтому для обычного доступа я пока оставляю Ed25519.

Если вход не работает, начинаем с подробного журнала клиента.

ssh -vvv -o IdentitiesOnly=yes 
 -i ~/.ssh/id_ed25519_production_2026 
 admin@server.example.com
Симптом Причина Проверка
Нет Offering public key Клиент не выбрал файл IdentityFile, ssh-add -l
Too many authentication failures Агент предложил много ключей IdentitiesOnly yes и -i
bad ownership or modes Неверный владелец или права Домашний каталог, .ssh, SELinux
no mutual signature algorithm Стороны не согласовали подпись Версии OpenSSH, Ed25519, RSA с SHA-2
Ключ принят, но вход не завершен Нужен второй фактор или подпись Агент, токен, AuthenticationMethods

На сервере смотрим journalctl -u ssh или journalctl -u sshd. Debian и Ubuntu также могут писать в /var/log/auth.log, системы семейства RHEL в /var/log/secure. На Windows обычные пользователи используют %USERPROFILE%.sshauthorized_keys, а администраторы по стандартной конфигурации используют %ProgramData%sshadministrators_authorized_keys с доступом только для SYSTEM и Administrators.

Надежный SSH-доступ строится не вокруг одного сильного алгоритма. Проверяйте ключ хоста, разделяйте ключи по устройствам и задачам, защищайте приватные файлы фразой или токеном, ограничивайте автоматические учетные данные и регулярно удаляйте ненужные строки. Когда серверов становится много, переходите к короткоживущим сертификатам и централизованному учету. В отдельном материале про SSH-туннели те же ограничения особенно важны, поскольку скомпрометированный ключ может открыть не только оболочку, но и внутренние сетевые сервисы.

Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.

антипов жжёт

В санатории вас лечат.
Или просто доят?

// пиявки, озон и клизмы в вашем счёте →

Юрий Кочетов

Здесь я делюсь своими не самыми полезными, но крайне забавными мыслями о том, как устроен этот мир. Если вы устали от скучных советов и правильных решений, то вам точно сюда.