SSH host keys — это «паспорт» сервера, который клиент проверяет при подключении. Если путать их с пользовательскими ключами, не планировать ротацию или учить команду «просто нажми yes», рано или поздно получите либо риск MITM, либо массовые падения автоматизаций из‑за смены отпечатка. Ниже — практический разбор: что хранится на сервере и у пользователя в known_hosts, чем ssh-ed25519 отличается от RSA hostkey, и как пережить host key rotation без сюрпризов.
Что такое SSH host keys и чем они не являются
SSH host key — это ключевая пара (приватный и публичный ключ), которая принадлежит серверу (sshd) и используется для идентификации сервера перед клиентом. При установлении соединения клиент делает verify host key: сверяет публичный ключ (или его отпечаток) с тем, что он видел раньше, либо с тем, что вы заранее «запинили».
Важно: host keys — это не то же самое, что ключи пользователя для входа.
- Host key отвечает на вопрос «это точно тот же сервер, к которому я подключался раньше?»
- User key (например,
~/.ssh/id_ed25519и запись вauthorized_keys) отвечает на вопрос «этому пользователю/ключу можно логиниться?»
Смена пользовательских ключей почти никогда не должна приводить к предупреждению REMOTE HOST IDENTIFICATION HAS CHANGED!. А вот смена host key — приводит, и это нормально, если вы делали ротацию осознанно.
Где лежат ключи хоста на сервере и как они выбираются
На типичном Linux ключи хоста хранятся в /etc/ssh/. Имена зависят от алгоритма. Самые частые:
/etc/ssh/ssh_host_ed25519_keyи/etc/ssh/ssh_host_ed25519_key.pub/etc/ssh/ssh_host_rsa_keyи/etc/ssh/ssh_host_rsa_key.pub
Какие ключи использует демон, задаётся директивами HostKey в sshd_config. Пример (порядок важен как «предпочтение», но итог зависит и от клиента):
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
Если HostKey не указаны, sshd обычно использует ключи, которые найдёт по умолчанию. В проде лучше явно зафиксировать ожидаемые алгоритмы и пути, чтобы обновления пакетов/миграции не «подсунули» неожиданный новый ключ.
Как клиент выбирает, какой host key принимать
Во время рукопожатия сервер предлагает набор поддерживаемых алгоритмов, клиент выбирает лучший из пересечения «сервер умеет» и «клиент разрешает». На современных OpenSSH почти всегда победит ssh-ed25519, если он доступен на сервере и не запрещён политиками клиента.
Если вы разворачиваете много серверов и хотите единообразно управлять SSH-политиками и ротациями, удобнее делать это на VDS: проще стандартизировать образы, конфиги и инвентарь отпечатков.

