Публичные ключи в authorized_keys удобны, пока машин десяток. Когда серверов становится больше, а сотрудники приходят и уходят, начинается ручная работа: копирование ключей, удаление строк, поиск забытых доступов. SSH-сертификаты решают эту задачу иначе: администратор один раз добавляет на сервер доверие к центру сертификации, а пользователи получают подписанные сертификаты с именем, сроком действия и ограничениями. Раздача приватных ключей при этом не нужна. Ниже — рабочая схема для собственной инфраструктуры.
Две роли одного механизма
Не путайте пользовательский и хостовый сертификаты. Первый доказывает серверу, кто вы, и подписывается пользовательским CA. Второй доказывает клиенту, что сервер настоящий, и подписывается хостовым CA. Для этих целей нужны разные ключи: компрометация одного не должна автоматически ломать вторую проверку. Приватные ключи CA храните на отдельной машине с ограниченным доступом, а на серверы копируйте только публичные части.
Создание центров сертификации
Создайте каталог с правами 0700 и два ключа ed25519 с парольной фразой. Пароль на ключе CA обязателен: это не повседневный ключ, а корень доверия.
sudo install -d -m 0700 -o root -g root /etc/ssh/ca
sudo ssh-keygen -t ed25519 -a 100 -C "user CA 2026" -f /etc/ssh/ca/user_ca
sudo ssh-keygen -t ed25519 -a 100 -C "host CA 2026" -f /etc/ssh/ca/host_ca
sudo chmod 600 /etc/ssh/ca/user_ca /etc/ssh/ca/host_ca
Параметр -a 100 увеличивает число итераций KDF при проверке пароля. Публичные файлы *.pub можно свободно раздавать: они нужны серверам и клиентам для проверки подписи. Сделайте резервную копию закрытых ключей на офлайн-носителе и проверьте, что восстановление действительно работает.
Выпуск пользовательского сертификата
Пользователь генерирует обычную пару ключей у себя, отдаёт публичную часть и получает сертификат. Сертификат кладётся рядом с ключом и должен называться так же, с суффиксом -cert.pub: тогда ssh найдёт его автоматически.
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519
ssh-keygen -s /etc/ssh/ca/user_ca \
-I "alice@laptop-2026-11" -n alice,deploy -V +12h -z 1042 \
-O no-agent-forwarding -O no-port-forwarding -O no-x11-forwarding \
~/.ssh/id_ed25519.pub
ssh-keygen -L -f ~/.ssh/id_ed25519-cert.pub
-I задаёт идентификатор для журналов, -n — список principals, то есть имён, под которыми можно войти. -V +12h ограничивает срок двенадцатью часами, -z задаёт серийный номер для будущего отзыва. Команда ssh-keygen -L показывает содержимое сертификата: principals, срок, серийный номер и разрешения. Читайте этот вывод перед выдачей, а не после инцидента.
Ограничения внутри сертификата
Главная выгода сертификата — политика, подписанная вместе с ключом. Можно разрешить вход только из подсети, привязать сертификат к одной команде или потребовать аппаратную проверку пользователя. Опция clear сбрасывает все разрешения, после чего их нужно выдать явно.
ssh-keygen -s /etc/ssh/ca/user_ca -I "backup-job" \
-n backup -V +2h -O clear \
-O force-command="/usr/local/sbin/backup.sh" \
-O source-address=10.20.0.0/16 /tmp/backup.pub
В примере сертификат не даёт интерактивной оболочки: после clear не разрешён PTY, а force-command заменяет любую команду пользователя. Для интерактивных сотрудников оставьте permit-pty, но уберите переадресацию агента и X11, если они не нужны. Для ключей FIDO2 полезна опция verify-required: она требует PIN при каждом использовании.
Настройка сервера
На каждом сервере добавьте публичный ключ пользовательского CA и запретите обычные файлы авторизации, чтобы доступ нельзя было обойти старым ключом. Список отозванных сертификатов подключается отдельно.
# /etc/ssh/sshd_config.d/10-cert-auth.conf
PubkeyAuthentication yes
TrustedUserCAKeys /etc/ssh/ca/user_ca.pub
AuthorizedKeysFile none
RevokedKeys /etc/ssh/revoked_keys
AuthorizedPrincipalsFile /etc/ssh/principals/%u
AuthorizedPrincipalsFile добавляет вторую проверку: principal из сертификата должен быть перечислен в файле /etc/ssh/principals/alice. Это защищает от ошибки, когда сертификат выписан на слишком широкое имя. Файлы должны принадлежать root и быть недоступны на запись другим. Перед перезагрузкой проверьте конфигурацию через sshd -t, а затем перезагрузите службу. Не отключайте парольный вход, пока не убедились, что сертификат работает в отдельном сеансе.
Сертификаты хостов
Хостовый сертификат убирает вопрос «доверять ли этому отпечатку» при первом подключении. Клиенту достаточно один раз получить публичный ключ хостового CA.
sudo ssh-keygen -s /etc/ssh/ca/host_ca -I "web01-2026" -h \
-n web01.example.com,10.0.0.11 -V +30d \
/etc/ssh/ssh_host_ed25519_key.pub
ssh-keygen -L -f /etc/ssh/ssh_host_ed25519_key-cert.pub
В sshd_config добавьте HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub. На клиенте в ~/.ssh/known_hosts появится строка @cert-authority *.example.com ssh-ed25519 AAAA... с публичным ключом хостового CA. После этого новые серверы в домене принимаются автоматически, а подмена хоста без подписи CA обнаруживается. Срок жизни хостовых сертификатов делайте больше пользовательских, но не бесконечным.
Отзыв и ротация
Короткий срок жизни снижает потребность в отзыве, но украденный сертификат нужно уметь заблокировать немедленно. Для этого служит KRL — двоичный список отозванных ключей и серийных номеров. Он генерируется из текстового описания.
printf 'serial: 1042\n' > /tmp/revoke.spec
sudo ssh-keygen -k -f /etc/ssh/revoked_keys \
-s /etc/ssh/ca/user_ca.pub /tmp/revoke.spec
sudo ssh-keygen -k -u -f /etc/ssh/revoked_keys \
-s /etc/ssh/ca/user_ca.pub /tmp/revoke-1043.spec
ssh-keygen -Q -f /etc/ssh/revoked_keys /tmp/alice-cert.pub
Флаг -u дополняет существующий KRL, а без него файл создаётся заново. Команда -Q проверяет, попал ли сертификат в список, и возвращает ненулевой код, если он отозван. Серийные номера не переиспользуйте: при подписи берите следующий из базы или используйте -z +1042, чтобы ssh-keygen увеличивал номер для каждого файла в одной команде.
Диагностика
Большинство ошибок видны в подробном выводе клиента и журнале сервера. Ищите строки ED25519-CERT: они подтверждают, что сервер принял именно сертификат, а не обычный ключ.
ssh -vvv alice@web01.example.com 2>&1 | grep -i cert
sudo sshd -T | grep -Ei 'trusteduserca|revokedkeys|authorizedkeysfile'
sudo journalctl -u ssh -n 50 --no-pager
Сообщение «Certificate invalid: not yet valid» означает рассинхронизацию часов, «principal not permitted» — несовпадение имени, «invalid certificate» — сертификат подписан не тем CA. Проверяйте время через timedatectl и права на файлы CA: sshd игнорирует ключ, если файл доступен на запись группе или остальным.
Чек-лист
- Пользовательский и хостовый CA разделены, закрытые ключи защищены паролем.
- Сертификаты выдаются на короткий срок и содержат только нужные principals.
AuthorizedKeysFile noneиTrustedUserCAKeysпрописаны на всех серверах.- KRL обновляется по процедуре, серийные номера уникальны.
- Резервная копия CA проверена восстановлением.
- Мониторинг следит за отказами аутентификации и истечением срока CA.
Итог
SSH-сертификаты заменяют ручную раздачу ключей на управляемую политику: один CA, короткие сроки, principals и ограничения в подписанном виде. Схема требует дисциплины — защиты CA, ротации и отзыва, — но именно она делает доступ к инфраструктуре предсказуемым и проверяемым.