title: SSH: Configuration et utilisation
description: Configurer SSH: clefs asymétriques, bonnes pratiques, 2FA...
published: true
date: 2024-05-17T13:20:18.034Z
tags: linux, ssh
editor: markdown
dateCreated: 2023-12-27T15:50:33.929Z
Introduction
SSH - et plus précisément, OpenSSH, développé par la fondation OpenBSD, signifiant Secure SHell est un logiciel nous permettant, via le client SSH, de nous connecter et d'administrer à distance les machines exécutant le serveur SSH sous énormément de systèmes d'exploitation dont GNU/Linux, Cisco IOS, Juniper JunOS, les BSD (FreeBSD, NetBSD, OpenBSD, etc), macOS, et même Windows via Powershell.
C'est un outil très puissant, qui ne se limite pas à simplement accéder à un shell sur une machine distante, mais qui peut aussi nous permettre:
- de copier des fichiers depuis ou vers la machine distante via SFTP ou la commande scp
- d'accéder à des ressources TCP situées "derrière" la machine à laquelle on se connecte via du port-forwarding
- de servir de "rebond" pour accéder en SSH à d'autres machines situées derrière le serveur auquel on accède
- de rapidement mettre en place une sorte de "VPN du pauvre" via sshuttle par exemple.
Cependant, comme tout outil d'administration puissant, sa mise en place et sa configuration doivent être les plus sécurisées possibles.
Nous verrons ici un ensemble de bonnes pratiques à mettre en place lors de l'utilisation de SSH, en environnement Debian GNU/Linux (mais qui peuvent facilement être adaptées à d'autres systèmes d'exploitation).
La première étape est, tout simplement, de se débarrasser définitivement de l'authentification par login mot de passe, et de la remplacer par l'authentification par clefs de chiffrement asymétrique.
Mise en place de l'authentification par clefs
La première étape, sur notre machine client, est de générer notre couple de clefs, si ce n'est déjà fait. Les algorithmes à utiliser en priorité sont soit ED-25519, soit RSA avec une clef de 4096 bits ou plus.
Si l'on opte pour un couple de clefs utilisant ED-25519, on génèrera notre couple de clefs via la commande:
ssh-keygen -t ed25519
Ce qui va créer deux fichiers dans le répertoire .ssh de notre répertoire utilisateur: un fichier id_ed25519 contenant notre clef privée qui doit absolument rester privée. Ne la "pushez" pas sur Github, ne la partagez pas avec qui que ce soit, et idéalement, lors de la création des clefs, utilisez une passphrase pour la protéger. Un second fichier aura aussi été créé dans le même répertoire, notre clef publique, qui s'appellera probablement id_ed25519.pub. C'est ce fichier, cette clef publique, que nous allons pouvoir partager.
Si l'on opte pour l'utilisation d'un couple de clefs RSA:
ssh-keygen -t rsa -b 4096
Et les fichiers créés par défaut porteront pour noms:
id_rsapour la clef privéeid_rsa.pubpour la clef publique
Il nous reste désormais deux choses à faire:
- copier la clef publique générée sur le(s) serveur(s)
- configurer le serveur SSH sur le(s) serveur(s)
Pour la première étape, la plupart des distributions GNU/Linux fournissent l'utilitaire ssh-copy-id. Pour l'utiliser, si le serveur s'appelle host.domaine.tld et notre utilisateur michel:
ssh-copy-id michel@host.domaine.tld
Et hop
Si l'utilitaire ssh-copy-id n'est pas disponible, on peut alors copier notre clef publique dans le fichier ~/.ssh/authorized_keys de notre serveur, par exemple en utilisant scp, en copiant/collant la clef publique, ou via tout autre moyen (la clef publique peut être par exemple rendue disponible sur un dépôt git que l'on clonera depuis le serveur et que l'on copiera ensuite dans le fichier authorized_keys, etc. Elle est publique, donc, non-sensible.).
Par exemple, en utilisant scp:
# sur le client:
scp ~/.ssh/id_ed25519.pub michel@host.domaine.tld:clef-michel.pub
# sur le serveur:
# si le répertoire .ssh n'existe pas:
mkdir ~/.ssh
# on ajoute ensuite notre clef publique au fichier authorized_keys, notez les deux chevrons:
cat clef-michel.pub >> ~/.ssh/authorized_keys
# idéalement, seul l'utilisateur "michel" doit ici pouvoir modifier le fichier
# authorized_keys:
chmod 600 ~/.ssh/authorized_keys
Il ne nous reste plus qu'à éditer le fichier de configuration du serveur SSH, situé sous Debian GNU/Linux dans le fichier /etc/ssh/sshd_config. Sur le serveur, on va donc éditer ce fichier avec notre éditeur de texte préféré (l'auteur est un fan de Vim ):
sudo vim /etc/ssh/sshd_config
Et nous allons simplement remplacer l'option par défaut (commentée dans le fichier de configuration, car il s'agit du comportement par défaut du serveur SSH):
#PasswordAuthentication yes
Par la ligne:
PasswordAuthentication no
On sauvegarde et on quitte, et on relance le service SSH, via systemctl restart sshd sous Debian GNU/Linux. Bien sûr, suivant la distribution utilisée, l'init du système peut être différent de systemd, par exemple, OpenRC sur Alpine Linux: rc-service sshd restart. Adaptez en fonction de la documentation de votre système d'exploitation.
Et voilà, une première bonne chose de faite.
Cependant, on peut bien sûr vouloir continuer de configurer SSH, pour, par exemple, complètement désactiver la possibilité de se connecter en tant qu'utilisateur root en SSH, ou n'autoriser que certains utilisateurs à se connecter en SSH. De plus, on peut aussi vouloir désactiver certaines options telles que le Forwarding X11, ou ajouter une double-authentification pour encore plus de sérénité.
Durcissement de la configuration du serveur SSH
Désactivation de la connexion en tant que root
Par défaut, la configuration du serveur SSH permet de se connecter en tant qu'utilisateur root via clefs de chiffrement asymétrique. On peut tout simplement désactiver cette possibilité en remplaçant la ligne:
PermitRootLogin prohibit-password
Par:
PermitRootLogin no
De même, on peut aussi vouloir n'autoriser la connexion que d'un seul, ou plusieurs utilisateur(s):
Limiter les utilisateurs autorisés à se connecter en SSH
Pour n'autoriser, par exemple, que l'utilisateur "michel" à se connecter, on peut utiliser la configuration suivante:
AllowUsers michel
Match User michel
AuthenticationMethods publickey
Et répéter pour chaque utilisateur amené à se connecter en SSH à la machine. Par exemple, si michel et alice sont autorisés à se connecter:
AllowUsers michel alice
Match User michel
AuthenticationMethods publickey
Match User alice
AuthenticationMethods publickey
Désactiver le forwarding X11
Là aussi, très simple:
X11Forwarding no
Couper les sessions utilisateurs inactives au bout d'un certain temps
Il peut aussi être important de terminer les connexions utilisateurs inactives au bout d'un certain temps. Le serveur SSH enverra alors des messages de keepalive à intervalle régulier aux clients, puis coupera la connexion de son côté en cas d'inactivité/absence de réponse au bout d'un certain temps (600 secondes dans cet exemple):
ClientAliveInterval 300
ClientAliveCountMax 2
Désactiver le message of the day (MOTD)
Le MOTD peut parfois fournir des informations indésirables à un attaquant, il peut être intéressant de le désactiver:
PrintMotd no
Changer le port d'écoute du serveur SSH
Concernant le port d'écoute par défaut du serveur SSH (le port 22), et pour minimiser le bruit de fond dans les journaux de connexion, on peut vouloir changer ce port (10458 dans l'exemple suivant):
Port 10458
Cependant, il y a deux écoles concernant cette modification:
- Ceux qui pensent que cela améliore la sécurité de leur machine
- Ceux qui pensent que le fait de ne plus être "noyé dans la masse" peut piquer l'intérêt d'un attaquant durant la phase de scan/découverte des services de son attaque.
A vous de choisir dans quel camp vous vous placez
Double authentification
Afin de sécuriser encore plus l'accès à notre machine (ou nos machines), on peut aussi vouloir mettre en place une double-authentification:
- Une première authentification par clefs asymétriques.
- Une seconde authentification par code OTP (OneTime Password) après la première authentification.
Pour cela, on va commencer par installer le paquet nécessaire sur notre machine:
sudo apt install libpam-google-authenticator
Puis créer nos tokens, clefs, etc:
google-authenticator
Note: on peut utiliser n'importe quel client OTP sur smartphone, pas uniquement le client Google, par exemple FreeOTP sur Android via le magasin de logiciels libres FDroid
Ce qui va nous donner quelque chose comme ça:

