Ubuntu 24.04 : SSH fonctionnait hier, maintenant « Permission denied » — corrigez les 5 causes les plus courantes

Cet article vous a aidé ?

Il est 09:12. Vous avez un déploiement en cours, un collègue qui attend, et votre terminal vient de répondre par les deux mots les moins utiles en exploitation : Permission denied. Hier vous pouviez SSH sur la machine. Aujourd’hui non. Rien n’« a changé », sauf que tout change toujours.

Ceci est un guide de terrain pour Ubuntu 24.04 (Noble) lorsque SSH cesse de vous laisser entrer. Pas de théorie — la réalité en production : des clés qui marchaient, des comptes qui existaient, des configs qui « devraient être correctes », et des couches de politique qui vous bloquent en silence tout en affirmant que vous avez tort.

Playbook de diagnostic rapide (premier/deuxième/troisième)

Quand SSH passe de « marche » à « Permission denied », ne commencez pas par modifier des fichiers au hasard. Commencez par prouver ce qui se passe, où ça échoue et quel côté ment. Voici le chemin le plus rapide que je connais qui n’engendre pas de nouveaux problèmes en poursuivant l’ancien.

Premier : confirmez que vous touchez la bonne machine et le bon utilisateur

  1. Résolvez la cible et capturez le chemin. Confirmez hostname → IP et si vous passez par un bastion/ProxyJump.
  2. Confirmez le nom d’utilisateur. « Permission denied » signifie souvent « mauvais utilisateur » plus « aucune méthode de secours autorisée ».
  3. Vérifiez la continuité de la clé hôte. Une mauvaise hôte ou une machine reconstruite apparaît comme un changement de clé hôte, mais les gens « réparent » souvent en supprimant known_hosts puis se connectent à la mauvaise chose.

Deuxième : lancez une tentative cliente verbeuse et lisez-la comme un log

  1. Utilisez -vvv une fois. Ne devinez pas ; le client vous dit quelles identités il a proposées et ce qui a été accepté ou rejeté.
  2. Décidez : échoue-t-on au niveau de la séléction de clé, de l’acceptation de la clé hôte, ou de l’autorisation du compte ?

Troisième : inspectez les logs serveur (ou utilisez la console si vous êtes verrouillé dehors)

  1. Si vous avez un chemin privilégié (console cloud, IPMI/iDRAC, console série, KVM), utilisez-le. Ce n’est pas de la triche, c’est pour ça que vous payez.
  2. Lisez journalctl pour sshd et les messages PAM/compte.
  3. Corrigez la chose la plus étroite qui explique les logs. Redémarrer sshd est rarement la solution ; c’est souvent ainsi qu’on transforme une petite erreur en panne.

Ce que signifie réellement « Permission denied » en SSH

Le message est célèbre pour son manque d’aide parce que c’est le client qui résume une négociation en plusieurs étapes. Sur Ubuntu 24.04 avec OpenSSH, « Permission denied » signifie généralement :

  • Le serveur a accepté la connexion, mais aucune méthode d’authentification n’a réussi.
  • Le serveur a rejeté votre clé, mot de passe ou tentative interactive par clavier.
  • Ou, plus subtilement : l’authentification a réussi mais la phase de compte a échoué (PAM, règles d’accès, utilisateur verrouillé, shell invalide), et l’expérience utilisateur se résume toujours à « Permission denied ».

Il existe trois grands ensembles :

  1. Problèmes d’identité côté client : mauvaise clé, mauvais agent, mauvais nom d’utilisateur, mauvaise section config.
  2. Problèmes de fichiers/config côté serveur : permissions cassées, blocs Match, authorized_keys illisible, mauvais chemin AuthorizedKeysFile, etc.
  3. Verrous de politique/compte : utilisateur verrouillé, expiré, restrictions PAM, AllowUsers/DenyUsers, exigences MFA non satisfaites.

Une citation pour vous remettre sur terre quand vous êtes tenté de « juste redémarrer jusqu’à ce que ça marche » :

« L’espoir n’est pas une stratégie. » — Gene Kranz

Faits intéressants et courte histoire (parce que ça compte)

