Aller au contenu
Administration Linux medium

Retrouver l'accès SSH à un serveur

12 min de lecture

Vous venez de modifier la configuration SSH d'un serveur distant, et vous ne pouvez plus vous y connecter. La panne la plus stressante de l'administration Linux, parce que l'outil que vous utilisez pour réparer est précisément celui qui est cassé. Cette page vous apprend à qualifier le refus avant tout, puis à traiter les trois causes qui produisent trois symptômes différents, et enfin la règle qui vous aurait évité l'incident.

Toutes les commandes et sorties de cette page proviennent d'un serveur AlmaLinux 10 avec SELinux en Enforcing, la configuration par défaut du monde RHEL.

  • Qualifier le refus : refused, timeout et Permission denied désignent trois coupables distincts
  • Valider sshd_config avec sshd -t avant tout redémarrage
  • Diagnostiquer le piège du port non standard bloqué par SELinux, l'un des pièges classiques du RHCSA
  • Corriger un rejet de clé dû aux permissions de authorized_keys
  • Garder une porte de sortie pour ne jamais se verrouiller dehors

Le message d'erreur de votre client SSH est le diagnostic. Trois refus, trois causes, trois procédures : les confondre, c'est chercher au mauvais endroit.

Ce que dit le clientSignificationCoupable probable
Connection refusedLe serveur a répondu, mais rien n'écoute sur ce portsshd est arrêté ou écoute ailleurs
Rien, puis Connection timed outAucune réponse : les paquets sont jetés en silencePare-feu, groupe de sécurité, ou serveur éteint
Permission denied (publickey)La connexion fonctionne, c'est l'authentification qui échoueClé, permissions de authorized_keys, ou compte

Un refus n'est pas un timeout. Un refus prouve que la machine est vivante et joignable : le réseau va bien, le problème est sur le service. Un timeout, à l'inverse, ne dit rien du service : les paquets n'arrivent même pas jusqu'à lui. Et un Permission denied est presque une bonne nouvelle : tout fonctionne, sauf la preuve d'identité.

C'est la faute la plus commune : une directive mal orthographiée, et le service refuse de redémarrer. Le point important est que cette panne est entièrement évitable, par une seule commande.

sshd -t analyse la configuration sans toucher au service en cours. Elle renvoie 0 si tout va bien, et un code non nul sinon :

Fenêtre de terminal
sshd -t ; echo "exit=$?"
exit=255

Un code de sortie non nul, et vous ne redémarrez pas. Vous corrigez d'abord. Si vous redémarrez quand même, voici ce qui se passe :

Fenêtre de terminal
systemctl restart sshd ; echo "exit=$?"
systemctl is-active sshd
ss -tlnp | grep -E ':22\b' || echo "AUCUN processus n'ecoute sur le port 22"
Job for sshd.service failed because the control process exited with error code.
exit=1
inactive
AUCUN processus n'ecoute sur le port 22

Le service est arrêté, plus rien n'écoute sur le port 22, et toute nouvelle connexion se prendra un Connection refused. Votre session actuelle, elle, survit : c'est votre unique porte de sortie.

Restaurez la sauvegarde de votre configuration (vous en avez fait une avant de la modifier), validez, puis redémarrez :

Fenêtre de terminal
cp -a /root/sshd_config.orig /etc/ssh/sshd_config
sshd -t && echo "sshd_config valide"
systemctl restart sshd
ss -tlnp | grep -E ':22\b'
sshd_config valide
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1865,fd=7))

Cause 2 : le port non standard bloqué par SELinux

Section intitulée « Cause 2 : le port non standard bloqué par SELinux »

Changer le port d'écoute de SSH est une demande courante. Sur Debian ou Ubuntu, il suffit d'éditer sshd_config. Sur RHEL, AlmaLinux ou Rocky, cela ne suffit pas, et l'erreur obtenue est particulièrement trompeuse.

La syntaxe est valide, et pourtant le service refuse de démarrer

Section intitulée « La syntaxe est valide, et pourtant le service refuse de démarrer »
Fenêtre de terminal
sed -ri 's/^#?Port .*/Port 2222/' /etc/ssh/sshd_config
sshd -t ; echo "exit=$?"
systemctl restart sshd ; echo "exit=$?"
exit=0
exit=1

Regardez bien : sshd -t renvoie 0. La configuration est parfaitement valide. Et pourtant le redémarrage échoue. C'est exactement le genre de contradiction qui fait perdre une demi-heure, parce que la commande de validation que vous venez d'apprendre vous dit ici que tout va bien.

Le journal donne la cause, mais elle induit en erreur

Section intitulée « Le journal donne la cause, mais elle induit en erreur »
Fenêtre de terminal
journalctl -u sshd --since '1 min ago' --no-pager | tail -3
sshd[1816]: error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.
sshd[1816]: error: Bind to port 2222 on :: failed: Permission denied.

« Permission denied » alors que vous êtes root. C'est le signal. Root n'a jamais de problème de permission Unix pour ouvrir un port. Quand root se voit refuser quelque chose sans raison apparente, le suspect numéro un est le contrôle d'accès obligatoire, c'est-à-dire SELinux.

SELinux journalise chaque refus sous forme d'AVC (Access Vector Cache) :

Fenêtre de terminal
ausearch -m avc -ts recent | tail -2
type=AVC msg=audit(1784022633.371:656): avc: denied { name_bind } for pid=1816
comm="sshd" src=2222 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023
tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0

