Mode opératoire — Les clés SSH : comprendre, créer, déployer, gérer
Document autonome et universel. Partie 1 théorique, parties suivantes applicables à Linux, macOS et Windows. Les exemples s’appuient sur l’infrastructure
sio.internalmais la méthode vaut partout.Dernière mise à jour : 01/10/2026
Sommaire
| § | Contenu |
|---|---|
| 1 | Théorie — pourquoi une clé plutôt qu’un mot de passe |
| 2 | Comment ça marche réellement : le défi-réponse |
| 3 | Les deux familles de clés qu’on confond toujours |
| 4 | Choisir l’algorithme · la phrase de passe |
| 5 | Générer une clé — Linux · macOS · Windows |
| 6 | Déployer la clé publique — et le piège Windows |
| 7 | L’agent SSH — saisir sa phrase de passe une seule fois |
| 8 | ~/.ssh/config — le fichier qui change tout |
| 9 | Le serveur de rebond (bastion / jump host) et ProxyJump |
| 10 | Durcir le serveur |
| 11 | Confiner une clé à une seule commande |
| 12 | Cycle de vie : inventaire, rotation, révocation |
| 13 | Les 8 pièges rencontrés · checklist par système |
1 · Théorie — pourquoi une clé plutôt qu’un mot de passe
1.1 Le problème du mot de passe
AUTHENTIFICATION PAR MOT DE PASSE
─────────────────────────────────
Le client ENVOIE le secret au serveur, qui le vérifie.
▲
le secret QUITTE ta machine à chaque connexion
| Faiblesse | Conséquence |
|---|---|
| Le secret voyage | il existe, à chaque connexion, ailleurs que chez toi |
| Le serveur le connaît | un serveur compromis récupère ton mot de passe |
| Il est devinable | 8 à 12 caractères mémorisables = quelques milliards de possibilités |
| Il est rejouable | qui l’obtient peut se connecter indéfiniment |
| Il est testable à distance | d’où les attaques par force brute, et les sshguard pour s’en défendre |
1.2 Ce que la clé change
AUTHENTIFICATION PAR CLÉ
────────────────────────
Le client PROUVE qu'il détient le secret, sans jamais le transmettre.
▲
la clé privée ne quitte JAMAIS ta machine
| Propriété | Effet |
|---|---|
| Le secret ne circule pas | un serveur compromis n’apprend rien d’exploitable |
| 256 bits d’entropie | indevinable en pratique — pas de force brute possible |
| Deux facteurs si phrase de passe | avoir le fichier et savoir la phrase |
| Révocable individuellement | on retire une clé sans toucher aux autres |
La même logique que
unix_socketsous MariaDB, ou qu’une carte à puce. On remplace « connais-tu le secret ? » par « peux-tu prouver que tu le détiens ? ». C’est la différence entre montrer sa clé et la donner.
2 · Comment ça marche réellement
2.1 Deux clés mathématiquement liées
ssh-keygen produit UNE PAIRE
────────────────────────────
id_ed25519 clé PRIVÉE → reste chez toi, ne sort jamais
id_ed25519.pub clé PUBLIQUE → se copie partout, sans risque
Ce qui est chiffré ou signé avec l’une ne peut être vérifié qu’avec l’autre. On ne peut pas retrouver la privée à partir de la publique — c’est le fondement de la cryptographie asymétrique.
La clé publique n’est pas un secret. On peut la publier, l’envoyer par courriel, la coller dans un ticket. Elle ne permet que de vérifier, jamais de se faire passer pour toi. C’est d’ailleurs ce que fait GitHub :
https://github.com/<pseudo>.keysexpose publiquement les clés de chacun.
2.2 Le dialogue, étape par étape
CLIENT SERVEUR
│ │
│ « je suis ipfixe, voici l'empreinte │
│ de la clé que je veux utiliser » │
│ ───────────────────────────────────────►│
│ │ cherche cette empreinte
│ │ dans ~/.ssh/authorized_keys
│ │
│ ◄───────────────────────────────────── │ « trouvée. Signe ceci. »
│ un défi aléatoire │ (nombre aléatoire)
│ │
│ signe le défi avec la clé PRIVÉE │
│ ───────────────────────────────────────►│
│ │ vérifie la signature
│ │ avec la clé PUBLIQUE
│ ◄───────────────────────────────────── │
│ accès accordé │
À aucun moment la clé privée n’est transmise. Le serveur n’apprend rien qu’il pourrait rejouer : le défi est différent à chaque connexion.
C’est pourquoi une clé publique volée est sans valeur. Elle permet de vérifier une signature, pas d’en produire une.
3 · Les deux familles de clés — ne jamais les confondre
C’est la confusion la plus fréquente, et elle rend les messages d’erreur incompréhensibles.
CLÉ D'UTILISATEUR CLÉ D'HÔTE
───────────────── ──────────
« qui suis-je ? » « à qui je parle ? »
le CLIENT prouve son identité le SERVEUR prouve la sienne
~/.ssh/id_ed25519 (privée) /etc/ssh/ssh_host_ed25519_key (privée)
~/.ssh/id_ed25519.pub (publique) /etc/ssh/ssh_host_ed25519_key.pub (publique)
vérifiée via vérifiée via
~/.ssh/authorized_keys ~/.ssh/known_hosts
sur le serveur sur le client
| Symptôme | Famille concernée |
|---|---|
Permission denied (publickey) | clé d’utilisateur — le serveur ne te reconnaît pas |
REMOTE HOST IDENTIFICATION HAS CHANGED! | clé d’hôte — le serveur n’est plus celui que tu connaissais |
The authenticity of host … can't be established | clé d’hôte — première rencontre |
3.1 Pourquoi les clés d’hôte comptent
Elles protègent de l’usurpation de serveur. Sans elles, un intercepteur pourrait se placer entre toi et la machine visée, recueillir ce que tu tapes, et relayer.
Conséquence directe pour le clonage de VM : deux machines clonées partagent leurs clés d’hôte. L’une peut donc se faire passer pour l’autre sans que SSH ne détecte quoi que ce soit. C’est la régénération la moins optionnelle après un clonage — voir MO-1-Clonage-VM.md §3.2.
sudo rm -f /etc/ssh/ssh_host_* && sudo dpkg-reconfigure openssh-server
3.2 known_hosts — le modèle « confiance à la première rencontre »
À la première connexion, le client affiche l’empreinte et demande confirmation. Une fois acceptée, elle est enregistrée — et toute divergence ultérieure déclenche une alerte.
ssh-keygen -F 10.0.20.11 # l'entrée est-elle présente ?
ssh-keygen -R 10.0.20.11 # la supprimer (après un légitime changement)
ssh-keyscan -H 10.0.20.11 >> ~/.ssh/known_hosts # l'ajouter d'avance
ssh-keyscanest indispensable pour l’automatisation. Un démon —lsyncd, une sauvegarde, un déploiement — ne peut pas répondre à la question « voulez-vous continuer ? ». Il faut enregistrer l’empreinte avant de le lancer.Mais
ssh-keyscanaccepte ce qu’il trouve, sans vérifier. Sur un réseau de confiance c’est acceptable ; en environnement sensible, l’empreinte se vérifie par un canal séparé (console de l’hyperviseur, par exemple).
4 · Choisir l’algorithme et la phrase de passe
4.1 Quel algorithme
| Type | Verdict | Pourquoi |
|---|---|---|
ed25519 | par défaut | rapide, clé courte (68 caractères), aucun paramètre à choisir donc rien à se tromper, résistant aux implémentations bancales |
rsa 4096 | compatibilité | pour du matériel ancien qui ignore ed25519. Clé longue, plus lente |
ecdsa | éviter | courbes NIST aux paramètres contestés, et implémentations historiquement fragiles |
dsa | interdit | retiré d’OpenSSH, cassé |
ssh-keygen -t ed25519 -C "axel@lenovo-2026"
-Cest un commentaire libre, stocké en clair à la fin de la clé publique. Il n’a aucun rôle cryptographique mais tout un rôle d’inventaire : c’est lui qu’on lit dans unauthorized_keyspour savoir à qui appartient une clé. Un format utile :utilisateur@machine-anneeouusage-machine.
4.2 La phrase de passe
SANS phrase de passe AVEC phrase de passe
──────────────────── ────────────────────
1 facteur : AVOIR le fichier 2 facteurs : AVOIR + SAVOIR
vol du disque = accès total vol du disque = rien d'exploitable
utilisable par un démon nécessite un agent (§7)
| Usage | Recommandation |
|---|---|
| Ta clé personnelle d’administration | phrase de passe obligatoire + agent |
| Clé de service (sauvegarde, synchronisation) | sans phrase, mais confinée par command= — voir §11 |
La règle : une clé sans phrase de passe se justifie uniquement si elle est enfermée dans une action précise sur une machine précise. Une clé sans phrase et sans restriction, c’est un mot de passe en clair dans un fichier.
Changer la phrase d’une clé existante — sans régénérer la clé :
ssh-keygen -p -f ~/.ssh/id_ed25519
5 · Générer une clé
5.1 Linux et macOS
ssh-keygen -t ed25519 -C "axel@lenovo-2026"
| Question | Réponse |
|---|---|
Enter file in which to save the key | Entrée pour le défaut, ou un chemin dédié |
Enter passphrase | une vraie phrase — elle ne s’affiche pas pendant la frappe |
5.2 Windows 10 / 11 / Server 2019+
OpenSSH est intégré depuis Windows 10 1809 — rien à installer pour le client.
ssh-keygen -t ed25519 -C "axel@poste-windows-2026"
Les fichiers atterrissent dans C:\Users\<toi>\.ssh\.
Le serveur SSH, lui, n’est pas installé par défaut sous Windows :
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 Start-Service sshd Set-Service -Name sshd -StartupType AutomaticLes deux dernières commandes sont nécessaires :
Start-Servicedémarre maintenant,Set-Servicerend le démarrage automatique. Sans la seconde, l’accès est perdu au prochain redémarrage.Et par défaut, une session SSH Windows ouvre
cmd.exe. Pour obtenir PowerShell :New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
5.3 Les fichiers produits et leurs droits
| Fichier | Contenu | Droits Linux/macOS |
|---|---|---|
id_ed25519 | clé privée | 600 |
id_ed25519.pub | clé publique | 644 |
~/.ssh/ | le répertoire | 700 |
~/.ssh/authorized_keys | clés autorisées à entrer | 600 |
~/.ssh/known_hosts | empreintes des serveurs connus | 644 |
chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519 ~/.ssh/authorized_keys 2>/dev/null
SSH refuse d’utiliser une clé privée trop permissive et affiche
UNPROTECTED PRIVATE KEY FILE!. Ce n’est pas un excès de zèle : sur une machine partagée, un fichier lisible par tous annule tout l’intérêt de la clé.
Vérifier l’empreinte d’une clé :
ssh-keygen -lf ~/.ssh/id_ed25519.pub
6 · Déployer la clé publique
6.1 Linux et macOS — ssh-copy-id
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
L’outil se connecte une dernière fois par mot de passe, ajoute la clé à authorized_keys, et
pose les bons droits tout seul. C’est la méthode à privilégier.
6.2 Sans ssh-copy-id — la méthode manuelle
cat ~/.ssh/id_ed25519.pub | ssh [email protected] "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Ne JAMAIS copier-coller une clé à la main depuis un terminal. Une clé publique fait une ligne d’environ 100 caractères ; un terminal la replie à l’affichage, et le collage réintroduit ces retours à la ligne. La clé devient invalide sans aucun message d’erreur — l’authentification échoue simplement.
(Piège rencontré dans ce TP lors de la mise en place de l’accès SSH à pfSense.)
Le contrôle qui tranche :
authorized_keysdoit contenir une ligne par clé.wc -l ~/.ssh/authorized_keys
6.3 Windows — le piège des comptes administrateurs
C’est la particularité Windows, et elle fait perdre des heures.
Compte STANDARD → C:\Users\<nom>\.ssh\authorized_keys
Compte ADMINISTRATEUR → C:\ProgramData\ssh\administrators_authorized_keys
▲
fichier COMMUN à tous les administrateurs
Si le compte appartient au groupe Administrateurs, OpenSSH ignore son
authorized_keys personnel et ne lit que le fichier commun.
# depuis le client, envoyer la clé
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | ssh admin@10.0.40.100 "powershell -Command `"Add-Content -Path C:\ProgramData\ssh\administrators_authorized_keys -Value ([Console]::In.ReadToEnd())`""
Puis, sur la machine Windows, corriger les droits — sans quoi le fichier est ignoré :
icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant "SYSTEM:F" /grant "Administrateurs:F"
Seuls
SYSTEMetAdministrateursdoivent y avoir accès. OpenSSH vérifie ces droits et refuse silencieusement le fichier s’ils sont plus larges. Aucun message côté client : on tombe simplement sur la demande de mot de passe.Le diagnostic, côté serveur Windows :
Get-Content C:\ProgramData\ssh\logs\sshd.log -Tail 20(activer le journal détaillé via
LogLevel DEBUG3dansC:\ProgramData\ssh\sshd_config)
6.4 Vérifier que ça fonctionne
ssh -o PreferredAuthentications=publickey -o BatchMode=yes [email protected] true ; echo "code : $?"
0 = la clé fonctionne seule. Ces options interdisent le repli sur le mot de passe : sans
elles, un succès pourrait masquer un échec de la clé.
7 · L’agent SSH
7.1 Le problème qu’il résout
Une clé protégée par phrase de passe la réclame à chaque connexion. L’agent la garde déchiffrée en mémoire pour la durée de la session.
sans agent : phrase saisie à CHAQUE connexion → tentation de retirer la phrase
avec agent : phrase saisie UNE FOIS par session
L’agent est ce qui rend la phrase de passe supportable — et donc ce qui la rend réellement utilisée. Un mécanisme de sécurité pénible finit toujours par être contourné.
7.2 Linux
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add -l # lister les clés chargées
Pour éviter de le relancer à chaque terminal, la plupart des bureaux démarrent un agent
automatiquement. Sinon, ajouter à ~/.bashrc :
[ -z "$SSH_AUTH_SOCK" ] && eval "$(ssh-agent -s)" > /dev/null
7.3 macOS — intégration au Trousseau
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
Et dans ~/.ssh/config, pour que ce soit automatique :
Host *
UseKeychain yes
AddKeysToAgent yes
IdentityFile ~/.ssh/id_ed25519
UseKeychainest propre à macOS : la phrase est stockée dans le Trousseau du système et rechargée à l’ouverture de session. Sur Linux ou Windows, cette directive provoque une erreur de configuration — d’où l’intérêt de la placer dans un fichier propre au Mac.
7.4 Windows
Le service existe mais est désactivé par défaut :
Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519
ssh-add -l
L’agent Windows stocke les clés dans le registre, chiffrées par DPAPI — liées à ta session Windows. Elles survivent donc au redémarrage, contrairement à l’agent Linux. Pratique, mais cela signifie qu’une session Windows compromise donne accès aux clés : raison de plus pour verrouiller sa session.
8 · ~/.ssh/config — le fichier qui change tout
C’est le fichier le plus rentable de SSH, et le plus ignoré des débutants.
# ~/.ssh/config (C:\Users\<toi>\.ssh\config sous Windows)
Host *
AddKeysToAgent yes
ServerAliveInterval 60
ServerAliveCountMax 3
Host pfsense
HostName 10.0.30.1
User admin
IdentityFile ~/.ssh/id_lab
Host web1
HostName 10.0.10.10
User ipfixe
IdentityFile ~/.ssh/id_lab
Host mysql1 mysql2 mysql3
User ipfixe
IdentityFile ~/.ssh/id_lab
Host mysql1
HostName 10.0.20.10
Host mysql2
HostName 10.0.20.11
Host mysql3
HostName 10.0.20.12
# Rebond : joindre une machine interne via le bastion
Host interne-*
User ipfixe
IdentityFile ~/.ssh/id_lab
ProxyJump bastion
Host bastion
HostName 10.0.30.12
User ipfixe
IdentityFile ~/.ssh/id_lab
Dès lors : ssh web1 suffit.
| Directive | Rôle |
|---|---|
HostName | l’adresse réelle — l’alias n’est qu’un raccourci |
IdentityFile | quelle clé utiliser pour cet hôte |
ProxyJump | rebondir par une machine intermédiaire, en une seule commande — détaillé au §9 |
ServerAliveInterval | envoie un signal toutes les 60 s — évite les coupures d’inactivité |
AddKeysToAgent | charge la clé dans l’agent à la première utilisation |
8.1 Deux pièges classiques — tous deux rencontrés dans ce TP
1 · Une directive sans valeur casse tout le fichier
Host web1
User
→ Bad configuration option et tout le fichier est ignoré, y compris les blocs valides.
Une directive vide n’est pas « neutre », c’est une erreur de syntaxe.
2 · Le fichier s’applique à l’alias, pas à l’adresse
ssh web1 # IdentityFile appliqué
ssh [email protected] # aucun bloc ne correspond → clé par défaut
SSH compare le nom écrit sur la ligne de commande aux motifs Host. Écrire l’adresse IP
court-circuite la configuration.
Pour contourner ponctuellement :
ssh -F /dev/null …ignore le fichier,ssh -v …affiche quel bloc est appliqué. Le mode verbeux est l’outil de diagnostic numéro un de SSH :ssh -v web1 2>&1 | grep -iE "identity file|offering|authentications"
9 · Le serveur de rebond (bastion / jump host)
9.1 Le problème qu’il résout
Une infrastructure correctement cloisonnée n’expose aucune de ses machines internes. Mais il faut bien les administrer. Deux mauvaises réponses, et la bonne :
| Réponse | Conséquence |
|---|---|
| Ouvrir le port 22 de chaque serveur depuis l’extérieur | autant de portes que de machines, autant de services sshd à surveiller et à durcir |
| Ouvrir une redirection de port par serveur sur le pare-feu | même chose, en plus confus — et la traçabilité est perdue |
| Une seule machine joignable, par laquelle tout passe | une porte, un journal, une politique |
Cette machine s’appelle un bastion (ou jump host, ou serveur de rebond). C’est la seule que le pare-feu autorise en entrée ; toutes les autres ne sont joignables que depuis elle.
┌──────────────── zone exposée ────────────────┐
administrateur ─┤ 22/tcp ► BASTION │
└──────────────────┬───────────────────────────┘
│ 22/tcp — autorisé
┌──────────────────▼─── zone interne ──────────┐
│ srv-web-01 srv-mysql-01 srv-ha … │
│ (injoignables depuis l'extérieur) │
└──────────────────────────────────────────────┘
Le bastion n’est pas une protection magique. Il ne rend pas les serveurs internes plus sûrs : il réduit la surface d’attaque à une seule machine, qu’on peut alors durcir et surveiller sérieusement. Tout l’intérêt est là — et toute la responsabilité aussi : qui compromet le bastion atteint tout le reste.
9.2 Les trois façons de rebondir — seule la troisième est canonique
1 · Se connecter au bastion, puis relancer ssh depuis lui
ssh bastion # première session
ssh [email protected] # seconde session, lancée DEPUIS le bastion
Ça marche, et c’est ce que tout le monde fait au début. Mais :
- la clé privée doit être sur le bastion — ou alors on retape un mot de passe ;
scpetrsyncdeviennent pénibles : il faut copier en deux temps ;- le bastion accumule des clés privées. S’il tombe, toutes tombent avec lui.
2 · Le transfert d’agent (ssh -A, ForwardAgent yes)
L’idée : ne pas poser la clé sur le bastion, mais laisser le bastion utiliser l’agent du poste client à distance.
ssh -A bastion
ssh [email protected] # utilise la clé restée sur le poste client
La clé privée ne quitte effectivement jamais le poste. Mais :
Le transfert d’agent crée une socket sur le bastion. Toute personne disposant de
rootsur cette machine peut s’en servir pour s’authentifier en votre nom, partout où votre clé est acceptée, tant que la session est ouverte. C’est précisément pour cela queauthorized_keyspropose l’optionno-agent-forwarding(voir §11), et que la documentation OpenSSH le déconseille.
Retenir : -A n’est acceptable que vers une machine dont on a la pleine maîtrise — et
il n’est de toute façon plus nécessaire depuis ProxyJump.
3 · ProxyJump — la version canonique
ssh -J bastion [email protected]
ou, mieux, écrit une fois pour toutes dans ~/.ssh/config :
Host bastion
HostName 10.0.30.12
User ipfixe
IdentityFile ~/.ssh/id_lab
Host mysql1
HostName 10.0.20.10
User ipfixe
IdentityFile ~/.ssh/id_lab
ProxyJump bastion
Dès lors, une seule commande suffit :
ssh mysql1
Ce qui se passe réellement — et c’est tout l’intérêt :
poste client bastion mysql1
│ │ │
├──── 1. session SSH ─────────►│ │
│ (authentifiée par ma clé) │ │
│ │ │
├──── 2. demande un tunnel TCP ►├──── vers 10.0.20.10:22 ►│
│ │ (le bastion ne fait │
│ │ QUE relayer des │
│ │ octets chiffrés) │
│ │ │
├══════ 3. seconde session SSH, de bout en bout ════════►│
│ chiffrée entre le poste et mysql1 │
| Conséquence | Pourquoi c’est décisif |
|---|---|
| La clé privée reste sur le poste client | le bastion n’en détient aucune |
| Le bastion ne déchiffre rien | il relaye un flux chiffré de bout en bout |
| Pas de socket d’agent exposée | contrairement à -A |
La clé d’hôte de mysql1 est vérifiée par le client | l’authentification du serveur reste intacte |
Avec
ProxyJump, le bastion est un relais réseau, pas un intermédiaire de confiance. Il voit *qu’*une connexion a lieu, et vers où — pas ce qui y transite. C’est exactement le niveau de confiance qu’on veut lui accorder.
9.3 Ce que ProxyJump rend possible gratuitement
Tout ce qui s’appuie sur SSH en hérite, sans configuration supplémentaire :
scp fichier.sql mysql1:/tmp/ # copie directe, à travers le bastion
rsync -av dossier/ mysql1:/srv/ # idem
sftp mysql1
ssh mysql1 'systemctl status mariadb' # commande distante
Plusieurs rebonds s’enchaînent avec une virgule :
ssh -J bastion1,bastion2 serveur-final
9.4 Deux clés, ou une seule ?
Question légitime : faut-il la même clé pour le bastion et pour les serveurs internes ?
| Approche | Quand la choisir |
|---|---|
Une clé unique id_lab | laboratoire, petite infrastructure — c’est ce qu’on fait ici |
| Deux clés distinctes | production : une clé n’ouvre que le bastion, une autre n’est acceptée que par les serveurs internes. Compromettre le poste client reste nécessaire pour les deux, mais la révocation devient granulaire |
Le principe de §12.1 reste le même : une clé par origine, pas une clé recopiée partout.
9.5 Appliqué à l’infrastructure sio.internal
Dans ce TP, srv-docker (10.0.30.12, VLAN 30 — ADM) joue le rôle de bastion :
| Élément | Valeur |
|---|---|
| Machine | srv-docker · 10.0.30.12 |
| Alias pare-feu | SRV_BASTION |
| Ports autorisés vers lui | PORTS_BASTION — 22 et 3389 |
| Ports autorisés depuis lui | administration des VLAN 10 et 20 |
Bloc ~/.ssh/config correspondant, à placer sur le poste d’administration :
Host bastion
HostName 10.0.30.12
User ipfixe
IdentityFile ~/.ssh/id_lab
Host web1 web2 ha mysql1 mysql2 mysql3
User ipfixe
IdentityFile ~/.ssh/id_lab
ProxyJump bastion
Host web1
HostName 10.0.10.10
Host web2
HostName 10.0.10.11
Host ha
HostName 10.0.10.5
Host mysql1
HostName 10.0.20.10
Host mysql2
HostName 10.0.20.11
Host mysql3
HostName 10.0.20.12
Validation
ssh -v mysql1 2>&1 | grep -iE "proxy|connecting to"
La trace doit montrer une connexion au bastion, puis l’établissement de la session
vers 10.0.20.10. Et sur le bastion, aucune clé privée ne doit apparaître :
ssh bastion 'ls -l ~/.ssh/'
→ authorized_keys et known_hosts uniquement. Aucun fichier id_* sans extension.
Dans ce TP, Tailscale court-circuite le bastion : le poste
ag-lenovojoint directement les VLAN par le routeur de sous-réseaux. C’est pratique, et c’est exactement la dette T-6 relevée dans la documentation — le tailnet est une zone de confiance qui contourne le cloisonnement. Le rebond par bastion est la méthode canonique ; Tailscale est le raccourci qu’on s’autorise en laboratoire, en le sachant.
10 · Durcir le serveur
Une fois les clés en place et testées, on ferme le mot de passe.
/etc/ssh/sshd_config — ou un fragment dans /etc/ssh/sshd_config.d/10-durcissement.conf :
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes
AllowGroups sshusers
MaxAuthTries 3
LoginGraceTime 30
| Directive | Effet |
|---|---|
PasswordAuthentication no | supprime la force brute par construction |
KbdInteractiveAuthentication no | ferme la voie détournée du clavier interactif |
PermitRootLogin prohibit-password | root par clé uniquement — no si un compte sudo suffit |
AllowGroups | seuls les membres du groupe peuvent se connecter |
MaxAuthTries 3 | limite les essais par connexion |
sudo sshd -t && sudo systemctl reload ssh
sshd -tavant tout rechargement, et garder une session ouverte pendant le test. Une erreur de configuration SSH sur une machine distante, c’est une machine perdue jusqu’au prochain accès console. Même réflexe queapache2ctl configtest,haproxy -couphp -l.Le filet de sécurité : la console de l’hyperviseur — Proxmox, VMware, iDRAC. Elle ne dépend ni de SSH ni du pare-feu. Un accès de secours ne doit jamais dépendre du système qu’il secourt.
10.1 Ce que le durcissement rend inutile
Une fois PasswordAuthentication no en place, les protections anti-force-brute (fail2ban,
sshguard, Login Protection de pfSense) n’ont plus grand-chose à défendre : il n’y a plus
de mot de passe à deviner.
Mais elles restent actives et peuvent te bloquer toi, si un client retente en boucle une authentification vouée à l’échec — par exemple un mot de passe périmé resté dans la configuration d’un client. C’est exactement ce qui s’est produit dans ce TP (incident H-13) : trois échecs suffisaient, et chaque blocage durait 1,5 fois plus longtemps que le précédent.
La leçon : après tout changement d’identifiants, passer en revue les endroits où l’ancien secret est encore stocké — clients SSH, gestionnaires de mots de passe, scripts, supervision.
11 · Confiner une clé à une seule commande
Le motif le plus utile pour l’automatisation : une clé qui ne peut faire qu’une chose.
command="/usr/bin/rrsync -wo /var/www/wordpress/wp-content",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAAC3Nza… lsyncd
| Option | Interdit |
|---|---|
command="…" | toute commande autre que celle-ci |
no-pty | l’ouverture d’un terminal interactif |
no-port-forwarding | d’utiliser la connexion comme tunnel |
no-agent-forwarding | de rebondir avec les clés du client |
no-X11-forwarding | le relais graphique |
Le test qui prouve le confinement :
ssh -i ~/.ssh/id_lsyncd [email protected]
PTY allocation request failed on channel 0 ← no-pty
/usr/bin/rrsync error: Not invoked via sshd ← command="…"
Une clé
rootqui ne donne aucun accèsroot. Le privilège appartient à la commande forcée, pas au compte. Motif réutilisable pour toute automatisation : sauvegardes, supervision, déploiements, synchronisation.
SSH_ORIGINAL_COMMANDcontient la commande réellement demandée par le client. Un script de confinement maison peut la lire pour n’autoriser qu’un jeu précis d’actions :case "$SSH_ORIGINAL_COMMAND" in "backup-now") /usr/local/bin/backup.sh ;; *) echo "Commande non autorisee" ; exit 1 ;; esac
12 · Cycle de vie : inventaire, rotation, révocation
12.1 Une clé par origine, pas une clé pour tout
MAUVAIS BON
───────── ──────
une clé recopiée sur une clé par machine d'origine
toutes tes machines + une clé par automatisation
│ │
un vol = tout révoquer un vol = révoquer une seule clé
impossible de savoir le commentaire dit d'où elle vient
laquelle a fuité
Le commentaire -C porte l’inventaire : axel@lenovo-2026, lsyncd-web01-vers-web02,
sauvegarde-nocturne.
12.2 Faire l’inventaire
Sur chaque serveur :
sudo find /home /root -name authorized_keys -exec sh -c 'echo "== $1"; cat "$1"' _ {} \;
Sous Windows :
Get-Content C:\ProgramData\ssh\administrators_authorized_keys
Une clé oubliée dans un
authorized_keysest une porte ouverte permanente. Les clés n’expirent pas toutes seules — contrairement aux mots de passe soumis à une politique de renouvellement. L’inventaire périodique est la seule parade.
12.3 Révoquer
Retirer la ligne correspondante de l’authorized_keys :
ssh-keygen -lf ~/.ssh/id_ed25519.pub # obtenir l'empreinte
sudo sed -i '/AAAAC3NzaC1lZDI1NTE5AAAAI.../d' ~/.ssh/authorized_keys
La révocation est immédiate et locale : pas d’autorité centrale à prévenir, pas de liste à publier. C’est à la fois la force du modèle (simplicité) et sa faiblesse (il faut penser à le faire sur chaque serveur).
12.4 Quand renouveler
| Événement | Action |
|---|---|
| Départ d’une personne | révoquer sa clé partout |
| Poste perdu ou volé | révoquer, régénérer, redéployer |
| Machine clonée | régénérer les clés d’hôte — voir MO-1 |
| Réinstallation d’un serveur | prévenir les clients : l’empreinte d’hôte change |
| Rotation périodique | tous les 1 à 2 ans pour une clé personnelle |
13 · Pièges et checklists
13.1 Les huit pièges rencontrés dans ce TP
| # | Symptôme | Cause | Correction |
|---|---|---|---|
| 1 | Permission denied (publickey) | clé non déployée, ou mauvaise clé proposée | ssh -v pour voir laquelle est offerte |
| 2 | Clé refusée sans message clair | clé collée sur plusieurs lignes depuis un terminal | wc -l authorized_keys → doit valoir 1 par clé |
| 3 | Demande de phrase à chaque connexion | agent non lancé ou clé non chargée | ssh-add · §7 |
| 4 | Bad configuration option, toute la config ignorée | directive sans valeur dans ~/.ssh/config | corriger la ligne fautive |
| 5 | IdentityFile ignoré | connexion par adresse IP et non par l’alias | utiliser l’alias, ou ajouter un bloc Host |
| 6 | Timeout, puis blocages de plus en plus longs | sshguard — un mot de passe périmé dans un client | vider le champ · liste blanche · H-13 |
| 7 | Clé générée pour www-data : inutilisable | son interpréteur est /usr/sbin/nologin | utiliser un compte avec shell + command= |
| 8 | REMOTE HOST IDENTIFICATION HAS CHANGED après clonage | clés d’hôte dupliquées | régénérer sur le clone · MO-1 |
13.2 Checklist — nouvelle VM Linux
Serveur SSH installé et activé
Clés d'hôte régénérées SI la machine est un clone
Clé publique déployée (ssh-copy-id de préférence)
Droits : ~/.ssh 700 · authorized_keys 600 · clé privée 600
Connexion par clé testée AVANT de fermer le mot de passe
PasswordAuthentication no + sshd -t + reload
Bloc ajouté dans ~/.ssh/config côté client
Empreinte enregistrée (ssh-keyscan) si un automate doit s'y connecter
13.3 Checklist — nouvelle machine Windows
Add-WindowsCapability OpenSSH.Server
Start-Service sshd ET Set-Service -StartupType Automatic
DefaultShell = PowerShell (optionnel mais recommandé)
Règle de pare-feu OpenSSH-Server-In-TCP active (créée automatiquement)
Compte ADMIN → C:\ProgramData\ssh\administrators_authorized_keys
icacls : SYSTEM et Administrateurs UNIQUEMENT
Service ssh-agent passé en Automatic si on utilise une phrase de passe
13.4 Checklist — poste client (Linux, macOS, Windows)
Une clé ed25519, avec phrase de passe, commentaire explicite
Agent configuré (Trousseau sur macOS, service sur Windows)
~/.ssh/config avec un bloc par hôte
ProxyJump configuré si l'accès passe par un bastion
Sauvegarde de la clé privée dans un coffre — PAS sur un partage réseau
Inventaire : savoir où chaque clé est déployée
À retenir en une phrase : une clé SSH remplace « connaître un secret » par « prouver qu’on le détient » — et tout le travail d’administration consiste à savoir, à tout moment, quelle clé ouvre quelle porte.
