Utiliser le fichier de configuration SSH pour ses connexions distantes
Apprendre à utiliser le fichier de configuration SSH pour organiser ses options de connexion.
- Pré-requis
- TL;DR
- Pourquoi utiliser un fichier de configuration ?
- Le fichier de configuration
- Les instructions de configuration
- Priorité des instructions
- Séparer et inclure ses fichiers de configuration
- Les instructions les plus courantes / utiles
- Connexion par rebond avec ProxyJump
- Multiplexer ses connexions SSH
- Pour aller plus loin : durcissement
- Sources
Si vous vous connectez à plusieurs hôtes distants, il y a fort à parier que vous ne mémorisez pas les subtilités de connexion propres à chacun d'entre eux (utilisateur spécifique, port non standard, options spécifiques…).
On a eu, il est vrai, l'occasion de croiser des façons originales de le faire, notamment à base d'alias Bash mais ça reste assez artisanal alors même que tout est prévu et qu'OpenSSH permet de définir un fichier de configuration propre à chaque utilisateur du système ;)
Cet article, principalement à destination des étudiant·e·s et des nouveaux·elles arrivant·e·s dans le domaine, saura sans doute également servir de pense-bête aux confirmé·e·s !
Pré-requis
Ils sont plus que pauvres puisqu'un client OpenSSH et une machine distante à laquelle se connecter suffiront.
TL;DR
Contenu d'un fichier config d'un client SSH pour référence :
Host *
User rix
IdentityFile ~/.ssh/id_ed25519
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
Recommandation
Privilégiez les clés ED25519 pour vos nouvelles clés (plus sûres et performantes que RSA). Si vous utilisez encore RSA, un minimum de 4096 bits est recommandé.
ForwardAgent
N'activez jamais ForwardAgent yes sur Host *. Si vous vous connectez à un serveur compromis, l'attaquant obtient un accès au socket de votre agent local et peut demander à signer des opérations au nom de toutes les clés chargées dans votre agent - pas seulement celle utilisée pour cette connexion. Il peut ainsi rebondir sur l'ensemble des serveurs accessibles par toutes vos identités SSH. Activez-le uniquement par hôte, sur des bastions de confiance.
Pourquoi utiliser un fichier de configuration ?
Comme abordé dans l'introduction, il existe autant de manières de se connecter à un serveur avec SSH qu'il n'en existe (de serveurs). Les principaux bénéfices que l'on peut retirer de cette utilisation :
- Ajouter de la cohérence dans votre façon de vous connecter à vos différentes machines (et on aime ça, la cohérence !). Il est en effet possible de créer une configuration spécifique à un serveur ou alors propre à différentes machines partageant les mêmes spécificités de connexion.
- Faciliter les connexions multiples, en créant des configurations aux contextes différents. Il est par exemple possible d'avoir une configuration utilisant une clé différente pour un groupe de machines données.
Le fichier de configuration
En « standard », vous trouverez un dossier appelé .ssh dans le répertoire utilisateur de votre système (/home/username/ sur un système de type UNIX ou C:\Users\username\ sous Windows). C'est ici que nous allons créer un fichier appelé tout simplement config (sans extension).
Configuration globale
Il est possible d'appliquer un comportement global au client SSH (c'est-à-dire pour tous les utilisateurs du système) en utilisant le fichier /etc/ssh/ssh_config.
Si le répertoire .ssh n'existe pas (il est créé automatiquement lorsque vous créez une nouvelle clé par exemple), vous pouvez le créer comme suit :
mkdir -p ~/.ssh && chmod 0700 ~/.ssh
Pour ensuite créer le fichier config :
touch ~/.ssh/config && chmod 0600 ~/.ssh/config
Les droits
Attention, SSH est très sensible (à juste titre) aux droits appliqués aux fichiers qu'il doit utiliser.
Le répertoire .ssh tout comme le fichier config ne doivent être accessibles, lisibles et modifiables qu'à l'utilisateur propriétaire.
Les instructions de configuration
Le fichier config est basé sur un système de paires clé/valeur organisées par section, une structure minimale d'un fichier de configuration pourrait être la suivante :
Host server-hostname-1
KEY value
KEY value
Allons plus loin avec une configuration :
Host server-hostname-1
HostName server.tld
User rix
IdentityFile ~/.ssh/id_ed25519
La directive Host permet d'indiquer à la fois une nouvelle section et le « pattern » qui permettra au client de savoir quand appliquer la configuration.
Dans ce premier exemple, c'est assez simple et spécifique puisque notre bloc s'appliquera à la chaîne server-hostname-1.
Ainsi, lorsque nous taperons ssh server-hostname-1, notre client saura à quel hôte se connecter, avec quel utilisateur et quelle clé.
L'équivalent sans fichier de configuration serait ssh -i ~/.ssh/id_ed25519 rix@server.tld.
L'utilisation d'un fichier de configuration prend tout son sens lorsque l'on souhaite appliquer des comportements spécifiques à un ensemble de machines.
Il est ainsi possible d'utiliser des « pattern » (et de les enchaîner) en utilisant des opérateurs :
Host *, par exemple, s'appliquera à tous les hôtes puisque le caractère*correspond à aucun ou plusieurs caractères.192.168.140.*: vous appliquerez votre configuration à l'ensemble des hôtes dont l'adresse fait partie du sous-réseau192.168.140.0/24.?permet de restreindre une expression à un seul caractère. AinsiHost 172.16.1.?correspondra à tous les hôtes ayant en dernier octet un chiffre compris entre 0 et 9.!en début de chaîne permet d'exclure une correspondance. Ainsi172.16.1.* !172.16.1.20s'appliquera à tous les hôtes du sous-réseau172.16.1.0/24à l'exception de172.16.1.20.
Organisation et structure du fichier
Le fichier de configuration SSH n'impose pas d'indentation, il est toutefois fortement recommandé de l'organiser afin de faciliter sa lecture et sa maintenance.
Il faut noter que SSH applique la première valeur trouvée pour chaque option (et non la dernière comme on pourrait s'y attendre). Il est donc préférable de commencer par les sections très spécifiques et de terminer par les plus génériques (Host * en dernier).
Priorité des instructions
Il est possible, en fonction d'où elles sont indiquées, de surcharger certaines options de connexion. Ainsi, votre client SSH considérera par ordre de priorité :
- Les options spécifiées dans la ligne de commande
- Les options définies dans le fichier
configdu compte utilisateur (~/.ssh/config) - Les options définies dans le fichier générique
/etc/ssh/ssh_config
Ainsi, en reprenant notre section précédente :
Host server-hostname-1
HostName server.tld
User rix
IdentityFile ~/.ssh/id_ed25519
Il est possible de vous connecter avec un autre utilisateur que celui défini dans votre fichier en surchargeant la clé User, avec ssh root@server-hostname-1 ou encore ssh -o "User=root" server-hostname-1.
Séparer et inclure ses fichiers de configuration
Il est également possible, notamment lorsque le contenu des fichiers devient conséquent ou tout simplement pour organiser ses configurations entre différents contextes (clients, perso, pro…), de séparer la configuration dans plusieurs fichiers.
Il est ainsi possible d'avoir autant de fichiers de configuration que de contextes pour ensuite les inclure dans notre fichier principal.
Exemple :
# Contenu de ~/.ssh/config
Host server-hostname-1
HostName server.tld
User rix
IdentityFile ~/.ssh/id_ed25519
Include ~/.ssh/config_alternative
# Contenu de ~/.ssh/config_alternative
Host 192.168.140.*
User debian
IdentityFile ~/.ssh/id_rsa
AddKeysToAgent yes
UseKeychain yes
Pattern Include moderne
Le globbing est supporté par Include. Il est courant d'organiser ses configurations dans un dossier dédié : Include ~/.ssh/config.d/*. Chaque contexte (client A, perso, prod…) dispose alors de son propre fichier sans toucher au config principal.
Les instructions les plus courantes / utiles
Le fichier config supporte nombre d'options de configuration, celles-ci sont consultables dans la documentation officielle OpenSSH.
Il va de soi que dans l'activité quotidienne, les mêmes instructions sont souvent utilisées, ci-dessous une liste des plus courantes :
IdentityFile: nous l'avons vu précédemment, elle permet d'indiquer la clé à utiliser pour la section définie ;ForwardAgent: permet de transmettre votre agent SSH au serveur distant, autorisant le rebond vers d'autres serveurs sans copier votre clé privée. Attention : à n'activer que sur des hôtes de confiance (voir l'avertissement dans le TL;DR). PréférezProxyJumppour les bastions ;IdentitiesOnly: par défaut, SSH essaie d'abord toutes les clés chargées dans votre ssh-agent avant celle spécifiée parIdentityFile. Cela peut déclencher une erreurToo many authentication failurescôté serveur si votre agent contient de nombreuses clés. ActiverIdentitiesOnly yeslimite SSH aux seules clés explicitement déclarées dansIdentityFile;StrictHostKeyChecking: contrôle la vérification de la clé d'hôte du serveur auquel on se connecte (voir les modes détaillés ci-dessous) ;Port: permet de spécifier un port de connexion non standard (très courant lorsque le port 22 est modifié) ;ServerAliveInterval/ServerAliveCountMax: envoie un signal keepalive au serveur à intervalle régulier. Indispensable pour éviter les déconnexions sur connexions instables ou derrière un NAT.
Les modes de StrictHostKeyChecking
| Mode | Nouvelle clé | Clé modifiée | Usage recommandé |
|---|---|---|---|
yes |
Refuse (ajout manuel) | Refuse | Production, conformité |
ask (défaut) |
Demande confirmation | Refuse | Usage interactif quotidien |
accept-new |
Accepte automatiquement | Refuse | CI/CD, automation |
no |
Accepte automatiquement | Accepte | TP/cours uniquement (voir ci-dessous) |
La différence critique entre accept-new et no : face à un serveur dont la clé a changé, accept-new refuse la connexion (protection contre les attaques MITM) tandis que no l'accepte silencieusement.
Désactiver StrictHostKeyChecking - uniquement en environnement isolé
La combinaison ci-dessous ne doit être utilisée que dans un contexte de TP / cours sur un réseau isolé, où des VMs éphémères récupèrent régulièrement les mêmes adresses IP avec des clés d'hôte différentes. Dans ce cas précis, accept-new ne suffit pas car les clés changent à chaque recréation de VM.
Ne jamais appliquer en production ni globalement. Scopez-la sur un pattern Host spécifique (ex : le sous-réseau de votre lab).
Host 192.168.140.*
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
La directive Match
Alternative plus puissante à Host, la directive Match permet de conditionner l'application d'options sur des critères variés : user, originalhost, exec, localuser, etc. Consultez la documentation officielle pour aller plus loin.
Connexion par rebond avec ProxyJump
Lorsque vous devez accéder à des serveurs qui ne sont pas directement joignables (derrière un pare-feu, dans un réseau privé), le passage par un bastion (ou jump host) est la pratique standard. Depuis OpenSSH 7.3 (2016), la directive ProxyJump est la méthode recommandée pour ce cas d'usage.
En ligne de commande :
ssh -J bastion.rix.fr serveur-interne
Dans le fichier de configuration :
Host bastion
HostName bastion.rix.fr
User rix
IdentityFile ~/.ssh/id_ed25519
Host prod-*
User rix
ProxyJump bastion
IdentityFile ~/.ssh/id_ed25519
Avec cette configuration, ssh prod-web-01 passera automatiquement par le bastion. La session SSH est négociée de bout en bout entre votre client et le serveur final : le bastion ne voit pas vos données en clair (il assure uniquement le forwarding TCP).
Il est également possible de chaîner plusieurs sauts : ssh -J bastion1,bastion2 serveur-final.
ProxyJump vs ForwardAgent
Contrairement à ForwardAgent, ProxyJump ne transmet pas votre clé privée au serveur intermédiaire. La clé reste sur votre machine locale. C'est ce qui en fait la méthode la plus sûre pour les rebonds.ForwardAgent fonctionne différemment : le serveur distant reçoit accès au socket Unix de votre agent local. Cela lui permet de demander à votre agent de signer n'importe quelle opération au nom de toutes les clés chargées, pas seulement celle utilisée pour la connexion en cours. Si le serveur est compromis (ou si un utilisateur root malveillant y est présent), toutes vos identités SSH sont exposées.
Si vous devez tout de même activer ForwardAgent sur un bastion de confiance, deux mitigations réduisent la surface d'exposition : ssh-add -c (confirmation interactive à chaque utilisation, requiert SSH_ASKPASS) et ssh-add -t <durée> (durée de vie limitée, ex : -t 3600 pour 1 h).
L'ancienne directive ProxyCommand reste supportée pour les cas particuliers (résolution DNS depuis le jump host, proxys non-SSH) mais ProxyJump est à privilégier par défaut.
Multiplexer ses connexions SSH
Le principe du multiplexage réside dans le fait de « partager » la même connexion entre les différentes sessions ouvertes sur une même machine. Cette stratégie permet, dans le cas d'SSH, de réutiliser une connexion TCP déjà ouverte vers un serveur distant.
Le but ? S'épargner le délai d'ouverture d'une connexion TCP ainsi que celui de la réauthentification. Cette fonctionnalité peut être particulièrement utile lors du transfert de nombreux fichiers d'une machine à une autre, elle réside principalement en l'utilisation de 3 options de configuration :
ControlMaster: définit la stratégie de réutilisation des connexions. Le modeauto(le plus courant) utilise une connexion existante si disponible, sinon en crée une nouvelle. Autres modes :yes(toujours créer un master),ask(demander confirmation),autoask(commeautomais avec confirmation),no(désactivé, par défaut) ;ControlPersist: permet d'indiquer comment SSH doit gérer la fermeture de la connexion initiale à la machine distante (celle qui a entraîné l'ouverture de la socket partagée) ;ControlPath: le chemin vers la socket utilisée pour le partage de connexion. Cette option supporte les tokens%h,%pet%rdont la combinaison est très fortement recommandée. Plus d'informations sur les tokens supportés par SSH (https://man.openbsd.org/ssh_config#TOKENS).
Exemple de fichiers de configuration avec multiplexage
Avant de configurer le multiplexage, créez le dossier qui accueillera les sockets :
mkdir -p ~/.ssh/controlmasters && chmod 0700 ~/.ssh/controlmasters
Host server-hostname-1
HostName server.tld
User rix
IdentityFile ~/.ssh/id_ed25519
ControlPath ~/.ssh/controlmasters/%C
ControlMaster auto
ControlPersist 10m
Le token %C
On remarquera son utilisation dans l'exemple ci-dessus. Il s'agit du hash des tokens %l%h%p%r%j (respectivement le nom d'hôte local (%l), le nom d'hôte distant (%h), le port de connexion distant (%p), le nom d'utilisateur distant (%r) et le contenu de ProxyJump (%j)).
L'utilisation du token %C assurant à la fois l'unicité de la connexion et l'obfuscation de ses détails sur le système de fichiers.
Pour aller plus loin : durcissement
Pour les environnements sensibles, il est possible de restreindre les algorithmes autorisés par votre client SSH via les directives HostKeyAlgorithms, KexAlgorithms et Ciphers. Les recommandations de l'ANSSI détaillent les algorithmes à privilégier et ceux à proscrire.
Exemple de configuration durcie (à adapter selon vos besoins) :
Host *
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
Sources
- Recommandations pour un usage sécurisé d'OpenSSH (ANSSI)
- Documentation officielle ssh_config (OpenBSD)
- SSH ProxyJump vs ProxyCommand (Teleport)
- Create SSH config file (nixCraft)
- ControlPersist feature (StackExchange)