Un peu de contexte vous rendra plus rapide au diagnostic parce que vous cesserez d’attendre que SSH se comporte comme une seule chose monolithique. C’est une pile.

  1. SSH a remplacé rsh/telnet principalement parce que ces anciens outils envoyaient des identifiants en clair. Le modèle de sécurité de SSH explique pourquoi il est exigeant — et pourquoi vous devez l’être aussi.
  2. Les contrôles stricts de permissions d’OpenSSH sont délibérés. Si votre ~/.ssh est écrivable par le groupe, il suppose que quelqu’un d’autre pourrait injecter des clés. Il préfère vous verrouiller que d’être « utile ».
  3. « Permission denied (publickey) » est un résumé côté client. Le serveur peut rejeter les clés pour de nombreuses raisons : mauvais type de clé, mauvais principal, mauvaises permissions, restrictions de forced-command, ou politique de compte.
  4. Les clés hôte sont l’identité du serveur. Elles préviennent les attaques man-in-the-middle. Quand on supprime known_hosts à l’aveugle, on choisit la commodité plutôt que la détection.
  5. PAM peut vous refuser après une authentification réussie. C’est pourquoi les logs comptent : vous pouvez vous « authentifier » et vous faire rejeter à l’étape compte/session.
  6. Les défauts d’OpenSSH évoluent. Algorithmes et tailles de clés acceptables il y a dix ans peuvent être désactivés aujourd’hui. Les mises à jour peuvent « casser » les vieilles clés, surtout RSA faibles.
  7. L’OpenSSH d’Ubuntu s’intègre étroitement avec systemd. Les logs se trouvent généralement dans journald, et le comportement du service (comme l’activation de socket dans certaines configurations) peut changer les attentes.
  8. Les images cloud utilisent souvent des réglages SSH opinionnés. Par exemple : mots de passe désactivés, utilisateurs par défaut spécifiques, et cloud-init qui gère authorized_keys.

Cause n°1 : Vous n’utilisez pas la clé que vous pensez utiliser (agent, identité, fichier)

Ceci est la panne la plus fréquente « ça marchait hier » en pratique parce que ce n’est généralement pas le serveur. C’est vous, votre laptop, votre agent, votre config, votre split-tunnel VPN, votre nouveau terminal, ou un outil de sécurité d’entreprise qui a fait tourner quelque chose pendant la nuit.

Tâche 1 : Lancez une tentative SSH verbeuse et identifiez quelle clé est proposée

cr0x@server:~$ ssh -vvv user@host.example.com
OpenSSH_9.6p1 Ubuntu-3ubuntu13, OpenSSL 3.0.13 30 Jan 2024
debug1: Reading configuration data /home/cr0x/.ssh/config
debug1: Connecting to host.example.com [203.0.113.10] port 22.
debug1: identity file /home/cr0x/.ssh/id_ed25519 type 3
debug1: identity file /home/cr0x/.ssh/id_rsa type 0
debug1: Offering public key: /home/cr0x/.ssh/id_ed25519 ED25519 SHA256:abc... agent
debug1: Authentications that can continue: publickey
debug1: Offering public key: /home/cr0x/.ssh/id_rsa RSA SHA256:def... agent
debug1: Authentications that can continue: publickey
user@host.example.com: Permission denied (publickey).

Ce que cela signifie : Vous avez proposé deux clés. Les deux ont été rejetées. Cela restreint le diagnostic : soit le serveur n’a aucune des clés publiques dans authorized_keys, soit il ne peut pas les lire, soit la politique serveur vous bloque.

Décision : Si vous attendiez une clé différente, corrigez d’abord le client (utilisez explicitement -i, nettoyez ~/.ssh/config ou corrigez l’agent). Si vous attendiez qu’une de ces clés fonctionne, passez aux vérifications côté serveur (Cause n°2 et n°3).

Tâche 2 : Forcez la clé et désactivez la confusion de l’agent

cr0x@server:~$ ssh -i ~/.ssh/prod_ed25519 -o IdentitiesOnly=yes -vv user@host.example.com
debug1: identity file /home/cr0x/.ssh/prod_ed25519 type 3
debug1: Offering public key: /home/cr0x/.ssh/prod_ed25519 ED25519 SHA256:xyz...
debug1: Authentications that can continue: publickey
user@host.example.com: Permission denied (publickey).

Ce que cela signifie : Vous avez définitivement proposé la clé voulue. Ça a quand même échoué.

Décision : Arrêtez de tripoter votre laptop. Allez vérifier que le serveur a la clé publique correspondante et peut la lire.

Tâche 3 : Vérifiez quelles clés votre agent détient réellement

cr0x@server:~$ ssh-add -l
256 SHA256:abc... /home/cr0x/.ssh/id_ed25519 (ED25519)
2048 SHA256:def... /home/cr0x/.ssh/id_rsa (RSA)

Ce que cela signifie : Ce sont les identités que votre agent proposera à moins que vous ne le contraigniez.

Décision : Si la bonne clé manque, ajoutez-la (ssh-add ~/.ssh/prod_ed25519) ou pointez SSH vers elle avec -i et IdentitiesOnly=yes. Si la bonne clé est présente mais rejetée, poursuivez côté serveur.

Tâche 4 : Inspectez la priorité de votre config SSH (le piège silencieux)

cr0x@server:~$ ssh -G host.example.com | sed -n '1,80p'
user user
hostname host.example.com
port 22
identityfile ~/.ssh/id_ed25519
identitiesonly no
proxyjump bastion.example.com
pubkeyauthentication yes
passwordauthentication no

Ce que cela signifie : ssh -G montre la config finale calculée. Si identityfile n’est pas ce que vous attendez — ou si user ne l’est pas — le client fait exactement ce que vous lui avez demandé, juste pas ce que vous vouliez.

