Cet article va aborder une fonctionnalité très utile d’OpenSSH et de la version 2 du protocole pour partager des connexions.
Même si ce n'est pas une nouveauté (la première implémentation est apparue dans OpenSSH version 3.9p1), c'est fichtrement commode, et une petite explication de texte n'est pas totalement superflue.
1. Introduction
Si on parle de sécurité et que l'on parle en même temps de partage de connexion, on peut soulever un sourcil d'incrédulité, et on aura certainement raison. On n'est pas à l'abri d'une utilisation indue des ressources en cas de partage, et il n'y a pas de raison qu'OpenSSH échappe à la règle.
Fort heureusement, il y a aussi la possibilité d'utiliser Netfilter pour empêcher des connexions indésirables, même en local. Et puis, avec SELinux, une politique peut aussi empêcher d'établir des connexions ou se mettre à l'écoute sur un port TCP par exemple.
2. Cas d'utilisation
Imaginez que vous vous connectez sous une certaine identité (toujours la même) sur un serveur.
Imaginez que, pour des besoins particuliers, vous devez ouvrir jusqu'à dix connexions en parallèle sur le même daemon. En réalité, pour chaque connexion établie, un nouveau daemon est démarré (fork) et est à l'écoute de cette nouvelle connexion.
Ce mécanisme est bien pratique et isole effectivement des processus par rapport à d'autres, mais présente quelques inconvénients.
2.1 Authentifications à répétition
Pour chaque nouvelle connexion, vous devrez repasser par la phase d'authentification, même si c'est fait de manière transparente du point de vue de l'utilisateur à l'aide de clefs ou d'un agent d'authentification.
Mais, si l'on regarde de manière détaillée tout ce qui se passe lors d'une connexion, beaucoup de calculs sont effectués pour négocier l'authentification et le secret partagé pour la suite des communications. Tout cela prend du temps, et débouche sur un processus dédié. Même si Linux est performant sur le fork() en raison de l'utilisation du Copy-On-Write entre autres, le temps de lancement d'un sshd n'est pas nul.
Fig. 1 : Connexion SSH sans multiplexage
2.2 Redirections
Si un processus démarre et ouvre une redirection de port TCP, et qu'un autre processus l'utilise, en cas de fermeture de la connexion qui supporte la redirection, la connexion de l'autre processus est coupée.
Dans le cas d'une redirection d'agent d'authentification ou de messages X11, le problème est que si elle n'est pas demandée au moment de la connexion, alors il ne sera plus possible de l'ajouter plus tard, sauf à couper la connexion et à ajouter sur la ligne de commande l'option appropriée (-A pour ForwardAgent=yes, -X pour ForwardX11=yes ou -Y pour ForwardX11Trusted=yes).
3. Multiplexons sans plus tarder
Les options qui nous intéressent tout de suite sont :
- -M précise que la connexion sera maîtresse (ControlMaster)
- -S fournit l'emplacement de la socket de contrôle (ControlPath)
D'un premier terminal, il faut ouvrir la connexion maîtresse.
% ssh B -S ~/.ssh/sockets/%r@%h:%p
L'emplacement de la socket de contrôle est forcé ici à un emplacement visible seulement pour le compte d'utilisateur qui lance la commande. Cet emplacement comporte le nom du compte d'utilisateur de la machine sur le serveur, le nom du serveur et le port TCP utilisé. Ceci évite la réutilisation indue des connexions.
Ensuite, pour les autres commandes, il suffit de spécifier l'emplacement de la socket de contrôle, qui sera réutilisée, dans la limite de 12 fois.
% ssh B -S ~/.ssh/sockets/%r@%h:%p
Bien entendu, si une connexion maîtresse est déjà démarrée et que j'essaie d'en démarrer une seconde, ssh se plaint à juste titre et désactive le multiplexage tout en continuant :
% ssh B -M -S /tmp/test
ControlSocket /tmp/test already exists, disabling multiplexing
Juste en passant, l'utilisation d'une socket de contrôle dans /tmp/ n'est pas une bonne idée. C'est juste pour donner un exemple (pas à suivre) sur une spécification sur la ligne de commandes.
Lors de la déconnexion, un message explicite rappelle que l'on utilise une connexion multiplexée.
Shared connection to B closed.
Le message est différent de ce que l'on aurait lorsque l'on se déconnecte d'une connexion normale ou de la connexion maîtresse.
Connection to B closed.
Il existe des variantes pour l'ouverture de la connexion maîtresse, pour une approche plus interactive (voir la signification de ask pour ControlMaster dans la page de manuel de ssh_config(5)). Et, pour faire simple, il est aussi possible d'utiliser la valeur auto, qui va automatiquement créer la socket de contrôle lors de la première connexion et la supprimer par la suite quand la dernière connexion est fermée.
Fig. 2 : Connexion SSH avec multiplexage
4. Exemple de configuration
Plutôt que de spécifier les arguments sur la ligne de commandes, on peut aussi spécifier :
Host *
User machin
StrictHostKeyChecking ask
NoHostAuthenticationForLocalhost yes
ControlPath ~/.ssh/sockets/%r@%h:%p
ControlMaster auto
Compression no
NoHostAuthenticationForLocalhost yes
5. Avantages du multiplexage de connexions
La connexion est multiplexée, c'est bien. On va pouvoir briller en soirée, mais, concrètement, qu'est-ce que ça peut nous faire ?
Eh bien, la réponse est simple : c'est mieux ! Précisons tout de même que ce n'est pas la panacée, et qu'il peut y avoir des inconvénients.
5.1 Authentification unique
La phase d'authentification est unique, toutes les connexions suivantes sont beaucoup plus rapides, tout simplement parce que l'authentification n'est pas retraitée. Si la partie qui prend le plus de temps est le lancement d'un processus à l'arrivée, comme une application ou un interpréteur de commandes, la différence sera certainement imperceptible.
5.2 Partage des configurations
Si la connexion maîtresse utilise la compression ou des redirections de messages X11, d'agent d'authentification ou de redirections de ports, toutes les connexions partagées héritent de ces paramétrages. C'est normal puisqu'il n'y a qu'une connexion ouverte.
5.3 Reconfiguration d'un ensemble de redirections en une fois
Pour aller plus loin sur le point précédent, le fait d'avoir une connexion partagée permet d'ajouter ou de supprimer par exemple des nouvelles redirections à chaud.
Toutes les connexions qui seraient multiplexées utiliseront alors immédiatement ces nouvelles redirections.
On peut faire ça très simplement à l'aide des séquences d'échappement décrites dans la page de manuel de ssh(1).
Par exemple, si on souhaite ajouter une redirection, et en supposant que le caractère d'échappement pour la connexion maîtresse est le « ~ » (caractère par défaut), on aurait :
% ~C
ssh> -L 2345:re.search.wikia.com:80
Forwarding port.
% netstat -alpetn|grep 2345
tcp 0 0 127.0.0.1:2345 0.0.0.0:* LISTEN 500 27373 6649/ssh
tcp 0 0 ::1:2345 :::* LISTEN 500 27372 6649/ssh
En réalité, on peut voir cette facilité comme un inconvénient aussi. Au pire, on pourra filtrer l'accès au port sur la boucle locale. Il est aussi possible de spécifier une interface d'écoute différente si on souhaite être plus large.
6. Inconvénients du multiplexage de connexions
6.1 Coupure massive
Évidemment, en cas de coupure de la connexion maîtresse, toutes les connexions sont coupées en une seule fois. Cela a au moins l'avantage d'être rapide. Dans ce cas, screen est votre ami.
6.2 Les restes de la veille
Si la dernière connexion est coupée brutalement (signal KILL par exemple), la socket de contrôle reste sur place et empêche les prochains multiplexages. On doit alors le supprimer manuellement.
6.3 Comportement de programmes tiers
Il y a eu des soucis avec le transport svn+ssh et le multiplexage de connexion. Je dois reconnaître que je n'ai pas suivi ce problème, mais le contournement est de désactiver le multiplexage pour les connexions svn. C'est finalement assez simple avec un fichier de configuration par utilisateur :
- Host svnhost
- User svnuser
- ControlMaster no
6.4 En cas d'oubli
Si l’on a oublié de demander le multiplexage explicite des connexions ou si l'on n'a pas précisé une option de compression ou de redirection des messages X11, il faudra démarrer explicitement une nouvelle connexion sans multiplexage ou fermer la connexion existante.
% ssh B -MM
ControlSocket ... already exists, disabling multiplexing
Last login: Sun Feb 8 15:15:20 2009 from b
En supposant qu'il existe une connexion multiplexée avec cette socket, une connexion non multiplexée sera ouverte.
Conclusion
Le multiplexage est très simple à mettre en œuvre, et même s'il a aussi quelques inconvénients et limites, comme le nombre de connexions multiplexées dans une seule connexion maîtresse, le confort d'utilisation est indéniable.
Du point de vue de la sécurité, le multiplexage n'introduit pas plus de failles qu'une authentification à l'aide d'un agent.
Laissez-vous tenter, l'essayer, c'est l'adopter !
Remerciements
Merci aux Mongueurs de Perl francophones pour la relecture.
Références
- Les pages de manuel de ssh(1) et ssh_config(5).