known_hosts: что хранится у пользователя и почему там бывает больно
Файл ~/.ssh/known_hosts — это кэш известных ключей серверов. Он существует, чтобы клиент мог детектировать подмену сервера при следующем подключении. Каждая запись привязана к имени хоста (или IP) и типу ключа.
Классический сценарий: вы один раз подключились к серверу, подтвердили отпечаток, после чего клиент запомнил ключ. Любая последующая смена ключа хоста приведёт к предупреждению и, в автоматизации, к фейлу (если включена строгая проверка).
Предупреждение о смене host key — это не «ошибка SSH». Это сигнал: «идентичность сервера изменилась». Иногда это плановая ротация, а иногда — потенциальный MITM.
Как устроены записи known_hosts (важно для диагностики)
В known_hosts могут быть разные формы привязки:
- простой хост:
example.com - хост с портом:
[example.com]:2222 - несколько имён на одной строке:
example.com,192.0.2.10 - хэшированные имена (если включён
HashKnownHosts) - несколько ключей для одного хоста (например, и
ssh-ed25519, и RSA)
Диагностика обычно начинается с вопроса «что сейчас отдаёт сервер» и «что сохранено у клиента». Для просмотра сохранённых записей:
ssh-keygen -F example.com
Чтобы удалить конкретную привязку (аккуратно: это сброс проверки, а не «лечение»):
ssh-keygen -R example.com
Если у вас нестандартный порт:
ssh-keygen -R "[example.com]:2222"
System-wide known_hosts и когда он реально полезен
Кроме пользовательского файла, есть системный /etc/ssh/ssh_known_hosts (или аналогичный). Он полезен, когда вы хотите централизованно сделать key pinning для всей команды или для CI-агентов: правильный ключ задан администратором, и пользователь не сможет «случайно подтвердить» подмену.
ED25519 vs RSA: что выбрать в 2026 и почему
Сравнение ssh-ed25519 и RSA hostkey часто сводят к «ed25519 лучше». Практичный вывод такой: ed25519 — дефолт для новых хостов, а RSA — это совместимость и иногда вынужденная мера (легаси-клиенты, вендорные агенты, железки).
Почему ssh-ed25519 — лучший дефолт
- Надёжные параметры “из коробки”: меньше пространства для админских ошибок.
- Компактные ключи и подписи: меньше overhead на рукопожатия, особенно при частых коннектах.
- Широкая поддержка в современных OpenSSH.
Когда RSA hostkey всё ещё нужен
- Есть клиенты, которые не умеют
ssh-ed25519или у которых он запрещён политикой. - Внутренние требования «RSA only» (часто исторические/комплаенс‑вдохновлённые).
Если RSA нужен, выбирайте адекватную длину ключа (обычно 3072 или 4096). Помните, что RSA заметно тяжелее по CPU и медленнее на рукопожатиях, чем ed25519.
Про DSA/ECDSA — и почему лучше не “тянуть” их в прод
DSA считается устаревшим. ECDSA в целом рабочий, но если у вас нет жёсткой причины, проще стандартизироваться на ssh-ed25519 плюс RSA для совместимости. Чем меньше «зоопарк» — тем проще аудит и ротации.
Verify host key: как правильно проверять отпечаток перед первым подключением
Первое подключение — критическая точка. Если в этот момент подтвердить не тот ключ, дальнейший key pinning будет фиксировать уже «подменённый» сервер.
Рабочий процесс выглядит так:
- Получить fingerprint ключа хоста из доверенного канала (панель управления, консоль провайдера, out-of-band сообщение, CMDB/инвентарь).
- Сравнить его с тем, что показывает SSH-клиент при первом подключении.
- Только после совпадения добавлять ключ в
known_hosts(вручную или управляемо).
На сервере отпечаток можно получить так (для ED25519):
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Для RSA:
ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub
Если вам нужно заранее собрать ключи в known_hosts (например, для CI), часто используют сетевое сканирование ключей. Но учитывайте риск: вы получаете ключ «как есть по сети», без гарантии, что в момент сканирования не было подмены. Такой подход имеет смысл только вместе с доверенной сетью/каналом или последующей сверкой fingerprint.
Key pinning на практике: как сделать так, чтобы автоматизация не “тыкала yes”
Запинить ключ — значит заранее и явно задать, какой ключ сервер должен иметь. В SSH это обычно делают через системный ssh_known_hosts, управляемый known_hosts в профиле CI, либо через конфигурационный менеджмент.
Что действительно помогает админам и девопсам:
- Запрещайте интерактивное принятие ключей в CI: лучше фейл и алерт, чем «молча приняли новый ключ».
- Держите “источник правды” с публичными ключами или fingerprint (CMDB, репозиторий, инвентарь).
- Разделяйте доступы: разные
known_hostsдля прод/стейджинга, чтобы случайно не смешивать окружения.
Если вы часто делаете миграции и переключения, полезно выстраивать процесс по принципу «сначала подготовка, потом переключение». См. материал про миграцию сайта без даунтайма — там эта логика хорошо ложится и на SSH-ключи.