Décision : Corrigez ~/.ssh/config pour que les hôtes de production utilisent explicitement IdentityFile et IdentitiesOnly yes. L’ambiguïté est mignonne dans les romans, pas dans le contrôle d’accès.

Blague sèche #1 : Les agents SSH sont comme des collègues « serviables » : ils se présentent sans invitation et proposent la mauvaise identité avec une confiance totale.

Cause n°2 : Permissions/ownership côté serveur corrompues (home, .ssh, authorized_keys)

Si l’authentification par clé SSH fonctionnait puis cesse soudainement, le coupable côté serveur le plus fréquent est un changement de permissions. Cela arrive après :

  • une migration de répertoire home,
  • un chmod -R trop zélé,
  • une restauration depuis une sauvegarde avec de mauvais propriétaires,
  • ou un script de « durcissement » de sécurité qui n’a pas compris les règles d’OpenSSH.

Tâche 5 : Lisez les logs serveur pour les raisons de rejet de clé

Vous aurez besoin d’un accès console ou d’une autre voie privilégiée si SSH est complètement HS.

cr0x@server:~$ sudo journalctl -u ssh -n 80 --no-pager
Aug 07 10:12:01 host sshd[12345]: Authentication refused: bad ownership or modes for directory /home/user
Aug 07 10:12:01 host sshd[12345]: Connection closed by authenticating user user 198.51.100.22 port 51234 [preauth]

Ce que cela signifie : C’est le classique : les permissions sur le home de l’utilisateur (ou sur .ssh) sont trop permissives, ou le propriétaire est incorrect.

Décision : Corrigez ownership et modes. Ne « détendez » pas les réglages sshd pour tolérer de mauvaises permissions ; corrigez l’état du système de fichiers sous-jacent.

Tâche 6 : Vérifiez ownership et modes pour le home et les fichiers SSH

cr0x@server:~$ sudo namei -l /home/user/.ssh/authorized_keys
f: /home/user/.ssh/authorized_keys
drwxr-xr-x root root /
drwxr-xr-x root root home
drwxrwxr-x user user user
drwxr-xr-x user user .ssh
-rw-r--r-- user user authorized_keys

Ce que cela signifie : /home/user est écrivable par le groupe (drwxrwxr-x). C’est suffisant pour qu’OpenSSH refuse les clés, selon la configuration. Même si .ssh semble correct, le répertoire parent peut casser la vérification.

Décision : Retirez l’écriture groupe sur le répertoire home et assurez-vous que l’ownership est correct.

Tâche 7 : Appliquez des permissions sensées (chirurgical, pas chaotique et récursif)

cr0x@server:~$ sudo chown -R user:user /home/user/.ssh
cr0x@server:~$ sudo chmod 0755 /home/user
cr0x@server:~$ sudo chmod 0700 /home/user/.ssh
cr0x@server:~$ sudo chmod 0600 /home/user/.ssh/authorized_keys
cr0x@server:~$ sudo ls -ld /home/user /home/user/.ssh /home/user/.ssh/authorized_keys
drwxr-xr-x  9 user user 4096 Aug  7 10:00 /home/user
drwx------  2 user user 4096 Aug  7 10:01 /home/user/.ssh
-rw-------  1 user user  402 Aug  7 10:01 /home/user/.ssh/authorized_keys

Ce que cela signifie : Ce sont les valeurs conservatrices qui gardent sshd content : home non écrivable par le groupe/les autres ; .ssh privé ; fichier authorized_keys privé.

Décision : Retestez la connexion. Si ça échoue encore et que les logs ne se plaignent plus d’ownership/modes, passez aux causes de config/politique.

Tâche 8 : Confirmez que la clé publique sur le serveur correspond à la clé privée utilisée

Cela évite le terrier du « mauvaise paire de clés ».

cr0x@server:~$ ssh-keygen -lf /home/user/.ssh/authorized_keys | head -n 3
256 SHA256:xyz... comment@laptop (ED25519)
2048 SHA256:old... legacy@laptop (RSA)

Ce que cela signifie : Ce sont les empreintes des clés publiques autorisées. Comparez-les à l’empreinte de votre clé cliente.

Décision : Si le serveur n’a pas la bonne clé, ajoutez-la (de préférence via votre chemin de provisioning standard). Si elle est présente, passez à la configuration sshd et aux politiques.

Cause n°3 : La configuration sshd a changé (AllowUsers, blocs Match, méthodes d’auth)

Sur Ubuntu 24.04, vous exécutez typiquement OpenSSH avec une configuration partagée entre /etc/ssh/sshd_config et des includes dans /etc/ssh/sshd_config.d/. C’est bien. C’est aussi comment un « petit » changement devient une surprise.

Tâche 9 : Validez la configuration sshd (syntaxe et paramètres effectifs)

cr0x@server:~$ sudo sshd -t
cr0x@server:~$ echo $?
0

