known_hosts
known_hosts это файл, в котором SSH-клиент хранит публичные ключи хостов серверов, к которым вы подключались, обычно ~/.ssh/known_hosts. При каждом подключении ssh сравнивает ключ, который предъявил сервер, с сохранённым, и так обнаруживает подмену сервера или атаку «человек посередине». Системная копия лежит в /etc/ssh/ssh_known_hosts.
Что такое known_hosts и как проверяется ключ хоста
При первом подключении к серверу ssh показывает отпечаток его ключа хоста и спрашивает, доверять ли ему. Ответ сохраняется в ~/.ssh/known_hosts. При каждом следующем подключении ssh сравнивает ключ сервера с сохранённым, поэтому другая машина не сможет незаметно занять место сервера. Формат описан в справке sshd(8): необязательный маркер (@cert-authority или @revoked), список шаблонов хостов через запятую, тип ключа, ключ в base64 и необязательный комментарий. Нестандартный порт записывается как [host]:port.
web1.example.com,203.0.113.7 ssh-ed25519 AAAAC3Nza...
[web1.example.com]:2222 ssh-ed25519 AAAAC3Nza...
Администратор может подготовить общий для всех файл /etc/ssh/ssh_known_hosts, а пользовательский файл обновляется автоматически. Проверяются оба. Это клиентская половина доверия: она подтверждает, что сервер именно тот, а ваши собственные ключи, о которых говорится в статье про вход по ключам, подтверждают, кто вы.
Как читать и править файл
Записями управляют через ssh-keygen(1) и ssh-keyscan(1). Опция -F ищет хост (удобно, когда имена хешированы), -R удаляет все ключи этого хоста, а -H заменяет имена хешами и переносит исходный файл в файл с суффиксом .old.
ssh-keygen -F web1.example.com
ssh-keygen -R web1.example.com
ssh-keygen -R "[web1.example.com]:2222"
ssh-keygen -H
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Последняя команда, выполненная на сервере, печатает отпечаток, который нужно сравнить с показанным ssh при первом подключении. Хешированные записи продолжают работать, но при утечке файла не раскрывают имена хостов. Опция HashKnownHosts (по умолчанию no) хеширует только новые записи. Чтобы безопасно проверить поведение, направьте ssh на временный файл: ssh -o UserKnownHostsFile=/tmp/kh-test web1.example.com, настоящий файл останется нетронутым. Вывод ssh-keyscan считайте непроверенным: в справке сказано, что он не может подтвердить подлинность ключей.
StrictHostKeyChecking и предупреждение об изменившемся ключе
Опция StrictHostKeyChecking из ssh_config(5) определяет поведение для неизвестных и изменившихся ключей. По умолчанию ask: новые ключи добавляются после вашего подтверждения, изменившиеся отвергаются. yes никогда не добавляет ключи сам и отвергает изменившиеся. accept-new молча добавляет новые ключи, но по-прежнему отвергает изменившиеся, для скриптов это разумный компромисс. no (или off) добавляет новые ключи и разрешает подключение к хостам с изменившимся ключом.
Если сохранённый ключ больше не совпадает, ssh печатает WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! и указывает файл и строку проблемного ключа. Безобидные причины: сервер переустановили, либо новая машина получила прежний IP-адрес. Сверьте новый отпечаток через консоль провайдера или другой доверенный канал и только потом выполните ssh-keygen -R для этого хоста. Не удаляйте строку рефлекторно: изменившийся ключ выглядит именно так же, как атака «человек посередине». Даже при no OpenSSH ограничивает сессию после несовпадения ключа (по исходному коду отключаются парольная аутентификация и проброс), но не стоит на это рассчитывать.
known_hosts в защищённой конфигурации
Слабое место это доверие при первом подключении: доверие получает тот, кто ответил первым. Для важных серверов сверяйте отпечаток с консолью провайдера, прежде чем вводить yes, как описано в руководстве по защите SSH. Для автоматизации и CI положите проверенный ключ хоста в ssh_known_hosts и используйте StrictHostKeyChecking yes вместо no: разовая проверка превращается в гарантию.
В крупных парках серверов можно пометить центр сертификации через @cert-authority, и подписанные ключи хостов будут приниматься без записей для каждого сервера, а @revoked полностью блокирует ключ. Опция VerifyHostKeyDNS (по умолчанию no) умеет проверять SSHFP-записи в защищённом DNS. За бастионным хостом помните, что у каждого внутреннего сервера своя запись. После подозрения на взлом считайте старые ключи хостов скомпрометированными и действуйте по руководству по реагированию на инциденты. Повседневная ошибка по соседству разобрана в руководстве по Permission denied (publickey).
Связанные термины: SSH, ssh-keygen, sshd_config, Bastion host (бастионный хост), Вход по ключам.
Часто задаваемые вопросы
Что такое файл known_hosts?
Это файл, в котором SSH-клиент хранит публичные ключи хостов серверов, к которым вы подключались, обычно ~/.ssh/known_hosts. По нему ssh проверяет, что сервер тот же, которому вы доверяли раньше.
Что значит REMOTE HOST IDENTIFICATION HAS CHANGED?
Ключ, который предъявляет сервер, отличается от сохранённого в known_hosts. Частые причины: переустановка сервера или повторно выданный IP-адрес, но это может быть и атака «человек посередине», поэтому сначала проверьте новый отпечаток, а потом удаляйте старую запись.
Как удалить хост из known_hosts?
Выполните ssh-keygen -R и имя хоста, а для нестандартного порта [host]:port. Команда удаляет все ключи этого хоста, включая хешированные записи.
Безопасно ли ставить StrictHostKeyChecking no?
Нет. Это позволяет подключаться к хостам с изменившимся ключом и сводит на нет защиту от подмены. Если нужно автоматически принимать ключи при первом подключении, используйте accept-new.
Что такое хешированные записи в known_hosts?
Это строки, в которых имя хоста заменено хешем, начинающимся с символа вертикальной черты, поэтому утёкший файл не раскрывает список ваших серверов. ssh по-прежнему находит их, а ssh-keygen -H преобразует существующий файл.
Хотите увидеть, в каком состоянии ваш сервер?
Запустите бесплатную read-only проверку сервера или откройте Security Lab и посмотрите цикл обнаружение, сдерживание, восстановление, проверка в действии.
Получить бесплатную проверку сервераОткрыть Security Lab