Host key rotation: как менять ключи хоста без массовых падений
Host key rotation нужен не только «если ключ украли». Нормальные плановые причины: пересоздание VM, миграция на новый образ, требования безопасности, стандартизация алгоритмов, обновление политики, подозрение на компрометацию уровня виртуализации.
Типовая проблема ротации
Проблема обычно не в том, что sshd не поднимется. Проблема в клиентах: у них в known_hosts лежит старый ключ, и они (правильно!) отказываются подключаться.
Стратегия “двойной ключ” (dual host keys)
Самый практичный путь — на время держать два ключа: старый и новый. Это позволяет клиентам постепенно обновить записи и минимизирует внезапные падения CI/скриптов.
- Добавляете новый ключ на сервер и прописываете дополнительный
HostKeyвsshd_config. - Делаете reload/перезапуск sshd (предпочтительно reload, чтобы не рвать активные сессии; зависит от init-системы).
- Обновляете
known_hostsна клиентах: добавляете новый ключ, не удаляя старый. - Когда уверены, что клиенты «перепинены», удаляете старый ключ с сервера и чистите старые записи у клиентов.
Почему это работает: known_hosts может содержать несколько ключей для одного и того же хоста (разных типов). Клиент примет тот, о котором договорится с сервером, если он есть среди известных.
Как подготовить новый host key
Генерация ключа на сервере (ED25519):
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key_new -N ""
RSA (если нужно):
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key_new -N ""
Дальше добавляете новый путь в sshd_config через HostKey. Следите за правами: приватные ключи должны быть доступны только root, иначе sshd может отказаться их использовать.
Обновление known_hosts на клиентах без “удалить и забыть”
Идеальный вариант — распространять новый публичный ключ в управляемый known_hosts (Ansible/Salt/скрипт/образ CI). Если делаете руками, логика такая: сначала добавляете новый ключ, и только потом, когда убедились в работоспособности, убираете старый.
Проверить, что сервер отдаёт нужный ключ, можно принудительно выбрав алгоритм:
ssh -o HostKeyAlgorithms=ssh-ed25519 -o StrictHostKeyChecking=yes user@example.com
Для проверки RSA-совместимости (если вам это действительно нужно):
ssh -o HostKeyAlgorithms=ssh-rsa -o StrictHostKeyChecking=yes user@example.com
Замечание: политика вокруг ssh-rsa менялась в OpenSSH. На современных клиентах RSA host key может работать иначе, чем вы ожидаете, или требовать явного разрешения. Всегда тестируйте на вашей матрице клиентов до окна работ.
Коммуникация и окно работ
Даже при dual-key стратегии заранее:
- объявите дату, когда старый ключ будет убран;
- дайте шаги для обновления
known_hosts(и отдельный шаг для нестандартных портов); - попросите владельцев автоскриптов проверить, откуда берётся
known_hostsи включён лиStrictHostKeyChecking.
Если инфраструктура активно растёт, а доступы администрируются «по взрослому», обычно удобнее делать это на управляемых серверах. Для таких задач хорошо подходит VDS: проще централизовать конфиги, инвентарь fingerprint и процессы ротации.
Best practices для sshd_config: что реально помогает
Ниже — практики, связанные именно с host keys и их проверкой (не общий hardening SSH):
- Явно перечисляйте
HostKeyи держите порядок под контролем. - Стандартизируйте алгоритм: по умолчанию
ssh-ed25519; RSA — только если нужен. - Не клонируйте образы с одинаковыми host keys: два разных сервера с одним «паспортом» ломают модель доверия.
- Документируйте fingerprint в CMDB/инвентаре и используйте их для verify host key.
- Планируйте ротацию: dual keys, управляемое обновление known_hosts, затем вывод старого ключа.
Частые ошибки и как их избежать
Ошибка 1: “Просто удалите known_hosts и подключитесь заново”
Так вы убираете защиту и повышаете шанс принять подмену. Это допустимо как аварийная мера после проверки fingerprint через доверенный канал, но не как стандартная инструкция для команды.
Ошибка 2: включили HashKnownHosts, а процесс ротации не предусмотрели
Хэширование имён в known_hosts усложняет ручную поддержку. Это не значит, что опция плохая, но вам нужен управляемый способ обновления записей (скрипт/CM) и понимание, как находить строки по хосту.
Ошибка 3: клонирование host keys между серверами
Если у вас golden image, убедитесь, что при первом старте ключи генерируются заново, а не тянутся из образа. Иначе любой «переезд» одного хоста будет выглядеть как «тот же сервер», что неверно.
Ошибка 4: отключение проверки ради удобства
Отключать строгую проверку в автоматизациях — значит терять одну из ключевых гарантий SSH. Гораздо правильнее — key pinning и управляемая ротация.
Мини-чеклист: host keys, known_hosts и ротация
- На сервере есть
ssh_host_ed25519_key; RSA добавлен только при необходимости. - В
sshd_configявно заданыHostKey. - Fingerprint ключей хранится в доверенном месте.
- Для CI/ботов настроен key pinning (управляемый
known_hosts), а не «accept-new/yes». - Ротация делается через период dual keys и заранее обновлённые known_hosts.
Если привести host keys к понятному стандарту (ed25519 как основной), научить команду проверять fingerprint перед первым подключением и выстроить процесс host key rotation, то SSH перестанет быть источником внезапных ночных алертов и станет тем, чем задуман: безопасным и предсказуемым транспортом для администрирования.


