À quoi il sert
Un client SSH doit savoir qu'il parle au vrai serveur avant d'envoyer un mot de passe ou d'exécuter une commande. À la première connexion, il affiche l'empreinte du serveur et demande confirmation. Si vous acceptez, la clé publique est ajoutée à known_hosts. Aux connexions suivantes, la vérification est automatique, et une clé différente provoque l'erreur REMOTE HOST IDENTIFICATION HAS CHANGED.
Le fichier ne contient que des clés publiques. Il ne renferme aucun secret, mais il révèle les serveurs que vous utilisez.
Le format
203.0.113.10 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGYt...
[server]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMJi...
server,203.0.113.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...
Chaque ligne contient les noms d'hôte, le type de clé et la clé. Un port autre que 22 s'écrit entre crochets, comme [server]:2222. Les noms peuvent former une liste séparée par des virgules et contenir des jokers. Deux marqueurs facultatifs peuvent venir en premier : @cert-authority pour une clé d'autorité de certification, et @revoked pour une clé qui ne doit jamais être acceptée. Avec les certificats d'hôte SSH, une seule ligne de CA peut remplacer une ligne par serveur.
Le client lit aussi un fichier global, /etc/ssh/ssh_known_hosts, qu'un administrateur peut remplir pour tout le monde.
Entrées hachées
|1|eoQ3SZFlQ/5gRWuuw3MoS+AtytA=|BlzFc5MrVrt8iIEm7rloTmKPRBo= ssh-ed25519 AAAAC3Nz...
Une ligne qui commence par |1| a son nom d'hôte haché, si bien que celui qui vole le fichier n'obtient pas de liste toute prête de vos serveurs. ssh la retrouve quand même. Cela dépend de HashKnownHosts. La valeur par défaut d'OpenSSH est no, mais Debian l'active dans /etc/ssh/ssh_config : vous verrez donc les deux formes.
Pour hacher un fichier existant :
ssh-keygen -H
Cela conserve l'original sous le nom known_hosts.old, en clair. Supprimez cette copie si c'est pour la confidentialité que vous l'avez fait.
Commandes courantes
Elles fonctionnent aussi sur les fichiers hachés. Ajoutez -f file pour utiliser un autre fichier que celui par défaut.
| Objectif | Commande |
|---|---|
| Trouver l'entrée d'un hôte | ssh-keygen -F server |
| En trouver une sur un autre port | ssh-keygen -F '[server]:2222' |
| Afficher l'empreinte de cet hôte | ssh-keygen -lF server |
| Lister toutes les empreintes | ssh-keygen -lf ~/.ssh/known_hosts |
| Supprimer un hôte | ssh-keygen -R server |
Avec -F, le code de sortie est 1 si l'hôte n'est pas trouvé, ce qui est utile dans les scripts. -R renvoie 0 dans les deux cas.
Comment vérifier une empreinte
À la première connexion, vous voyez ceci :
The authenticity of host 'server (203.0.113.10)' can't be established.
ED25519 key fingerprint is: SHA256:iU7+QOFWSHJeCFBdzU31dTOoJRNhncp+Wzw3UJMzasU
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Taper yes sans vérifier revient à faire confiance à ce qui a répondu. Pour vérifier correctement, obtenez la valeur par un canal qui ne passe pas par cette connexion, comme la console de votre hébergeur, ou auprès de la personne qui gère le serveur. Sur le serveur :
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Comparez les valeurs, ou collez la bonne empreinte à l'invite à la place de yes, et ssh compare pour vous. Dans notre test, la bonne valeur a été acceptée, et une mauvaise a reçu Please type 'yes', 'no' or the fingerprint:.
ssh-keyscan et son problème de confiance
ssh-keyscan -t ed25519 server >> ~/.ssh/known_hosts
Cette commande récupère la clé publique d'un serveur et se voit souvent dans les scripts d'installation et les jobs de CI. Le problème est qu'elle ne vérifie rien. Elle enregistre ce qui a répondu : un attaquant placé sur le chemin fait enregistrer sa clé, et l'attaque est ensuite invisible.
Elle convient si vous vérifiez le résultat ensuite :
ssh-keyscan -t ed25519 server | ssh-keygen -lf -
En CI, il vaut mieux stocker la ligne known_hosts attendue comme valeur dans votre pipeline, et écrire celle-ci dans le fichier.
Valeurs de StrictHostKeyChecking
| Valeur | Nouvel hôte | Clé modifiée |
|---|---|---|
ask (par défaut) | Vous demande | Refuse |
yes | Refuse | Refuse |
accept-new | L'ajoute | Refuse |
no ou off | L'ajoute | Se connecte, avec des restrictions |
accept-new est le choix raisonnable pour l'automatisation : il fait confiance à la première utilisation et détecte les changements ultérieurs. yes est le plus strict, et convient aux parcs de serveurs où vous distribuez vous-même known_hosts. Avec lui, un hôte inconnu donne :
No ED25519 host key is known for server and you have requested strict checking.
Host key verification failed.
Évitez no. Il se connecte à un hôte dont la clé a changé, c'est-à-dire le cas que ce fichier existe pour détecter.
UpdateHostKeys
Un serveur peut communiquer à un client toutes ses clés d'hôte après la connexion. Avec UpdateHostKeys, le client les ajoute à known_hosts, ce qui permet à un administrateur d'ajouter une nouvelle clé, d'attendre que les clients la connaissent, puis de retirer l'ancienne sans aucun avertissement. Nous avons testé UpdateHostKeys=yes : en partant de la seule entrée ED25519, une connexion a ajouté des lignes RSA et ECDSA.
Selon le manuel, il est activé par défaut si vous n'avez pas modifié UserKnownHostsFile et n'avez pas activé VerifyHostKeyDNS. Il n'accepte que des clés venant d'un hôte déjà approuvé par votre propre fichier, pas par un fichier global, et ne s'applique pas quand l'hôte s'est authentifié avec un certificat.
SSHFP : les empreintes dans le DNS
Les empreintes de clés d'hôte peuvent aussi être publiées dans le DNS sous forme d'enregistrements SSHFP. Cette commande, lancée sur le serveur, affiche les enregistrements à ajouter pour ce serveur :
ssh-keygen -r example.com
Les clients les utilisent avec VerifyHostKeyDNS yes. Ils ne sont crus automatiquement que si la réponse DNS est sécurisée, ce qui signifie en pratique des zones signées et un résolveur qui les valide. Sinon, le comportement est celui de ask : il vous montre la correspondance, et vous confirmez quand même. La valeur par défaut est no.
Questions
Où se trouve le fichier known_hosts ?
Dans ~/.ssh/known_hosts, dans votre dossier personnel, sur tout système avec OpenSSH. Un fichier commun à tout le système peut aussi exister dans /etc/ssh/ssh_known_hosts.
Peut-on supprimer known_hosts ?
Il ne contient que des clés publiques, donc rien de secret n'est perdu. Mais ssh redemande alors pour chaque serveur, et vous perdez la vérification qui détecte une clé changée. Supprimez plutôt un seul hôte avec ssh-keygen -R.
Comment supprimer un hôte de known_hosts ?
Lancez ssh-keygen -R server, écrit '[server]:2222' si le port n'est pas 22. Cela marche aussi avec les fichiers hachés.
Sources
- sshd(8), format du fichier SSH_KNOWN_HOSTS
- ssh_config(5), manuel OpenBSD
- ssh-keygen(1), manuel OpenBSD
- ssh-keyscan(1), manuel OpenBSD