Note: bien évidemment ce QRCode n'est plus valide
Une fois notre QRCode scanné, nos codes de secours dûment notés et sécurisés (!), nous allons pouvoir configurer SSH et PAM pour pouvoir utiliser notre 2FA.
Tout d'abord, côté SSH, nous allons activer le paramètre keyboard-interactive au niveau de notre bloc Match User ainsi que le paramètre KbdInteractiveAuthentication dans notre fichier de configuration SSH (/etc/ssh/sshd_config)
KbdInteractiveAuthentication yes
... [snip] ...
Match User michel
AuthenticationMethods publickey,keyboard-interactive
On va ensuite modifier le fichier /etc/pam.d/sshd, pour activer notre double-authentification (une fois que notre identité est validée par notre serveur SSH, il va passer l'authentification au système PAM). On va d'abord commenter la ligne:
@include common-auth
# qui doit donc devenir:
#@include common-auth
Et, toujours dans le même fichier, ajouter la ligne:
auth required pam_google_authenticator.so
Il ne nous reste plus qu'à redémarrer notre serveur SSH, avec un systemctl restart sshd (ou autre commande équivalente suivant votre distribution/OS), et vérifier le bon fonctionnement:

Et voilà!
Utilisation de SSH
Connexion, commandes, etc
Une fois notre client et notre(nos) serveur(s) configurés, on va pouvoir se connecter à notre machine, par exemple, si notre serveur a pour IP 172.16.100.100 et que notre utilisateur sur la machine distante s'appelle michel:
ssh michel@172.16.100.100
Si notre utilisateur local a le même identifiant que notre utilisateur distant, on peut omettre le nom de l'utilisateur:
ssh 172.16.100.100
On peut aussi vouloir exécuter une seule commande sur le serveur:
ssh 172.16.100.100 ip address show
Ou plusieurs:
ssh 172.16.100.100 'ip addr show; ip route show; echo "youpi"'
Si notre serveur dispose d'un FQDN (Fully Qualified Domain Name), on peut l'utiliser en lieu et place de son adresse IP, par exemple, si notre serveur a pour FQDN srv-test.lidstah.info:
ssh srv-test.lidstah.info
Si on veut utiliser une autre clef nommée clef-entreprise dans le répertoire ~/.ssh pour se connecter:
ssh -i ~/.ssh/clef-enterprise srv-test.lidstah.info
Cependant, cela peut être fastidieux de taper nom d'utilisateur@adresse IP ou FQDN à chaque fois. On peut configurer notre client SSH pour nous faciliter la vie. On va éditer le fichier ~/.ssh/config, et ajouter par exemple un bloc qui va nous permettre de nous connecter au serveur 172.16.100.100 avec l'utilisateur michel et le couple de clef "clef-entreprise" en utilisant simplement l'identifiant "serveur-entreprise":
Host serveur-entreprise
Port 22
Hostname 172.16.100.100
IdentityFile ~/.ssh/clef-entreprise
User michel
Il nous suffira alors de simplement taper ssh serveur-entreprise, et hop!
Port Forwarding
Imaginons que notre serveur "serveur-entreprise" exécute un service uniquement en local (127.0.0.1), sur le port 9000. Pour pouvoir y accéder depuis notre client SSH, nous pouvons utiliser le Port Forwarding:
ssh -L 9000:127.0.0.1:9000 serveur-entreprise
On pourra ensuite accéder au service en question depuis notre client, par exemple avec notre navigateur en tapant http://127.0.0.1:9000.
Mais il y a encore plus fort (ou plus dangereux ). Si mon client a par exemple pour IP 192.168.1.10/24, je peux rendre ce service accessible à tout mon réseau local de cette façon:
ssh -L 192.168.1.10:9000:127.0.0.1:9000 serveur-entreprise
Evidemment, ça marche aussi dans l'autre sens! Imaginons que notre serveur ait accès au réseau 192.168.100.0/24 mais pas nous, et que nous voulions accéder à un service exécuté par une machine de ce sous-réseau, à l'IP 192.168.100.10 sur le port 8080:
ssh -L 8080:192.168.100.10:8080 serveur-entreprise
On pourra alors accéder à ce service depuis notre client à l'IP 127.0.0.1:8080
JumpHost
De la même manière, on peut utiliser notre serveur "serveur-entreprise" pour accéder en SSH à d'autres machines sur un réseau auquel il a accès, mais pas nous (technique du "bastion"), par exemple une machine à l'IP 192.168.100.10:
ssh -J serveur-entreprise 192.168.100.10
SSHuttle
SSHuttle nous permet de créer un équivalent de VPN "du pauvre" (en fait, on va se servir du tunnel SSH comme d'un VPN, sauf qu'au lieu de transmettre des paquets, le serveur ne transmettra que des sessions - donc, du TCP) via l'utilitaire sshuttle. On l'installe:
sudo apt install sshuttle
Et par exemple, pour pouvoir accéder au réseau 192.168.100.0/24 (encore lui!), on utilisera la commande:
sshuttle -r serveur-entreprise 192.168.100.0/24
Bien sûr, on peut préciser plusieurs sous-réseaux ou directement toute la table de routage du serveur:
sshuttle -r serveur-entreprise 192.168.100.0/24 172.20.0.0/16 10.100.100.0/24
Et pour toute la table de routage du serveur:
sshuttle -Nr serveur-entreprise
On peut aussi demander au serveur de "forwarder" nos requêtes DNS (pourtant de l'UDP) via les options --to-ns, etc. Je vous recommande chaudement la lecture de la manpage de sshuttle
SCP, copie de fichiers
On peut copier des fichiers (ou des répertoires avec l'option -r) via l'utilitaire scp depuis ou vers le serveur:
# copier le fichier /mon/fichier vers le répertoire Downloads du serveur:
scp /mon/fichier serveur-entreprise:Downloads/
# copier le fichier "test" du répertoire Downloads du serveur dans le répertoire courant:
scp serveur-entreprise:Downloads/test ./