Votre rotation des clés d’hôte SSH est-elle prête ?
Planifiez la rotation des clés d’hôte SSH avec chevauchement, empreintes publiées, fenêtre contrôlée et tests de révocation fiables.

Une clé d’hôte SSH doit changer selon votre calendrier, lorsque sa remplaçante est déjà approuvée. Si les développeurs découvrent la rotation avec l’avertissement rouge du terminal, le plan a déjà échoué. Cet avertissement ne dit pas si le serveur a changé légitimement ou si quelqu’un intercepte la connexion. Demander dans l’urgence de supprimer une ligne de known_hosts détruit les preuves nécessaires à la décision.
Une rotation sûre comporte quatre actions distinctes : publier les anciennes et nouvelles empreintes par un canal fiable, proposer les deux clés assez longtemps pour que les clients apprennent la nouvelle, retirer l’ancienne pendant une fenêtre définie et prouver que les clients refusent l’identité retirée. J’ai vu des équipes réussir le travail côté serveur tout en enseignant la pire habitude aux développeurs : traiter la vérification de l’hôte comme un obstacle. Le travail d’exploitation consiste à rendre le chemin sûr ordinaire avant l’alerte.
L’identité de l’hôte diffère de l’authentification utilisateur
Une clé d’hôte prouve quel serveur SSH répond ; une clé utilisateur prouve qui demande à se connecter. La rotation de l’une ne change pas l’autre. Cette distinction semble élémentaire, mais les procédures mélangent souvent authorized_keys, clés personnelles, certificats d’hôte et fichiers /etc/ssh/ssh_host_* sous l’instruction vague « faire tourner les clés SSH ».
La RFC 4253 place l’authentification du serveur dans la négociation de transport. Le serveur signe le hash de l’échange avec sa clé privée d’hôte ; le client compare la clé publique à une source fiable comme known_hosts, une autorité de certification d’hôte ou des enregistrements SSHFP authentifiés. Mots de passe, certificats et clés utilisateur arrivent ensuite. Sans contrôle du serveur, un développeur peut remettre des identifiants parfaitement valides à un imposteur.
L’avertissement de changement est donc volontairement sévère. Il signale une rupture de continuité : le nom saisi présente une autre identité. Remplacement prévu, machine virtuelle reconstruite, répartiteur dirigé vers le mauvais groupe, DNS altéré et interception active peuvent sembler identiques. Le client ne voit pas votre ticket de changement.
Écrivez le périmètre avant de générer quoi que ce soit. Recensez chaque nom et alias, port non standard, adresse inscrite dans un script, bastion, runner CI, agent de déploiement et GlobalKnownHostsFile partagé. [host]:port et host sont deux noms distincts ; un alias peut masquer la destination canonique. Couvrir git.example.net mais oublier git.internal produira une panne apparemment intermittente, même s’ils mènent à la même machine.
Recensez aussi chaque algorithme de clé d’hôte proposé. Un serveur peut posséder simultanément des clés Ed25519, ECDSA et RSA. OpenSSH négocie avec le client ; deux développeurs peuvent donc épingler des clés publiques différentes pour le même daemon. Changer uniquement celle de votre portable ne définit pas l’identité complète. Prenez les directives HostKey et les fichiers publics vérifiés comme inventaire officiel, puis comparez-les aux négociations des groupes de clients pris en charge.
Publiez les deux empreintes avant de modifier le serveur
Publiez l’empreinte actuelle et sa remplaçante pendant que l’ancienne sert encore le trafic. Le canal ne doit pas tirer sa confiance de l’hôte en cours de changement. Un dépôt d’exploitation signé, une page interne authentifiée, une configuration d’appareils gérée ou une zone DNSSEC administrée séparément conviennent. Un message copié depuis la session SSH potentiellement interceptée ne convient pas.
Calculez les empreintes depuis les fichiers publics sur une machine d’administration fiable, pas en demandant au réseau de production ce qu’il présente. OpenSSH affiche SHA-256 par défaut :
$ ssh-keygen -lf ssh_host_ed25519_key.pub -E sha256
256 SHA256:<base64-fingerprint> host.example.net (ED25519)
Publiez davantage que le résumé. Pour chaque identité, donnez nom, port, algorithme, empreinte SHA-256, état (current, new ou retired), début d’utilisation, retrait et approbateur. Précisez le fuseau horaire. Listez les alias communs. Si plusieurs nœuds derrière un nom présentent volontairement des clés différentes, publiez l’ensemble autorisé et sa raison.
Un enregistrement utile ressemble à ceci :
Host: build.example.net:22
Algorithm: ssh-ed25519
Current: SHA256:<old-fingerprint>
New: SHA256:<new-fingerprint>
Overlap begins: 2026-08-10 15:00 UTC
Old key removed: 2026-08-17 15:00 UTC
Old key marked revoked: 2026-08-17 15:30 UTC
Owner: Platform operations
Les dates illustrent, mais l’ordre est impératif. Publier après le changement transforme une opération prévue en décision de confiance improvisée. Ne publier que la nouvelle valeur empêche la comparaison avec l’épingle existante. Laissez l’ancien enregistrement visible comme retiré afin d’identifier une machine obsolète ou une réutilisation inattendue.
Les empreintes sont publiques. La clé privée reste protégée sur le serveur, mais diffusez assez largement la clé publique et l’empreinte pour ne pas dépendre d’un administrateur disponible. Traitez l’approbation comme un changement de sécurité : deux fichiers sources donnant la même empreinte valent mieux qu’une capture collée dans une conversation.
Le chevauchement transmet la remplaçante en sécurité
Servez les deux clés avant de retirer l’ancienne. Pendant ce chevauchement, un client authentifie le serveur avec l’ancienne clé fiable, puis apprend la nouvelle via [email protected]. La continuité vient de l’ancienne ; la nouvelle n’arrive donc pas comme une affirmation non authentifiée.
Le manuel ssh_config décrit UpdateHostKeys comme une aide à la rotation progressive et précise ses limites. Le client n’accepte des clés supplémentaires qu’après authentification par une clé simple déjà approuvée ou explicitement acceptée, au moyen du fichier utilisateur. Ce mécanisme ne fonctionne pas après un certificat d’hôte ni avec le seul fichier global. Il peut aussi être désactivé si l’utilisateur remplace UserKnownHostsFile ou active VerifyHostKeyDNS.
Ne supposez pas la valeur par défaut. Inspectez la configuration effective :
$ ssh -G build.example.net | grep -E '^(updatehostkeys|userknownhostsfile|stricthostkeychecking) '
stricthostkeychecking ask
updatehostkeys true
userknownhostsfile ~/.ssh/known_hosts ~/.ssh/known_hosts2
Sur le serveur, gardez deux fichiers privés séparés et déclarez-les. Ces chemins sont des exemples :
HostKey /etc/ssh/ssh_host_ed25519_key_old
HostKey /etc/ssh/ssh_host_ed25519_key_new
Exécutez sshd -t avant le rechargement. Selon le manuel, ce mode vérifie la configuration et l’état des clés, et détecte ainsi fichier illisible ou réglage invalide avant relecture. Rechargez plutôt que d’interrompre les sessions, sauf consigne différente du gestionnaire. Connectez ensuite un client propre qui ne connaît que l’ancienne clé et inspectez son fichier isolé après une session authentifiée.
Plusieurs clés configurées ne garantissent pas que tous les clients négocient la même. Préférences d’algorithmes, âge du client, HostKeyAlgorithms personnalisé, certificats et magasins globaux influent. Gardez le chevauchement pendant au moins un cycle normal de chaque classe de client. Des portables hebdomadaires et des workers CI actifs toutes les minutes n’ont pas besoin de la même fenêtre.
Mesurez l’adoption sans prétendre voir tous les known_hosts personnels. Les clients gérés peuvent signaler la présence de la nouvelle clé. Pour les autres, observez les connexions par version si la politique le permet, publiez une commande de vérification et laissez un chevauchement couvrant l’usage normal. Le silence ne prouve pas la propagation.
La fenêtre exige des états et des critères d’arrêt
Une fenêtre doit définir des états observables, des responsables et les conditions de retour. « Rotation à 15 h » ne dit rien du chevauchement, de la préparation ni de l’instant où l’ancienne identité devient interdite. Placez la transition de confiance sur la même chronologie que le déploiement.
Utilisez cinq jalons :
- Publication terminée : des réviseurs reproduisent toutes les empreintes depuis les fichiers approuvés.
- Chevauchement actif : le serveur propose les deux identités, passe
sshd -t, et les clients propres s’authentifient par l’ancienne tout en apprenant la nouvelle. - Préparation atteinte : les magasins gérés contiennent la remplaçante, les tests couvrent systèmes et routes, et le support possède les empreintes exactes.
- Bascule terminée : le serveur ne propose plus l’ancienne privée, les nouvelles sessions réussissent avec contrôle strict et aucun nœud imprévu ne la présente.
- Révocation prouvée : un endpoint de test présentant l’ancienne identité est refusé, tandis que son empreinte reste publiée comme révoquée.
Donnez à une personne le pouvoir d’arrêter. Arrêtez si un nœud montre une clé non publiée, si une route sort de l’inventaire, si un client pris en charge ne reçoit pas la remplaçante ou si revenir exige une clé présumée compromise. Une rotation ordinaire peut revenir pendant le chevauchement ; un incident ne peut pas considérer une clé compromise comme sûre.
Séparez retour du service et retour de confiance. Vous pouvez rétablir un ancien paquet sans restaurer l’identité retirée. Gardez configuration connue, accès à la nouvelle privée et console disponibles. Si SSH est l’unique moyen de réparer SSH, la fenêtre contient un point de défaillance caché.
Couvrez les connexions multiplexées longues. Un maître OpenSSH peut rester actif pendant que de nouveaux shells réutilisent le transport ; ils ne vérifient pas la nouvelle identité. Fermez les maîtres de test avec ssh -O exit host si nécessaire et imposez de nouvelles connexions TCP aux sondes.
Fixez précisément le retrait et maintenez la communication ensuite. Un développeur de retour de congé aura une ancienne épingle. Il doit recevoir un échec documenté et une procédure vérifiée, pas une exception. Le support compare d’abord les empreintes, trouve l’entrée avec ssh-keygen -F, puis la remplace depuis le registre approuvé.
Répétez l’avertissement avec un fichier isolé
Testez sans toucher au vrai ~/.ssh/known_hosts. Un fichier isolé rend chaque état reproductible et empêche qu’une clé apprise des mois auparavant fausse le résultat. Utilisez un endpoint de préproduction reproduisant la séquence, ou un sshd temporaire sur un autre port avec les mêmes contraintes.
Créez known_hosts.test depuis l’ancienne clé publique approuvée, jamais depuis un scan direct. Connectez-vous en fixant le nom logique avec HostKeyAlias :
$ ssh -F /dev/null \
-o HostKeyAlias=build.example.net \
-o UserKnownHostsFile=./known_hosts.test \
-o GlobalKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=yes \
-o UpdateHostKeys=yes \
-p 2222 test-host.example.net true
La première exécution réussit avec les deux clés. Inspectez avec ssh-keygen -F build.example.net -f ./known_hosts.test, confirmez la remplaçante et comparez chaque empreinte à la publication. Un code zéro prouve la connexion, pas l’ensemble d’identités.
Faites ensuite servir uniquement la nouvelle clé et ouvrez une nouvelle connexion. Elle doit réussir grâce à l’apprentissage authentifié. Restaurez une copie ne contenant que l’ancienne épingle et recommencez : avec StrictHostKeyChecking=yes, l’échec est obligatoire. Ce cas prouve que les clients ayant manqué le chevauchement s’arrêtent.
Présentez enfin une clé étrangère. Conservez le message et le code pour la procédure. Ne rendez pas le test permissif pour le faire réussir : le rejet est précisément la protection attendue. Vérifiez que les scripts transmettent le code non nul au lieu de le masquer dans une boucle.
N’utilisez jamais StrictHostKeyChecking=no. Le manuel actuel indique qu’il permet certaines clés changées, alors que accept-new les refuse. Ce dernier ne résout pas la rotation d’un nom déjà connu. Fournissez des données authentifiées ou le chevauchement.
La révocation doit refuser, pas seulement nettoyer
Retirer l’ancienne privée du serveur prévu prouve seulement que ce serveur ne la sert plus. Révoquer signifie que les clients refusent sa publique si elle réapparaît sur un nœud oublié ou chez un attaquant. Supprimer la ligne de known_hosts efface au contraire la mémoire nécessaire.
Les fichiers OpenSSH acceptent le marqueur @revoked. Une clé correspondante n’est jamais acceptée et déclenche un avertissement. Distribuez une entrée globale ou un fichier dédié, avec l’exacte clé approuvée et une portée réfléchie :
@revoked build.example.net ssh-ed25519 <old-public-key-data>
Une Key Revocation List convient aux ensembles importants et aux certificats. Créez une KRL de test et interrogez-la :
$ ssh-keygen -k -f revoked-hostkeys.krl ssh_host_ed25519_key_old.pub
$ ssh-keygen -Q -f revoked-hostkeys.krl ssh_host_ed25519_key_old.pub
ssh_host_ed25519_key_old.pub (<comment>): REVOKED
La requête renvoie un statut non nul pour une clé révoquée ; l’automatisation doit l’interpréter volontairement. Configurez RevokedHostKeys, exigez le refus de l’ancien endpoint puis le succès du nouveau. Un fichier invalide peut sinon bloquer toutes les connexions.
ssh-keygen -R host édite les fichiers aux noms hachés, mais ne révoque rien. Il retire toutes les entrées, y compris la remplaçante, et remet la prochaine connexion en situation de nouvelle confiance. Ne l’utilisez qu’après comparaison puis ajout approuvé. L’enchaîner avec ssh-keyscan non authentifié automatise l’abandon de confiance.
Conservez le matériel public révoqué. Vous pouvez détruire une privée retirée non compromise selon la politique, mais gardez publique, empreinte, approbation et résultat de test. Ils identifieront une ancienne image revenue plus tard.
L’automatisation doit échouer fermée sans devenir fragile
Les tâches non interactives ont besoin d’une source de confiance maintenue, pas d’un contrôle désactivé. CI, déploiement et agents de programmation autonomes rencontrent souvent la rotation d’abord. Quand une image contient une seule clé sans propriétaire pour son renouvellement, le correctif d’urgence devient StrictHostKeyChecking=no, transformant un défaut de disponibilité en défaut d’authentification.
Choisissez un modèle par classe : inclure les deux clés pendant le chevauchement, monter un fichier global géré, produire les lignes approuvées par KnownHostsCommand, utiliser SSHFP avec DNSSEC ou une CA d’hôte. Le manuel précise que la commande complète les fichiers normaux et arrête la connexion en cas d’échec. C’est le bon comportement, mais le service de confiance doit être disponible.
Rendez le mode batch explicite :
Host build.example.net
BatchMode yes
StrictHostKeyChecking yes
UserKnownHostsFile /etc/company/ssh_known_hosts
UpdateHostKeys no
UpdateHostKeys no est volontaire ici : la gestion de configuration possède le fichier. Laisser chaque worker éphémère le modifier crée un état perdu et non audité. Dans un fichier utilisateur persistant, yes peut convenir. Le propriétaire de la distribution décide.
Testez alias, bastions, IP directes et ports comme des identités distinctes. ProxyJump authentifie toujours la destination et le saut a sa propre épingle. Conteneurs et agents isolés peuvent employer un fichier en lecture seule, un autre binaire ou ignorer le répertoire utilisateur. Exécutez ssh -G target dans l’environnement réel.
Pour le SSH piloté par agent, séparez identifiants et confiance d’hôte. Sallyport exécute les actions via sp-ssh tandis que les clés restent dans son coffre chiffré ; l’agent ne reçoit pas les secrets. Cette garde ne remplace pas une source d’identité authentifiée ni un refus testé.
Un échec doit nommer empreintes attendue et observée sans données privées. Ne réessayez pas avec un réglage plus faible. Arrêtez, conservez stderr et la configuration effective, puis transmettez au responsable.
Répétez depuis un worker jetable sans état de répertoire personnel. Donnez-lui exactement le bundle géré, lancez la vraie tâche et archivez ssh -G. Vous détecterez un succès trompeur dû à une ancienne session ayant rempli un fichier non déclaré.
Retirez la remplaçante d’une copie du bundle après la bascule pour tester l’échec. La tâche doit s’arrêter avant la commande distante et préserver le statut SSH. Redistribuez puis recommencez. Si le framework transforme tout en délai dépassé, corrigez cela avant la fenêtre afin de distinguer identité refusée, réseau et utilisateur.
Repérez la confiance trop large. Un joker peut valider une clé pour plusieurs noms ; des clés partagées rendent des machines indistinguables. Ces choix peuvent être voulus, mais le registre doit préciser leur portée. Préférez une ligne propre à chaque identité et testez le nom exact de la tâche.
Figez enfin le binaire SSH et le contrat de configuration des tâches autonomes. Une mise à jour d’image peut changer les valeurs par défaut en même temps que l’identité. Capturez version, algorithmes, hash du fichier et nom logique avant et après pour distinguer mauvais serveur, clé absente et négociation impossible.
DNS et certificats changent la distribution
SSHFP et les certificats réduisent la gestion par hôte, sans supprimer la rotation. Ils déplacent l’ancre stable. Employez-les si vous savez mieux gérer cette ancre que des milliers d’entrées.
La RFC 4255 exige un DNS authentifié avant de faire confiance à SSHFP. DNSSEC doit être validé du client au record. Un DNS non signé aide à comparer, mais n’établit pas l’identité contre un attaquant. VerifyHostKeyDNS yes ne fait confiance implicitement qu’aux correspondances sécurisées.
Publiez les deux records pendant le chevauchement, attendez les caches, puis retirez l’ancien avec la privée. Générez-les par ssh-keygen -r hostname -f public_key_file depuis les fichiers approuvés. Vérifiez record et validation sur le chemin réel. Un TTL court ne répare ni DNSSEC cassé ni une mauvaise valeur.
Les certificats permettent une confiance comme @cert-authority *.example.net. Une nouvelle clé certifiée avec principaux et validité corrects passe sous la CA existante. C’est propre pour une flotte dynamique, mais la CA est puissante : protégez sa privée, limitez l’émission, journalisez numéros et principaux, testez sa révocation.
Ne déployez pas une CA pour éviter une seule rotation gênante. Elle ajoute émission, expiration, nommage et rotation de CA. Une petite flotte stable gère bien des épingles explicites ; une grande flotte éphémère profite souvent des certificats.
Documentez le début de la confiance. UpdateHostKeys ne s’applique pas après certificat, et un fichier global n’apprend pas via le fichier utilisateur. Mélanger sans priorité donne un succès sur portable et un échec en CI.
Terminez avec des preuves durables
Une rotation achevée prouve ce qui a changé, qui a approuvé, ce que les clients ont accepté et si l’ancien a été refusé. Gardez clés publiques, empreintes reproduites, résultat sshd -t, configuration effective, révision publiée, matrice client, horodatages, révocation et test négatif. Aucune privée dans le ticket.
Relevez l’état réel après la fenêtre. Interrogez chaque nœud par chaque route et comparez à l’ensemble approuvé, en sachant que la collecte réseau n’est qu’une observation. Comparez-la à la publication authentifiée. Vérifiez images d’autoscaling et nœuds éteints : une ancienne clé revient souvent avec une capacité de remplacement.
Activity journal et Sessions journal de Sallyport peuvent conserver une trace résistante aux altérations des actions SSH d’un agent, issue d’un journal chiffré chaîné par hashes. sp audit verify contrôle cette chaîne hors ligne sur le texte chiffré sans clé du coffre, ajoutant une preuve d’action sans remplacer les tests d’hôte.
Planifiez un suivi selon la flotte. Cherchez clients bloqués par l’ancienne empreinte, nœuds inattendus et scripts ayant reçu des options de contournement. Retirez le chevauchement temporaire. Maintenez la révocation tant que la privée peut survivre dans une sauvegarde, une image ou une copie non autorisée.
L’avertissement doit rester rare et alarmant. Une bonne rotation ne le supprime pas. Elle organise assez tôt la transition pour que les clients attendus ne l’ignorent jamais, puis prouve qu’il bloque encore l’ancienne identité si elle revient.
FAQ
À quelle fréquence faut-il changer les clés d’hôte SSH ?
Fixez un cycle adapté à la garde des clés, aux images et aux obligations ; aucun intervalle universel ne sécurise toutes les flottes. Changez immédiatement après une exposition suspectée et répétez assez souvent la procédure normale pour connaître l’urgence.
Peut-on changer une clé sans déconnecter les utilisateurs ?
Les sessions existantes continuent généralement car leur négociation est terminée. Rechargez la configuration validée et testez de nouvelles connexions TCP, car sessions et maîtres multiplexés ne contrôlent pas la nouvelle identité.
Pourquoi SSH indique-t-il que l’identité distante a changé ?
L’identité stockée ne correspond pas à la clé présentée. Rotation prévue, interception, erreur DNS, reconstruction ou backend imprévu produisent le même avertissement ; vérifiez donc l’empreinte séparément.
Peut-on supprimer l’ancienne entrée known_hosts sans risque ?
Seulement après comparaison avec l’ancienne empreinte publiée et installation fiable de la remplaçante. Une suppression aveugle efface la preuve et transforme la prochaine connexion en nouvelle décision de confiance.
StrictHostKeyChecking accept-new gère-t-il la rotation ?
Non. accept-new ajoute un hôte inconnu mais refuse une clé changée pour une identité stockée. Utilisez chevauchement authentifié, données gérées, SSHFP avec DNSSEC ou certificats.
Combien de temps les clés doivent-elles se chevaucher ?
Au moins un cycle normal pour chaque classe de client. Basez la durée sur le comportement observé et fixez une heure de retrait au lieu de garder l’ancienne indéfiniment.
ssh-keyscan peut-il vérifier la nouvelle clé ?
Il rapporte ce que présente l’endpoint, mais cette observation ne s’authentifie pas elle-même. Comparez-la à l’empreinte d’un fichier approuvé ou d’une autre source indépendante.
Quelle différence entre retrait et révocation ?
Le retrait empêche le serveur prévu de proposer l’ancienne privée. La révocation oblige les clients à refuser sa publique partout où elle réapparaît ; testez les deux.
La CI doit-elle utiliser UpdateHostKeys ?
Seulement si le worker possède un fichier utilisateur persistant et conserve l’état appris. Les workers éphémères fonctionnent généralement mieux avec un fichier central en lecture seule contenant les deux clés pendant le chevauchement.
Les certificats suppriment-ils la rotation ?
Ils réduisent les mises à jour par hôte en déplaçant la confiance vers une CA, mais serveurs, clés et certificats changent toujours. Il faut aussi protéger, émettre, expirer, révoquer et finalement faire tourner la CA.