Ce que cela signifie : Le code de sortie 0 signifie que la syntaxe est valide. Non-zéro signifie que vous avez probablement cassé la config sshd ; il se peut qu’un démon existant tourne encore, mais reload/restart échouera.

Décision : Si la syntaxe échoue, corrigez-la d’abord. Si la syntaxe est OK, inspectez les réglages effectifs.

Tâche 10 : Affichez les réglages effectifs de sshd (la vérité, pas ce dont vous vous souvenez)

cr0x@server:~$ sudo sshd -T | egrep -i 'passwordauthentication|pubkeyauthentication|authorizedkeysfile|allowusers|denyusers|permitrootlogin|match'
pubkeyauthentication yes
passwordauthentication no
authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2
permitrootlogin prohibit-password

Ce que cela signifie : C’est la config évaluée (moins le contexte Match à moins que vous ne le testiez). Elle montre si l’authentification par mot de passe est désactivée et où sshd attend les clés.

Décision : Si AuthorizedKeysFile pointe ailleurs que prévu, vos clés peuvent être au mauvais endroit. Si PubkeyAuthentication est désactivé, vous avez trouvé le problème. Si des règles Allow/Deny existent, inspectez-les ensuite.

Tâche 11 : Vérifiez les blocs Match qui s’appliquent seulement à votre utilisateur ou IP source

cr0x@server:~$ sudo awk 'BEGIN{p=0} /^Match /{p=1} {if(p)print}' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null
Match User user
    AuthenticationMethods publickey
    X11Forwarding no

Ce que cela signifie : Vous avez une politique spécifique par utilisateur. Peut‑être que quelqu’un a ajouté AuthenticationMethods publickey (correct) mais retiré la clé correcte, ou combiné avec une autre exigence, ou défini une forced command qui échoue maintenant.

Décision : Assurez‑vous que le bloc Match reflète la réalité. Si vous exigez uniquement publickey, la clé doit exister et être lisible. Si vous exigez plusieurs méthodes, confirmez que le client peut les satisfaire.

Tâche 12 : Confirmez que sshd exécute la config que vous pensez

cr0x@server:~$ systemctl status ssh --no-pager
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-08-07 09:59:10 UTC; 15min ago
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 1122 (sshd)
      Tasks: 1 (limit: 2321)
     Memory: 2.3M
        CPU: 79ms
     CGroup: /system.slice/ssh.service
             └─1122 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

Ce que cela signifie : sshd est en cours d’exécution. Super. Cela ne veut pas dire qu’il vous autorise. Mais cela signifie que vous pouvez recharger sans danger après des changements de config (testez toujours avec sshd -t d’abord).

Décision : Si vous avez changé la config et n’avez pas rechargé, faites un rechargement sûr après validation.

cr0x@server:~$ sudo sshd -t && sudo systemctl reload ssh

Ce que cela signifie : Le reload applique la config sans couper les sessions existantes. Restart coupe les sessions et c’est comme ça qu’on transforme un verrouillage en plusieurs verrouillages.

Décision : Préférez reload. Si le reload échoue, corrigez la config et réessayez — ne redémarrez pas par frustration.

Cause n°4 : Le compte/politique vous bloque (utilisateur verrouillé, clé expirée, PAM, access.conf)

Voici la zone « tout semble correct, les clés correspondent, les permissions sont bonnes, sshd est sain, mais je ne peux toujours pas entrer ». C’est aussi là où les environnements d’entreprise cachent les objets tranchants : politiques PAM, identité centralisée, expiration de compte, et listes de refus « temporaires » qui deviennent permanentes.

Tâche 13 : Vérifiez si le compte utilisateur est verrouillé ou expiré

cr0x@server:~$ sudo passwd -S user
user L 2025-07-10 0 99999 7 -1

Ce que cela signifie : Le L indique que le compte est verrouillé. L’auth SSH par clé peut encore être bloquée à l’étape compte selon PAM et la configuration ; dans beaucoup de setups, un mot de passe verrouillé bloque effectivement les connexions.

Décision : Si ce compte doit être utilisable, déverrouillez‑le (via votre processus de contrôle des changements). Si il doit rester verrouillé, ne cherchez pas à contourner la politique et utilisez le compte break‑glass ou le workflow approprié.

Tâche 14 : Vérifiez si le shell est valide (oui, ça arrive encore)

cr0x@server:~$ getent passwd user
user:x:1001:1001:User,,,:/home/user:/usr/sbin/nologin

Ce que cela signifie : Le shell du compte est /usr/sbin/nologin. SSH peut authentifier puis refuser la session (souvent ressemble à permission denied ou déconnexion immédiate).

Décision : Si l’utilisateur doit avoir un shell, donnez‑lui un shell valide comme /bin/bash ou celui de votre standard. Si c’est intentionnellement nologin, n’insistez pas.

Tâche 15 : Cherchez des restrictions PAM dans les logs

