Retour à l'accueil
  • #Cours
  • #Ssh
  • #HowTo

Utiliser le fichier de configuration SSH pour ses connexions distantes

Apprendre à utiliser le fichier de configuration SSH pour organiser ses options de connexion.

  1. Pré-requis
  2. TL;DR
  3. Pourquoi utiliser un fichier de configuration ?
  4. Le fichier de configuration
  5. Les instructions de configuration
  6. Priorité des instructions
  7. Séparer et inclure ses fichiers de configuration
  8. Les instructions les plus courantes / utiles
    1. Les modes de StrictHostKeyChecking
  9. Connexion par rebond avec ProxyJump
  10. Multiplexer ses connexions SSH
    1. Exemple de fichiers de configuration avec multiplexage
  11. Pour aller plus loin : durcissement
  12. 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éseau 192.168.140.0/24.
  • ? permet de restreindre une expression à un seul caractère. Ainsi Host 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. Ainsi 172.16.1.* !172.16.1.20 s'appliquera à tous les hôtes du sous-réseau 172.16.1.0/24 à l'exception de 172.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 config du 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érez ProxyJump pour 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 par IdentityFile. Cela peut déclencher une erreur Too many authentication failures côté serveur si votre agent contient de nombreuses clés. Activer IdentitiesOnly yes limite SSH aux seules clés explicitement déclarées dans IdentityFile ;
  • 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 mode auto (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 (comme auto mais 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, %p et %r dont 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

Crédits: photo de couverture par Mohammad Rahmani