opened image

known_hosts и host key в SSH

 

 

Зачем вообще существует known_hosts

 

Когда вы подключаетесь к серверу по SSH, клиент должен убедиться, что перед ним действительно тот самый сервер, а не подмена на маршруте. Для этого SSH хранит публичные ключи серверов в файле known_hosts и сравнивает их при каждом подключении.

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

 

 

Где лежит known_hosts и чем отличается системный файл от пользовательского

 

Обычно SSH использует два уровня хранения.

Пользовательский файл:

  • ~/.ssh/known_hosts

Системный файл (общий для всех пользователей):

  • /etc/ssh/ssh_known_hosts

На практике новичкам проще начинать с ~/.ssh/known_hosts, а системный файл использовать, когда вы администрируете парк серверов и хотите централизованное доверие для всех пользователей.

 

 

Как выглядит первое подключение и что происходит после подтверждения

 

При первом подключении к неизвестному серверу вы увидите сообщение вроде:

ssh root@server.example.com

SSH покажет отпечаток ключа (fingerprint) и спросит, доверяете ли вы этому серверу. Если вы отвечаете yes, ключ сохраняется в known_hosts и дальше вопрос повторяться не будет.

Скриншот из консоли: первое подключение по ssh с вопросом о доверии и отображением fingerprint.

 подтверждайте ключ только после проверки отпечатка. В идеале отпечаток должен быть известен заранее из панели управления, тикета или внутренних записей.

 

 

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

 

Иногда в интернете советуют использовать StrictHostKeyChecking=no, чтобы SSH не задавал вопросов. Технически это работает, но это также означает, что вы можете незаметно подключиться к подмененному серверу.

Если вам нужно автоматизировать подключение, безопаснее заранее положить ключ сервера в known_hosts, а не отключать проверку.

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

 

 

Как заранее добавить публичный ключ сервера в known_hosts через ssh-keyscan

 

Самый практичный метод - получить публичные host keys сервера командой ssh-keyscan и записать их в known_hosts.

Пример для стандартного порта 22:

ssh-keyscan server.example.com >> ~/.ssh/known_hosts

Если SSH на нестандартном порту, добавьте -p:

ssh-keyscan -p 2222 server.example.com >> ~/.ssh/known_hosts

Скриншот из консоли: вывод ssh-keyscan и затем хвост файла ~/.ssh/known_hosts через tail -n 3.

 

Важный момент: ssh-keyscan получает ключ по сети без проверки, поэтому правильный процесс такой:

  • получить ключ

  • сравнить отпечаток с доверенным источником

  • только после этого фиксировать его как доверенный

 

Чтобы посмотреть отпечаток добавленного ключа:

ssh-keygen -lf ~/.ssh/known_hosts | grep server.example.com

 

 

Как добавлять ключи с хешированием имен хостов

 

Иногда в настройках включено HashKnownHosts. Тогда в known_hosts имена серверов будут храниться в хешированном виде. Это повышает приватность, если файл known_hosts попадет в чужие руки.

Проверить значение можно в /etc/ssh/ssh_config или ~/.ssh/config, если у вас есть пользовательские настройки.

Если нужно добавить запись сразу с хешированием, используйте -H:

ssh-keyscan -H server.example.com >> ~/.ssh/known_hosts

Если у вас уже есть записи и вы хотите захешировать существующий known_hosts:

ssh-keygen -Hf ~/.ssh/known_hosts

Скриншот из консоли: выполнение ssh-keygen -Hf ~/.ssh/known_hosts с сообщением о создании файла .old.

Практический совет Zomro: после хеширования храните .old осторожно, там будут незахешированные записи. Если приватность важна, удалите файл .old после проверки.

 

 

Как найти запись о сервере в known_hosts и быстро убедиться, что она там есть

 

Когда known_hosts разрастается, удобнее искать запись командой ssh-keygen.

Поиск по хосту:

ssh-keygen -F server.example.com -f ~/.ssh/known_hosts

Если используется нестандартный порт, формат записи будет в виде [host]:port. Тогда ищите так:

ssh-keygen -F "[server.example.com]:2222" -f ~/.ssh/known_hosts

Скриншот из консоли: вывод ssh-keygen -F, где видно найденную строку и тип ключа.

 

 

Что делать, если SSH ругается на смену ключа

 

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

Самые частые причины:

  • сервер переустановили

  • поменяли OpenSSH и пересоздались host keys

  • вы подключаетесь к другому серверу под тем же именем или IP

  • есть риск атаки man-in-the-middle

Если вы уверены, что причина легитимная, удалите старую запись и добавьте новую.

 

Удаление записи по хосту:

ssh-keygen -R server.example.com

Для хоста с портом:

ssh-keygen -R "[server.example.com]:2222"

Дальше заново добавьте ключ через ssh-keyscan, как показано выше.

 

 

Минимальный безопасный сценарий для автоматизации в скриптах

 

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

  • заранее добавить host key в known_hosts

  • включить строгую проверку

Пример подключения:

ssh -o StrictHostKeyChecking=yes -o UserKnownHostsFile=~/.ssh/known_hosts root@server.example.com "uptime"

Если у вас отдельный файл known_hosts под конкретный проект:

ssh -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/opt/zomro/known_hosts root@server.example.com "uptime"

Скриншот из консоли: выполнение ssh команды с uptime и отсутствие вопросов про доверие.

 

 

Итог

 

known_hosts - это простая, но критически важная часть безопасности SSH. Для стабильной работы и автоматизации не нужно отключать проверки. Правильнее один раз собрать и проверить host keys, положить их в known_hosts и дальше подключаться без сюрпризов.