cr0x@server:~$ sudo journalctl -u ssh -n 120 --no-pager | egrep -i 'pam|account|access|denied|failure'
Aug 07 10:14:09 host sshd[12555]: pam_access(sshd:account): access denied for user `user' from `198.51.100.22'
Aug 07 10:14:09 host sshd[12555]: Failed password for user from 198.51.100.22 port 51288 ssh2

Ce que cela signifie : PAM refuse l’accès au compte selon l’IP source ou des règles. La ligne d’authentification après peut être trompeuse ; le refus est explicite.

Décision : Inspectez /etc/security/access.conf et la pile PAM pour sshd. Corrigez la règle ou l’hypothèse sur l’IP source. Ne désactivez pas les modules PAM à la légère ; vous gagnerez l’accès et perdrez audit/conformité.

Tâche 16 : Vérifiez la configuration PAM pour sshd (quels modules s’exécutent)

cr0x@server:~$ sudo grep -nE 'pam_access|pam_sss|pam_faillock|pam_tally2' /etc/pam.d/sshd
15:account    required     pam_access.so
22:account    [default=bad success=ok user_unknown=ignore] pam_sss.so

Ce que cela signifie : pam_access.so est actif. Cela explique les blocages basés sur la source. pam_sss.so suggère qu’une identité centralisée (SSSD) est impliquée.

Décision : Si les règles d’accès sont trop strictes, ajustez‑les. Si SSSD est en panne ou mal configuré, il faudra rétablir la santé du service d’identité (pas seulement SSH).

Tâche 17 : Détectez les pannes SSSD / identité qui se déguisent en échecs SSH

