Comment durcir sshd_config : une checklist testable

Placez vos réglages dans un fichier drop-in comme /etc/ssh/sshd_config.d/10-hardening.conf : PermitRootLogin no, PasswordAuthentication no, KbdInteractiveAuthentication no, AllowUsers avec votre identifiant, et des valeurs plus basses pour MaxAuthTries et LoginGraceTime. Vérifiez avec sudo sshd -t, rechargez sshd et testez une nouvelle connexion pendant que votre session actuelle reste ouverte.

Mis à jour le . La configuration, sshd -t, sshd -T, sshd -T -C et chaque refus montré ici ont été exécutés sur OpenSSH 10.0p1 sous Debian 13 dans un conteneur jetable, avec un client OpenSSH 10.3 sous macOS.

Gardez une session ouverte pendant vos tests

Recharger sshd ne met pas fin aux connexions existantes. Dans notre test, une session ouverte avant le rechargement a continué et s'est terminée normalement après. Laissez donc ouverte une session capable d'agir en root, et faites tous les tests depuis un second terminal. Si un réglage vous enferme dehors, vous le corrigez depuis la première.

Avant de mettre PasswordAuthentication no, assurez-vous qu'une connexion par clé fonctionne. Voir comment désactiver la connexion SSH par mot de passe.

Utilisez un fichier drop-in, et sachez que la première valeur l'emporte

Pour la plupart des réglages, sshd garde la première valeur qu'il lit. Debian et Ubuntu ont Include /etc/ssh/sshd_config.d/*.conf en haut de sshd_config : un drop-in l'emporte donc sur une ligne plus bas dans le fichier principal. Sur notre système de test, le fichier principal avait PasswordAuthentication yes à la ligne 125, et le drop-in avec no a gagné.

Les fichiers de ce dossier sont lus dans l'ordre de leur nom, et certaines images cloud y ajoutent les leurs : un numéro bas comme 10- est donc un choix sûr. Si votre système n'a pas de ligne Include, modifiez sshd_config directement et placez les réglages avant tout bloc Match.

Les réglages

# /etc/ssh/sshd_config.d/10-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
AllowUsers deploy
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
RéglageValeur par défaut en amontCe que change la modification
PermitRootLogin noprohibit-passwordRoot ne peut plus se connecter du tout, même avec une clé. Chacun se connecte sous son propre compte et utilise sudo, ce qui garde une trace de qui a fait quoi.
PasswordAuthentication noyesSupprime la devinette de mot de passe comme attaque.
KbdInteractiveAuthentication noyesFerme l'autre voie vers une invite de mot de passe. Laissez-le activé si vous utilisez des codes à usage unique via PAM.
AllowUsers deployNon défini : tout compte peut essayerSeuls les comptes listés peuvent se connecter. Une faute de frappe ici enferme tout le monde dehors, c'est pourquoi la première session reste ouverte.
MaxAuthTries 36Moins de tentatives par connexion. Chaque clé proposée par un client compte : un client avec beaucoup de clés peut donc en manquer. Voir Too many authentication failures.
LoginGraceTime 30120 secondesLes connexions non authentifiées sont coupées plus tôt.
X11Forwarding nono, mais le fichier de Debian met yesDésactive une fonction que la plupart des serveurs n'utilisent jamais.
AllowAgentForwarding noyesVoir les risques du transfert d'agent.
AllowTcpForwarding noyesEmpêche les tunnels SSH à travers ce serveur, et son usage comme hôte de rebond. Ne le définissez pas si vous utilisez l'un ou l'autre.

Le manuel est clair sur une limite : désactiver la redirection TCP n'améliore pas la sécurité si les utilisateurs n'ont pas aussi un shell refusé, car quiconque a un shell peut lancer son propre outil de redirection. Considérez-le comme un nettoyage pour les comptes qui ont un shell, et comme une vraie restriction seulement pour ceux qui n'en ont pas.

Laissez MaxStartups et PerSourcePenalties à leurs valeurs par défaut sans raison particulière. Ils ralentissent déjà les rafales de connexions sur les versions actuelles.

Vérifier avant de recharger

