Зачем вообще существует 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 и дальше подключаться без сюрпризов.