cr0x@server:~$ systemctl status sssd --no-pager
● sssd.service - System Security Services Daemon
     Loaded: loaded (/usr/lib/systemd/system/sssd.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-08-07 08:01:44 UTC; 2h 13min ago

Ce que cela signifie : SSSD tourne, mais « tourne » n’est pas synonyme de « fonctionne ». Toutefois, un SSSD mort est une victoire facile.

Décision : Si SSSD est tombé, redémarrez‑le. S’il est actif, vérifiez les logs pour des échecs de lookup d’authentification/compte (hors du périmètre de cet article, mais vous savez où ça mène).

Cause n°5 : La machine n’est pas la machine attendue (host keys, DNS/IP, bastion, ProxyJump)

« SSH fonctionnait hier » est souvent vrai. C’est juste que vous vous connectiez sur une machine différente hier et vous ne le saviez pas. Les changements DNS, la réaffectation d’IP flottante, les load-balancers devant SSH (oui, ça existe) et les bastions peuvent créer cette illusion.

Tâche 18 : Confirmez DNS et routage vers la cible

cr0x@server:~$ getent hosts host.example.com
203.0.113.10   host.example.com

Ce que cela signifie : C’est l’IP que votre système utilisera. Si elle a changé depuis hier, vous frappez probablement à une autre porte.

Décision : Si l’IP est inattendue, arrêtez et validez la bonne cible (inventaire, console cloud). Corrigez le DNS, ou mettez à jour votre config SSH pour utiliser l’adresse stable.

Tâche 19 : Vérifiez le mismatch de clé hôte (l’avertissement honnête)

cr0x@server:~$ ssh user@host.example.com
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Host key verification failed.

Ce que cela signifie : Soit l’hôte a été reconstruit, soit le DNS/IP a changé, soit quelqu’un intercepte le trafic. Dans les réseaux d’entreprise, les reconstructions et la réutilisation d’IP sont courantes ; les attaques sont moins fréquentes, mais vous ne pouvez pas les exclure.

Décision : Vérifiez la nouvelle clé hôte via un canal de confiance hors bande (console, CMDB, logs de provisioning). Ensuite seulement mettez à jour known_hosts.

Tâche 20 : Supprimez une seule entrée known_hosts fautive en toute sécurité

cr0x@server:~$ ssh-keygen -R host.example.com
# Host host.example.com found: line 42
/home/cr0x/.ssh/known_hosts updated.
Original contents retained as /home/cr0x/.ssh/known_hosts.old

Ce que cela signifie : Vous avez supprimé une entrée hôte, pas le fichier entier.

Décision : Reconnectez‑vous et validez la nouvelle empreinte. Si vous ne pouvez pas la valider, n’allez pas plus loin. « Ça doit être bon » est la façon dont on rédige les rapports d’incident.

Tâche 21 : Confirmez le chemin ProxyJump/bastion (vous pouvez être bloqué en amont)

cr0x@server:~$ ssh -G host.example.com | egrep -i 'proxyjump|proxycommand|hostname|user'
user user
hostname host.example.com
proxyjump bastion.example.com

Ce que cela signifie : Votre connexion passe par un bastion. Le Permission denied peut se produire au niveau du bastion, pas de l’hôte final.

Décision : Essayez de vous connecter directement au bastion en verbosité et confirmez l’authentification là‑bas d’abord.

cr0x@server:~$ ssh -vvv user@bastion.example.com
debug1: Authentications that can continue: publickey
user@bastion.example.com: Permission denied (publickey).

Ce que cela signifie : Le bastion vous rejette. L’hôte cible peut très bien être correct.

Décision : Corrigez l’accès au bastion (clés, listes blanches, politique) avant de toucher à l’hôte cible.

Blague sèche #2 : Rien ne forge le caractère comme une heure de debug pour « Permission denied » — pour finir par découvrir que vous vous connectiez à la machine de staging avec la confiance de la production.

Trois mini-récits d’entreprise (réalistes, anonymisés et douloureusement pédagogiques)

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Ils avaient une flotte de serveurs Ubuntu derrière un bastion. L’accès était par clés uniquement, pas de mots de passe, et l’entreprise venait de déployer un nouvel outil de gestion de laptops. L’outil a remplacé silencieusement l’intégration agent SSH de l’utilisateur — toujours un agent, toujours « fonctionnel », mais ne chargeait plus les mêmes clés par défaut.

À 08:30, un ingénieur a essayé de patcher une CVE critique. SSH a retourné Permission denied (publickey). Il a supposé que le serveur était cassé, parce que « je n’ai rien changé ». Un second ingénieur a eu la même erreur et a pensé que le bastion était en panne. Ils ont ouvert un incident, page la plateforme, et commencé à préparer un accès console d’urgence.

Les logs sur le bastion étaient clairs : des dizaines de clés rejetées, aucune ne correspondant à l’empreinte attendue. Sur les clients, ssh -vvv montrait l’agent proposant une vieille clé RSA et une clé GitHub — aucune n’autorisée en production. La bonne clé existait sur le disque, mais n’était jamais proposée parce que le nouvel outil avait changé le comportement de l’agent et que ~/.ssh/config n’avait pas d’IdentityFile explicite pour le bastion.

La correction fut peu glamour : mettre à jour la config SSH pour fixer l’identité correcte pour le bastion et définir IdentitiesOnly yes. Le postmortem fut aussi peu glamour, ce qui signifie qu’il fut utile : la mauvaise hypothèse était « le serveur a changé ». Le serveur n’avait pas changé. Le client oui.

Ils ont aussi ajouté une vérification pré‑vol à leur runbook : si SSH échoue, collecter ssh -G et ssh -vvv avant d’escalader. Cette seule étape a évité toute une catégorie de faux‑positifs futurs.

Mini-récit 2 : L’optimisation qui s’est retournée

Une autre entreprise a mené un « sprint de durcissement de sécurité ». Quelqu’un a décidé de standardiser les permissions des répertoires home sur toutes les machines Linux. Le script a mis /home/* en 0775 pour qu’un groupe partagé puisse « aider à la collaboration ». Ça semblait anodin. Ça a même été approuvé dans un ticket parce que le réviseur pensait que « l’écriture groupe » n’affecte que les modifications locales.

En quelques minutes, l’auth SSH par clé a commencé à échouer pour un sous-ensemble d’utilisateurs. Pas tous — seulement ceux dont les home sont devenus écrivables par le groupe et dont sshd conservait les vérifications strictes (le défaut). L’on-call a vu Permission denied (publickey) et a supposé que les clés avaient été retirées ou que cloud-init avait réécrit authorized_keys.

Les logs sshd disaient la vérité : Authentication refused: bad ownership or modes for directory /home/user. L’« optimisation » (collaboration via écriture groupe) violait les contrôles d’OpenSSH. Le sprint de durcissement avait ironiquement réduit la sécurité en encourageant la proposition de désactiver strict mode juste pour récupérer l’accès.

Le correctif fut de revenir aux permissions 0755 (ou plus restrictives), et d’implémenter la collaboration via un répertoire projet partagé avec des ACL correctes, pas en affaiblissant les frontières des home. Ils ont aussi changé leurs scripts pour appliquer les permissions seulement aux chemins sûrs connus au lieu d’écraser tout l’arborescence.

La leçon n’était pas « ne pas automatiser ». C’était « n’automatisez pas sans comprendre les invariants dont dépend le système ». SSH dépend d’invariants de permissions. Les casser et il supposera une compromission — c’est un trait de personnalité raisonnable pour un daemon de sécurité.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une équipe faisait tourner Ubuntu 24.04 sur un mélange de machines physiques et d’instances cloud. Ils avaient une pratique simple : chaque changement affectant SSH nécessitait (1) une validation sshd -t, (2) un systemctl reload ssh, pas un restart, et (3) une seconde session ouverte avant de fermer la première.

Ce n’était pas glamour. Ça ne faisait pas de slides. Ça empêchait les pannes.

Pendant une fenêtre de maintenance, un ingénieur a ajouté un bloc Match Address pour appliquer une auth plus stricte depuis l’Internet public tout en gardant l’accès interne fluide. La config était syntaxiquement valide, mais logiquement incorrecte : elle matchait plus d’adresses que prévu, appliquant en fait les règles « Internet public » aux jump hosts internes. Résultat : des refus pour tout le monde.

Parce qu’ils utilisaient reload et gardaient une seconde session ouverte, ils ne se sont jamais verrouillés dehors. Ils ont immédiatement tail‑lu les logs, vu le comportement du match, corrigé la condition de match, rechargé à nouveau, et vérifié depuis les chemins internes et externes. Pas de drame, pas de récupération console, pas d’héroïsme à minuit.

La pratique qui les a sauvés n’était pas un génie. C’était de la discipline : valider, recharger, garder une session de secours jusqu’à preuve du contraire.

Erreurs courantes : symptômes → cause racine → correctif

Cette section est opinionnée parce que c’est ce que les gens font vraiment sous stress. Si vous vous reconnaissez, félicitations : vous êtes humain. Maintenant arrêtez.

1) Symptom : « Permission denied (publickey) » après une copie de fichier sur le serveur

  • Cause racine : ~/.ssh ou permissions du home ont changé (écriture groupe, propriétaire incorrect).
  • Correctif : Utilisez namei -l pour trouver le premier répertoire fautif ; mettez home à 0755, .ssh à 0700, authorized_keys à 0600.

2) Symptom : Marche depuis un laptop, échoue depuis un autre

  • Cause racine : Différente clé proposée à cause d’un agent/config ; ou IP source bloquée par PAM/règles d’accès.
  • Correctif : Comparez ssh -G et ssh -vvv des deux machines ; vérifiez les logs serveur pour des refus pam_access.

3) Symptom : « Permission denied » juste après avoir « nettoyé » known_hosts

  • Cause racine : Vous vous êtes connecté à la mauvaise machine (DNS/IP changé) et avez fait confiance à une nouvelle clé aveuglément, ou vous êtes sur une instance reconstruite sans les bons authorized_keys.
  • Correctif : Vérifiez l’IP cible avec getent hosts. Vérifiez la clé hôte hors bande. Puis vérifiez que les authorized_keys sont présents et corrects.

4) Symptom : Vous pouvez vous authentifier mais êtes immédiatement déconnecté

  • Cause racine : Shell invalide (/usr/sbin/nologin), forced command qui échoue, ou module PAM session en erreur.
  • Correctif : Vérifiez le shell avec getent passwd, inspectez les logs sshd, et vérifiez toute forced command ou environnement restreint.

5) Symptom : Un seul utilisateur est bloqué ; les autres SSH fonctionnent

  • Cause racine : Bloc Match pour cet utilisateur, mauvais authorized_keys, compte verrouillé, ou politique par utilisateur.
  • Correctif : Cherchez Match User dans sshd_config et sshd_config.d. Validez le statut du compte avec passwd -S. Corrigez ownership/modes dans le home de cet utilisateur.

6) Symptom : Ça a cassé juste après une mise à jour OpenSSH/Ubuntu

  • Cause racine : Algorithme déprécié ou type de clé désactivé ; ou comportement de config sshd changé par des snippets inclus.
  • Correctif : Confirmez le type de clé (ssh-keygen -lf), préférez ED25519. Inspectez la config effective avec sshd -T et vérifiez les includes dans /etc/ssh/sshd_config.d/.

Listes de contrôle / plan étape par étape

Si vous voulez un plan à exécuter sous pression, le voici. Il est conçu pour minimiser les dommages collatéraux et maximiser le signal.

Checklist A : Triage côté client (2 minutes)

  1. Confirmez l’utilisateur/hôte ciblé (ne riez pas ; faites‑le).
  2. Lancez ssh -vvv une fois et sauvegardez la sortie.
  3. Vérifiez la config calculée : ssh -G host | head.
  4. Listez les clés de l’agent : ssh-add -l.
  5. Réessayez avec clé épinglée : ssh -i ~/.ssh/prod_ed25519 -o IdentitiesOnly=yes user@host.

Checklist B : Côté serveur « pourquoi sshd m’a rejeté ? » (5–10 minutes)

  1. Lisez les logs : journalctl -u ssh -n 120.
  2. Si les logs mentionnent ownership/modes, lancez namei -l /home/user/.ssh/authorized_keys.
  3. Corrigez les permissions (home, .ssh, authorized_keys), puis retestez.
  4. Si les logs mentionnent PAM access, inspectez /etc/pam.d/sshd et /etc/security/access.conf.
  5. Validez la config sshd : sshd -t et paramètres effectifs : sshd -T.
  6. Rechargez sshd en toute sécurité : systemctl reload ssh.

Checklist C : « Est‑ce bien la bonne machine ? » (3 minutes)

  1. Résolvez l’hôte : getent hosts host.example.com.
  2. Vérifiez si la clé hôte a changé (ne pas ignorer les avertissements).
  3. Si vous utilisez un bastion, testez l’authentification du bastion séparément.
  4. Confirmez que l’empreinte de la clé hôte correspond à ce que vous attendez via la console.

Conseils opérationnels à reprendre

  • Gardez toujours une session fonctionnelle ouverte pendant que vous changez la config liée à SSH.
  • Utilisez reload, pas restart, à moins que vous aimiez les verrouillages spontanés.
  • Ne diminuez pas les contrôles de permissions de SSH pour « rentrer ». Corrigez les permissions. Le daemon a raison d’être strict.
  • Rendez l’identité explicite dans ~/.ssh/config pour les hôtes critiques : chemin de la clé, user, et IdentitiesOnly yes.

FAQ

1) Pourquoi SSH dit « Permission denied » alors que ma clé est bien sur le serveur ?

Parce que « sur le serveur » ne suffit pas. sshd doit pouvoir la lire, et il doit faire confiance au chemin vers elle. De mauvaises permissions sur /home/user ou ~/.ssh provoquent souvent un rejet silencieux avec un log du type « bad ownership or modes ».

2) Comment savoir quelle clé SSH essaie d’utiliser ?

Utilisez ssh -vvv. Cherchez des lignes comme « Offering public key: » et « identity file … type … ». Si une clé est proposée que vous n’attendiez pas, forcez la bonne avec -i et IdentitiesOnly=yes.

3) Est‑ce sûr de supprimer ~/.ssh/known_hosts ?

C’est sûr autant que de désactiver les détecteurs de fumée parce qu’ils sonnent. Supprimez uniquement l’entrée hôte spécifique avec ssh-keygen -R, et seulement après avoir validé la nouvelle empreinte de clé hôte.

4) SSH fonctionnait, puis après un reboot ça a cassé. Qu’est‑ce qui a changé ?

Souvent : les services d’identité (SSSD) ne se sont pas lancés correctement, les home ont montés différemment, des permissions ont été modifiées par l’automatisation, ou l’IP de l’instance a changé et vous touchez un autre hôte. Commencez par les logs (journalctl -u ssh) et vérifiez l’IP cible.

5) Un mot de passe verrouillé peut‑il empêcher la connexion par clé SSH ?

Oui, selon PAM et les politiques de compte. Même si l’authentification par clé réussit, la phase compte de PAM peut rejeter un compte verrouillé/expiré. Vérifiez avec passwd -S user et les logs PAM.

6) Je n’obtiens que « Permission denied (publickey) » et aucune autre méthode. Pourquoi ?

Parce que le serveur a probablement PasswordAuthentication no et/ou KbdInteractiveAuthentication no. C’est courant et souhaitable. Cela signifie aussi que le chemin des clés doit être correct, et la clé doit être autorisée et lisible.

7) Quelle commande serveur la plus rapide pour voir si la config sshd est en cause ?

sudo sshd -T pour imprimer les paramètres effectifs et sudo sshd -t pour valider la syntaxe. Associez cela à journalctl -u ssh pour voir pourquoi le démon vous a rejeté.

8) Pourquoi SSH échoue uniquement depuis le réseau du bureau mais marche depuis chez moi (ou l’inverse) ?

Politique basée sur la source : règles pam_access, règles de firewall, AllowUsers avec motifs user@host, ou bloc Match sur adresse. Les logs montrent en général le point de décision.

9) Je vois « Authentication refused: bad ownership or modes » mais tout semble correct dans ~/.ssh. Et maintenant ?

Vérifiez tout le chemin avec namei -l. La mauvaise permission est souvent sur /home/user ou un répertoire parent, pas sur .ssh lui‑même.

10) Dois‑je redémarrer sshd lors du dépannage ?

Préférez systemctl reload ssh après sshd -t. Le restart peut couper votre dernière session fonctionnelle et transformer une correction en verrouillage. Le reload est le choix mature.

Prochaines étapes pratiques

Si SSH fonctionnait hier et qu’aujourd’hui c’est « Permission denied », votre travail est de transformer cette plainte vague en l’une des cinq causes concrètes : mauvaise clé, mauvaises permissions, politique sshd, politique de compte, ou mauvais hôte cible. Ne improvisez pas — mesurez.

  1. Lancez ssh -vvv et identifiez quelle clé est proposée et rejetée.
  2. Confirmez la config cliente calculée avec ssh -G et épinglez la bonne identité.
  3. Côté serveur, lisez journalctl -u ssh. Il dit généralement la vraie raison.
  4. Corrigez les permissions en utilisant namei -l pour trouver le premier répertoire non sûr du chemin.
  5. Validez la config sshd avec sshd -t, confirmez les paramètres effectifs avec sshd -T, et rechargez en sécurité.
  6. Quand les logs incriminent PAM ou l’état du compte, traitez‑le comme un incident identité/politique, pas seulement un incident SSH.

Et une fois que vous êtes de retour : rendez SSH déterministe. Clés explicites par hôte, permissions strictes, et un runbook qui commence par les logs. Le vous du futur sera fatigué et méritera cette gentillesse.

← Précédent
Ubuntu 24.04 : mises à jour ont cassé les modules noyau — reconstruire correctement l’initramfs (cas n°28)
Suivant →
Gestion des clés ZFS : la partie que tout le monde oublie jusqu’au jour du désastre

Laisser un commentaire