Petite revue de terminaux SSH par le web🔗
Introduction
Parfois, on n'a pas le choix, le port SSH est définitivement inaccessible depuis l'extérieur. Dans les entreprises, la politique de pare-feux vient souvent fermer tous les ports différents de 80 et de 443 et un serveur mandataire vient encore un peu plus surveiller les échanges. Dans ces conditions, il serait intéressant de pouvoir disposer d'un logiciel qui permette un accès Shell via un simple navigateur web.
Au-delà des accès fermés des entreprises, il arrive parfois qu'on ne dispose pas d'un client distant. Par exemple, si vous êtes sur une machine bien verrouillée ou si vous utilisez une machine d'emprunt qui tourne sous un système d'exploitation dénué d'un client SSH. Dans ces conditions, un accès shell via le Web serait d'un grand intérêt même si d'un point de vue sécurité, on a vu mieux (notamment si la machine sans SSH dispose d'un keylogger).
Ce petit article a pour objet de faire une petite revue des différents terminaux SSH libres en évaluant rapidement leurs fonctionnalités ainsi que leur mode d'installation.
Présentations
J'ai retenu trois logiciels de terminaux web:
J'ai rapidement exclu Ajaxterm essentiellement pour des raisons esthétiques: dans mon navigateur en mode tuilé, il semble que l'affichage du shell ne se passe pas correctement. Je ne pouvais pas afficher une fenêtre de terminal lisible même en essayant de modifier les paramètres de taille du terminal. Étant dans une impasse, je n'ai pas pu en tester les fonctionnalités.
Avec Shellinabox, je n'ai pas eu ces problèmes et j'ai rapidement pu me lancer à faire des tests. Ce dernier est codé en C et il semble très rapide. De son côté, Gate One est codé en Python et il dispose d'une sérieuse page de présentation. Reste à tester tout ça !
Shellinabox
Installation et configuration
aptitude install shellinabox
Suffit pour installer shellinabox et le faire tourner avec une configuration de base. Cette dernière installe le service sur le port 4200 sur toutes les interfaces réseaux. Vous pouvez y jeter un oeil en allant sur https://localhost:4200.
Par défaut, shellinabox utilise un utilisateur dédié (et non avec les pouvoirs de root) ce qui est plutôt intéressant en matière de privilèges. Mais d'un point de vue de sécurité, on peut aller plus loin. Notamment, n'oublions pas que shellinabox écoute par défaut sur toutes les interfaces réseaux et que, par conséquence, tout Internet peut s'y connecter. Il faut donc modifier un peu les options de démarrage pour pouvoir obtenir ce qu'on veut. La configuration de shellinabox se fait essentiellement dans /etc/default/shellinabox. Le répertoire /etc/shellinabox se comporte de la même manière que celui d'Apache2. On trouve en effet un ensemble de fichiers css dans le répertoire options-available qu'on active en créant des liens symboliques dans le répertoire options-enabled.
Avant toute chose, voici ce que je souhaite pour mon installation de shellinabox:
- Je souhaite y accéder via une URL du type https://my.server.example.com/terminal .
- L'accès sera uniquement sur un canal chiffré par TLS.
- L'accès à la page sera soumise à une authentification HTTP en mode Basic (étant donné qu'on utilise TLS).
- Le tout sera servi par un serveur web déjà existant (Apache2).
Voici les options que j'ai retenues pour Shellinabox dans cette configuration:
- Par défaut, il ne faut écouter que sur localhost. Pas besoin d'un trou de sécurité supplémentaire. C'est l'option --localhost-only.
- Pas besoin de travailler en mode chiffré, c'est Apache qui va gérer TLS. C'est l'option --disable-ssl.
- Je veux un port différent de celui par défaut, genre 34200. C'est l'option SHELLINABOX_PORT
A la fin, voici mon fichier /etc/default/shellinabox
:
# Should shellinaboxd start automatically SHELLINABOX_DAEMON_START=1 # TCP port that shellinboxd's webserver listens on SHELLINABOX_PORT=34200 # Parameters that are managed by the system and usually should not need # changing: # SHELLINABOX_DATADIR=/var/lib/shellinabox # SHELLINABOX_USER=shellinabox # SHELLINABOX_GROUP=shellinabox # Any optional arguments (e.g. extra service definitions). Make sure # that that argument is quoted. # # Beeps are disabled because of reports of the VLC plugin crashing # Firefox on Linux/x86_64. SHELLINABOX_ARGS="--no-beep --localhost-only --disable-ssl"
Attaquons-nous maintenant à la configuration d'Apache2. Je souhaite accéder par TLS à une page web dont l'accès est protégé par une authentification Basic qui redirige vers Shellinabox. Cette redirection sera gérée par les fonctionnalités de ReverseProxy d'Apache. Pour la partie TLS, je dispose déjà d'un service fonctionnel. Au pire, vous pouvez toujours activer le site TLS par défaut d'Apache (a2ensite default-ssl).
D'abord, il faut activer les modules mod_proxy et mod_proxy_http. Ces derniers vont permettre d'ajouter les fonctionnalités de Proxy et de ReverseProxy pour Apache:
# a2enmod proxy # a2enmod proxy_http
Ensuite, on peut simplement activer les fonctionnalités de ReverseProxy avec deux directives Apache que vous pouvez placer dans le VirtualHost par défaut:
# ShellInaBox ## On désactive les fonctions de Proxy direct ProxyRequests Off ## On active les fonctions de Mandataire inverse ProxyPass /terminal http://localhost:34200 ProxyPassReverse /terminal http://localhost:34200
ProxRequests est une directive Apache utilisée pour configurer l'accès mandataire direct. Ce n'est pas celui qui nous intéresse donc nous forçons la configuration à Off pour être sûr qu'elle soit désactivée. Viennent ensuite les directives ProxyPass et ProxyPassReverse. ProxyPass monte un reverse proxy pour l'url /terminal et exécute la requête sur localhost:34200 qui est notre serveur shellinabox. ProxyPassReverse gère les éventuelles redirections d'URL que shellinabox pourrait lancer. A priori, ce ne sera jamais le cas mais comme ça ne coûte rien, autant renseigner cette directive.
Il nous reste maintenant à gérer l'authentification. Voici l'ensemble de directives commentées pour mieux comprendre:
# Configuration ShellInaBox ## On désactive les fonctions de Proxy direct ProxyRequests Off ## Shellinabox sera disponible à l'emplacement /terminal <Location /terminal> ## On active les fonctions de Mandataire inverse ProxyPass http://localhost:34200 ProxyPassReverse http://localhost:34200 ## On donne l'accès à cet emplacement à tout Internet Order allow,deny Allow from all ## On restreint l'accès à un utilisateur dédié AuthName "Acces Shellinabox" AuthType Basic AuthUserFile /etc/apache2/shellinabox_passwd Require user shellinabox_admin </Location>
Bien entendu, il faut créer un fichier de mot de passe avec au moins un compte dedans (le compte d'accès à shellinabox):
htpasswd -c shellinabox_passwd shellinabox_admin
Voilà un exemple de sécurisation de shellinabox. De cette manière, on peut exposer ce service à Internet, la couche de protection étant apportée par Apache grâce à l'authentification. Toutefois, vous veillerez à mettre en place une directive fail2ban sur ce point pour éviter les attaques en force brute. Il existe des centaines de manières de sécuriser l'accès à ShellInabox via Apache. Cette implémentation est un moyen simple d'y parvenir, dans un contexte avec peu d'utilisateurs.
Évaluation
Une fois installé, il convient de tester la bête. Je vais vite faire le tour, car ses fonctionnalités sont assez limitées. D'ailleurs, c'est bien le but: on veut un terminal pour administrer, c'est tout !
Vous pouvez modifier le style du terminal en activant le menu utilisateur de ShellInabox en faisant un clic droit dans la fenêtre. Mon test de base s'est contenté de lancer des commandes shell et de constater que la réponse est assez rapide même sur un équipement limité.
J'ai essayé d'utiliser Emacs et j'ai été plutôt surpris par la réactivité, à condition que vous utilisiez le style monochrome sinon l'affichage est ultra-lent. J'ai également testé Mutt et tout s'est très bien passé.
Petit inconvénient, sur les claviers AZERTY, il semble que certaines touches ne passent pas, notamment les touches $/*ù). Le bug est référencé chez Debian. Cela peut être vite gênant dans l'expérience utilisateur, notamment si vous comptez abuser de cet accès au shell de votre serveur. Un moyen de contournement consiste à faire un clic-droit dans le terminal et de choisir l'outil "paste from browser". On peut alors écrire ce qu'on veut avec.
Par ailleurs, shellinabox détecte les URL http et permet de les ouvrir directement dans le navigateur Web.
Pour tester les performances, j'ai effectué le "test de la racine": ça consiste à faire un ls -R / et à voir comment se comporte l'affichage en surveillant les processus. Le retour que j'ai de ce test c'est que le processus shellinaboxd reste peu gourmand, il monte peu dans les tours de CPU. En revanche, c'est le navigateur web qui a plus de mal: il peut consommer 100% de CPU (test réalisé avec iceweasel 25). Mais ce constat me va bien: le serveur que je souhaite administrer à distance n'aura pas à pâtir de l'utilisation de Shellinabox et mon navigateur web peut bien attendre un peu !
Gate One
Installation et configuration
Gate One est un autre terminal Web. Ses sources sont disponibles sur Github et il est possible d'acheter des paquets d'installation ou de payer des licences pro. De mon côté, je vais juste partir des sources pour "compiler" (c'est du Python). Pour cela, vous aurez besoin du paquet python-stdeb.
$ git clone https://github.com/liftoff/GateOne.git # aptitude install python-stdeb python-concurrent.futures $ cd GateOne $ python setup.py --command-packages=stdeb.command bdist_deb $ cd deb_dist # dpkg -i ./gateone_1.2.0-1_all.deb
Le paquet produit n'est pas conforme à la sauce debian. Notamment, il utilise le répertoire /opt/ pour placer l'ensemble du programme ainsi qu'une partie de la configuration. Dans la pratique, ça ne change pas grand chose. La configuration est gérée dans /opt/gateone/settings dans un format un peu bizarre. En effet, les directives de configuration sont au format JSON, ce que je trouve loin d'être lisible. Les fichiers .conf de ce répertoire sont lus dans l'ordre alphabétique.
Néanmoins, si vous tentez d'utiliser GateOne sur Debian Wheezy (mon cas), vous aurez quelques difficultés. En effet, certains paquets ne sont pas à la bonne version. C'est notamment le cas de python-tornado. Vous pouvez utiliser la version de Debian Jessie et l'installer manuellement avec dpkg. Il m'a fallu également ajouter le paquet python-concurrent.futures pour pouvoir lancer gateone.
Si vous voulez juste tester le logiciel, il suffit de le lancer une première fois. GateOne s'occupe alors de créer des fichiers de configuration initiaux dans /opt/gateone/settings
. Notamment, le fichier 10server.conf
qui gère le lancement du service gateone. Vient ensuite le fichier 20authentication.conf
qui gère la partie authentification qui est réglée par défaut sur Pam. Enfin, on trouve un fichier 50terminal.conf
chargé de créer une "application" de connexion de terminal via SSH. De ce que j'en retiens, on pourrait imaginer de créer une autre application genre le lancement de Mutt. Tous les réglages sont expliqués dans la documentation officielle.
Évaluation
Maintenant que GateOne est lancé, il faut l'évaluer. Il est d'abord beaucoup plus complexe à configurer. Les nombreux fichiers pour le régler finement en attestent. Les fonctionnalités de GateOne sont plus nombreuses également. Ainsi, il propose la gestion de plusieurs terminaux, de conserver les logs de connexions ou encore de re-visualiser une session. Il est donc beaucoup plus orienté professionnel où l'on doit se servir en permanence de plusieurs terminaux sur plusieurs machines différentes. Le terminal de GateOne propose lui aussi la détection des URL pour les ouvrir dans le navigateur.
Une fonction qui peut sembler gadget est la possibilité de rejouer une session en cliquant sur la timeline située en bas de l'écran. On peut alors revoir tout ce qui s'est passé dans le terminal depuis le début de la session. C'est important pour un serveur de bastion où on doit pouvoir tracer l'activité des administrateurs.
GateOne propose également un système de marques-pages qui permet de se connecter sur plusieurs serveurs différents en un clic. Enfin, on peut noter la présence d'un plugin SSH qui permet de gérer vos clefs ainsi que de répliquer des sessions SSH.
J'ai également effectué le test du ls -R / et de ce côté, c'est moins flatteur. En effet, le process python qui fait tourner GateOne se met à consommer une puissance CPU qui n'a rien à voir avec celle de shellinabox (50% d'un CPU au lieu de 2%) et il n'y avait qu'un seul utilisateur du côté serveur. En conséquence, je pense que GateOne n'est pas adapté pour tourner sur un Sheevaplug ou tout autre serveur à la puissance limitée. Je n'irai donc pas plus loin dans les tests même si cet outil me semble fonctionnellement un cran au dessus de Shellinabox.
Conclusion
De ces petits tests de logiciels de terminaux web, je retiendrai que Shellinabox correspond tout à fait à mes besoins. Il est simple à gérer, peu gourmand, bien intégré à Debian et sans fioritures. On peut facilement l'intégrer à une configuration Apache existante. GateOne est intéressant dans ses fonctionnalités. On sent qu'il veut se faire un peu plus professionnel, notamment avec la timeline et les options de gestion de SSH. Je le vois plus comme une solution de serveur de bastion où tout passerait par le navigateur Web.