sshd -t vérifie la syntaxe et les clés d'hôte. Il n'affiche rien quand tout va bien. Une faute de frappe donne une erreur et un code de sortie non nul :

$ sudo sshd -t
/etc/ssh/sshd_config.d/99-typo.conf: line 1: Bad configuration option: PermitRootLogn
/etc/ssh/sshd_config.d/99-typo.conf: terminating, 1 bad configuration options

sshd -T affiche les valeurs que sshd utilisera réellement, une fois tous les fichiers combinés. Les noms apparaissent en minuscules :

sudo sshd -T | grep -iE '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|allowusers|maxauthtries|logingracetime|x11forwarding|allowagentforwarding|allowtcpforwarding) '

Si vous utilisez des blocs Match, ajoutez -C pour voir le résultat pour une connexion précise :

sudo sshd -T -C user=deploy,host=example.com,addr=203.0.113.10 | grep -i allowtcpforwarding

sshd -T lit les fichiers sur le disque, pas ce que le démon en cours a chargé. Il montre ce que vous aurez après le rechargement.

Recharger et tester depuis un second terminal

# Debian, Ubuntu
sudo systemctl reload ssh
# Red Hat family
sudo systemctl reload sshd

Essayez ensuite chacune de ces commandes. La première doit réussir et les autres doivent échouer :

ssh deploy@server 'echo ok'
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password deploy@server
ssh root@server
ssh -N -L 8022:127.0.0.1:22 deploy@server

La dernière commande n'échoue pas à la connexion. Elle se connecte, et la redirection est refusée quand vous utilisez le port local. Le journal du serveur montre alors une ligne comme celle-ci :

refused local port forward: originator 127.0.0.1 port 63434, target 127.0.0.1 port 22

Une connexion root refusée apparaît dans le journal sous la forme User root from 203.0.113.10 not allowed because not listed in AllowUsers.

Algorithmes modernes : seulement si vous devez les restreindre

Les valeurs par défaut actuelles d'OpenSSH sont bonnes. Sur OpenSSH 10.0, la liste d'échange de clés par défaut commence par l'hybride post-quantique mlkem768x25519-sha256. Définir vos propres listes veut dire les maintenir : faites-le quand un audit l'exige ou quand votre système est ancien. Cet ensemble ne garde que des choix modernes :

KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

Les anciennes versions d'OpenSSH ne connaissent pas certains de ces noms. Exécutez ssh -Q kex, ssh -Q cipher et ssh -Q mac sur le serveur et retirez ce qui n'est pas listé. Vérifiez ce qu'un client négocie réellement :

ssh -v deploy@server true 2>&1 | grep -E 'kex: algorithm|server->client cipher'

Les anciens clients et équipements échoueront avec ce message, qui a son propre guide :

Unable to negotiate with 203.0.113.10 port 22: no matching key exchange method found.

Cette liste retire aussi les courbes NIST et les échanges Diffie-Hellman : testez donc chaque équipement et chaque script qui se connecte au serveur avant de la conserver.

Ce que cela ne couvre pas

Ces réglages réduisent ce qui peut être tenté contre sshd. Ils ne corrigent pas OpenSSH : gardez-le donc à jour. Ils ne limitent pas non plus ce qu'un utilisateur connecté peut faire. Pour les attaques répétées dans vos journaux, voir fail2ban pour SSH.

Pour voir qui essaie, voir comment vérifier les tentatives de connexion SSH.

Questions

Recharger sshd ferme-t-il ma session SSH en cours ?

Non. Les sessions existantes continuent après le rechargement. Seules les nouvelles connexions utilisent les nouveaux réglages, d'où le test depuis un second terminal.

Où mettre mes propres réglages sshd ?

Dans un fichier de /etc/ssh/sshd_config.d/ avec un petit numéro, comme 10-hardening.conf. sshd garde la première valeur lue, donc un fichier lu tôt l'emporte.

Comment vérifier sshd_config ?

Lancez sudo sshd -t. La commande n'affiche rien si la configuration est valide, et une erreur avec un code de sortie non nul sinon.

Sources

Autres guides : Sécuriser un serveur

Tous les guides