Cette ligne se lit comme une phrase. Le démon sshd (dans le contexte sshd_t) a tenté un name_bind sur le port 2222, dont l'étiquette est unreserved_port_t. SELinux n'autorise sshd_t à se lier qu'aux ports étiquetés ssh_port_t. Le port 2222 n'en fait pas partie, donc le bind est refusé.

Vérifiez quels ports la politique connaît réellement :

Fenêtre de terminal
semanage port -l | grep -E '^ssh_port_t'
ssh_port_t tcp 22

On étiquette le port pour la politique SELinux, puis on redémarre :

Fenêtre de terminal
semanage port -a -t ssh_port_t -p tcp 2222
semanage port -l | grep -E '^ssh_port_t'
systemctl restart sshd ; echo "exit=$?"
ss -tlnp | grep -E ':2222\b'
ssh_port_t tcp 2222, 22
exit=0
LISTEN 0 128 0.0.0.0:2222 0.0.0.0:* users:(("sshd",pid=1847,fd=7))

Le port 2222 est maintenant connu de la politique, sshd s'y lie, et le service démarre. Deux étapes restent à faire avant de fermer votre session témoin : ouvrir le port dans le pare-feu (firewall-cmd --add-port=2222/tcp --permanent) et vérifier qu'une nouvelle connexion aboutit bien sur le nouveau port. Un port SSH changé sans règle de pare-feu correspondante produit un timeout, et vous revoilà dans la première colonne du tableau de qualification.

Votre clé est la bonne, elle est bien dans authorized_keys, et pourtant le serveur la refuse. La cause est presque toujours StrictModes, actif par défaut : sshd refuse d'utiliser un fichier de clés que d'autres utilisateurs pourraient modifier. La logique est saine, un attaquant qui peut écrire dans votre authorized_keys peut y ajouter sa propre clé.

Fenêtre de terminal
ssh -i /root/.ssh/lab_probe root@127.0.0.1 'echo connexion OK' ; echo "exit=$?"
root@127.0.0.1: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
exit=255

Rien, dans ce message, ne parle de permissions de fichier. Le client SSH ne sait pas pourquoi le serveur a refusé sa clé : le serveur ne le lui dit pas, et c'est volontaire (un serveur bavard aiderait un attaquant).

Fenêtre de terminal
journalctl -u sshd --since '1 min ago' | grep -i 'authentication refused'
stat -c '%a %U:%G %n' /root/.ssh/authorized_keys
sshd-session[1910]: Authentication refused: bad ownership or modes for file /root/.ssh/authorized_keys
777 root:root /root/.ssh/authorized_keys

« bad ownership or modes », le journal du serveur est explicite là où le client était muet. Le fichier est en 777 : tout le monde peut le réécrire, donc sshd l'ignore. Retenez ce réflexe : quand une clé est refusée, le vrai message est côté serveur, dans journalctl -u sshd.

Fenêtre de terminal
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys
chown -R root:root /root/.ssh
restorecon -Rv /root/.ssh

Les permissions attendues sont 600 pour authorized_keys (lecture et écriture pour le propriétaire seulement) et 700 pour le répertoire .ssh. Le restorecon remet au passage les étiquettes SELinux correctes, souvent perdues quand le fichier a été copié depuis un autre emplacement.

SymptômeCause probableVérificationCorrection
Connection refusedsshd arrêté (config invalide)systemctl is-active sshd, sshd -tCorriger la config, systemctl restart sshd
Connection refused après un changement de portLe service écoute ailleursss -tlnp | grep sshdSe connecter avec ssh -p <port>
Connection timed outPare-feu ou groupe de sécuritéfirewall-cmd --list-allOuvrir le port, vérifier aussi le pare-feu du fournisseur
Le service refuse de démarrer sur un port non standard, sshd -t dit 0SELinux : port non étiquetéausearch -m avc -ts recentsemanage port -a -t ssh_port_t -p tcp <port>
Permission denied (publickey) avec la bonne cléStrictModes : permissions trop largesjournalctl -u sshd, stat sur authorized_keyschmod 600 sur le fichier, 700 sur .ssh
Tout semble correct mais rien n'aboutitLe serveur ne boote plusConsole du fournisseur ou virsh consoleVoir Arrêter, redémarrer, récupérer

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  • Le message du client est le diagnostic : refused (rien n'écoute), timeout (pare-feu), Permission denied (authentification). Trois causes, trois procédures.
  • sshd -t avant chaque restart. Cette commande seule évite la majorité des verrouillages.
  • Gardez toujours une session ouverte et testez avec une seconde connexion. Une session établie survit au redémarrage de sshd.
  • Sur RHEL, changer le port SSH ne suffit pas : SELinux n'autorise sshd à se lier qu'aux ports ssh_port_t. Le symptôme est un Permission denied alors que vous êtes root, et sshd -t ne le voit pas.
  • semanage n'est pas installé par défaut sur les images cloud RHEL, alors que SELinux, lui, est bien en Enforcing.
  • Une clé refusée se diagnostique côté serveur : le client ne dit jamais pourquoi. journalctl -u sshd révèle le « bad ownership or modes ».
  • authorized_keys en 600, .ssh en 700. Plus permissif, et StrictModes ignore le fichier.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn