L’un des outils les plus polyvalents que nous ayons à notre disposition est ssh. Plus connu comme l’outil d’accès à distance de choix pour l’administration d’hôtes distants, il possède de nombreuses autres fonctionnalités pratiques qu’il est vraiment utile de connaître. Par exemple, nous pouvons utiliser ssh pour transférer des fichiers, monter des hôtes distants en tant que systèmes de fichiers réseau et générer des clés.

Dans ce tutoriel, nous allons creuser un peu plus les capacités de proxy et de tunneling de ssh.

Concepts

Dès les premiers jours de la pile TCP/IP, l’accès aux nœuds distants était indispensable. Cependant, les protocoles conçus à cet effet – telnet pour l’accès interactif et FTP pour les transferts de fichiers – manquaient d’une mesure de sécurité très élémentaire : le flux de données n’était pas crypté.

Par conséquent, les données transférées à l’aide de ces protocoles peuvent être capturées et examinées par des outils d’analyse du trafic réseau tels que tcpdump et Wireshark. Comme le nom d’utilisateur et le mot de passe ont été échangés en clair, il est facile pour un attaquant de les recueillir.

Pour résoudre ce problème et d’autres limitations, ssh implémente le cryptage dans ses connexions. Ainsi, à condition d’utiliser une configuration adéquate, un chiffrement fort et des schémas d’échange de clés, nous pouvons être sûrs que notre communication ne sera pas interceptée en cours de route.
freestar

L’une des fonctions les plus utiles, et peu connue, est la possibilité d’établir des tunnels et des proxies. De cette façon, nous pouvons utiliser une session ssh pour nous connecter à d’autres services distants qui ne nous sont pas visibles autrement, comme ceux qui sont protégés par un pare-feu :

Comme on le voit sur l’image, une machine cliente, en ouvrant la session ssh, demande au serveur SSH d’ouvrir des tunnels qui peuvent fonctionner dans les deux sens.

Il peut également fonctionner comme un proxy pour le protocole XWindows, nous permettant d’ouvrir localement des applications GUI distantes, ou comme un serveur proxy conforme à SOCKS 4 ou 5, permettant au client d’accéder à plusieurs destinations du site distant en se faisant passer pour le serveur SSH.

Encore plus impressionnant et dangereux, car il permet une expérience complète de type VPN, est la capacité de tunnelliser des paquets de niveau 2 ou 3 en utilisant des dispositifs tun.

Configuration du serveur

Tout d’abord, il convient de noter que l’autorisation de tunnels par le biais de connexions ssh peut constituer un risque pour la sécurité, car elle peut transgresser nos politiques de pare-feu. En tant que tel, il faut veiller à ne pas exposer des services et des hôtes que nous préférerions garder fermés à un accès non désiré. Pour cette raison, certaines distributions Linux désactivent par défaut les tunnels et les proxys.
freestar

Options SSHD

L’activation de sshd, le démon qui gère les sessions ssh, se fait en éditant le fichier sshd_config. Son emplacement varie un peu mais se trouve généralement dans /etc/ssh ou /etc/openssh. Les clés de configuration pertinentes sont :

AllowStreamLocalForwarding : Permet aux sockets du domaine Unix d'être transférés. La valeur par défaut, lorsqu'elle est omise, est yes
AllowTcpForwarding : Autorise la redirection des ports TCP. La valeur par défaut, lorsqu'elle est omise, est "allow". Il active les transferts de ports TCP simples et le proxy socks.
DisableForwarding : Désactive tous les types de transfert. Remplace, si elles sont activées, toutes les autres options de configuration connexes.
GatewayPorts : Permet aux autres hôtes d'utiliser les ports transférés à un client (tunnels inversés). Par défaut, seuls les hôtes exécutant le serveur SSH peuvent utiliser les tunnels inversés. Désactivé par défaut
PermitListen : Spécifie les adresses et les ports qui peuvent être liés pour autoriser le transfert de port vers les clients. Il fournit un contrôle plus fin si on active GatewayPorts. La valeur par défaut est localhost ('127.0.0.1' et '::1').
PermitOpen : Spécifie l'adresse et les ports vers lesquels une redirection TCP peut pointer. Par défaut, toute destination est autorisée
PermitTunnel : Spécifie si le transfert de périphérique tunnel est autorisé. La valeur par défaut est non
X11Forwarding : Indique si le transfert X11 est autorisé. La valeur par défaut est non
X11UseLocalhost : Force le transfert X11 à être autorisé uniquement à partir de l'adresse de bouclage de l'hôte du serveur SSH. S'il est désactivé, d'autres hôtes sur le réseau du serveur SSH peuvent l'utiliser. La valeur par défaut est true.

Autres configurations

D’autres configurations sur l’hôte peuvent affecter la capacité du serveur SSH à transférer et à utiliser un proxy. AppArmor et SELinux peuvent inhiber certaines de ces options. De même, certaines configurations du pare-feu de l’hôte peuvent limiter la possibilité de se connecter à des services externes (voir notre tutoriel sur iptables). Notez que la liaison des ports d’écoute sous 1024, par défaut, nécessite les privilèges de l’utilisateur root.

Et, bien sûr, les pare-feu intermédiaires doivent autoriser le trafic SSH, généralement sur le port TCP/22, mais nous pouvons utiliser d’autres ports en modifiant la valeur par défaut du fichier sshd_config.

Transférer les tunnels TCP

Port unique

Un tunnel TCP direct ou forward est celui qui suit la direction de la connexion SSH du client au serveur SSH. Notre tutoriel d’introduction à SSH décrit brièvement ce type de transfert. Pour créer un tunnel direct TCP forward, nous devons utiliser l’option -L sur la ligne de commande :

ssh -L [bind_address :]port:host:hostport [user@]remote_ssh_server

L’option bind_address attribue une interface locale au client pour écouter les connexions. Si nous l’omettons, ssh se connecte uniquement sur les interfaces de bouclage. Nous pouvons également utiliser « 0.0.0.0 » ou « : : » pour nous lier sur toutes les interfaces. Donc, si nous lançons la commande suivante :

ssh -L 0.0.0.0:8022:10.1.4.100:22 user@10.1.4.20

Nous aurions une connexion SSH ouverte à l’hôte sur l’adresse IP 10.1.4.20 et un tunnel, écoutant sur le port client 8022, pointant vers l’adresse SSH de l’hôte 10.1.4.100.

De cette façon, si une connexion entre dans le port client 8022, elle sera transférée vers l’hôte et le port de destination, en utilisant l’adresse IP du serveur SSH, en ressemblant exactement à un réseau local normal entre eux.

De même, pour transférer des sockets locaux (un peu moins habituel), nous pouvons utiliser :

ssh -L local_socket:host:hostport [user@]remote_ssh_server

Ou nous pouvons utiliser :

ssh -L local_socket:remote_socket [user@]remote_ssh_server

Dynamique ou multiport

Un cas particulier des tunnels TCP de transfert est la capacité de proxy Socks. En utilisant ces options, le client SSH écoute sur un port de liaison spécifié et agit comme un serveur proxy SOCKS 4 ou 5.

Toute connexion utilisant le protocole SOCKS sur le port de liaison sera transmise au serveur SSH en utilisant sa propre adresse IP. Pour cela, il faut utiliser

ssh -D [bind_address :]port [user@]remote_ssh_server

Notez que nous n’avons même pas besoin de spécifier l’hôte et le port de destination pour la redirection dans ce cas. Toutes les connexions entrantes conformes à SOCKS sur le port spécifié passeront par le tunnel.

Pour l’utiliser, nous devons, bien sûr, configurer l’application qui utilisera le tunnel pour utiliser un serveur proxy sur l’adresse et le port liés spécifiés sur la ligne de commande. Par exemple, après avoir émis la commande
freestar

ssh -D 8080 user@10.1.4.100

nous pouvons configurer un navigateur sur l’hôte client pour utiliser notre serveur proxy SOCKS sur 127.0.0.1, port 8080. De cette façon, nous pouvons naviguer sur le Web comme si nous utilisions un navigateur installé sur le serveur SSH situé à 10.1.4.100.

Et si l’application cliente ne prend pas en charge le proxy SOCKS ? Nous pouvons utiliser des solutions telles que proxychains ou tsocks qui interceptent les appels système des sockets et forcent les connexions à passer par un proxy SOCKS.

Tunnels inversés

Port unique

Les proxys inversés ou de rappel nous permettent de faire des astuces similaires à celle ci-dessus mais dans le sens inverse. Nous pouvons ouvrir des services sur nos propres réseaux locaux à des hôtes du côté distant de la session SSH. La syntaxe de la commande est assez similaire à celle du sens direct :

ssh -R [bind_address :]port:host:hostport [user@]remote_ssh_server

Cette commande crée un tunnel inverse. Il transfère toute connexion reçue sur le serveur SSH distant à l’adresse bind_address:port vers le réseau client local host:hostport. Si nous omettons le paramètre bind_address, il se lie uniquement aux interfaces de bouclage.

De même, en utilisant les sockets, nous pouvons utiliser trois syntaxes différentes :

ssh -R remote_socket:host:hostport [user@]remote_ssh_server

ssh -R remote_socket:local_socket [user@]remote_ssh_server

ssh -R [bind_address :]port:local_socket [user@]remote_ssh_server

Dynamique ou multiport

Enfin, nous pouvons exposer un serveur proxy SOCKS sur l’hôte distant dirigé vers le réseau du client, comme nous pouvons le faire avec la redirection directe. Pour ce faire, nous devons omettre l’hôte et le port de destination locaux :

ssh -R [bind_address :]port [user@]remote_ssh_server

Cela ouvre un port sur le serveur SSH distant qui servira de serveur SOCKS au réseau client local, ce qui peut permettre de contourner les règles de trafic sortant qui s’appliqueraient autrement au serveur SSH distant.

Tunnels X Windows

Un cas particulier de tunneling inverse est la possibilité de tunneler les connexions X11. De cette façon, les applications GUI exécutées sur le côté distant des connexions SSH peuvent utiliser le côté local exécutant des serveurs X pour exposer leurs interfaces utilisateur.

SSH se charge d’établir les tunnels nécessaires. Il définit également les variables d’environnement DISPLAY nécessaires aux applications client X sur le serveur SSH. Ainsi, elles sauront comment se connecter correctement au serveur X du client local.

Il existe deux types de transfert X11, qui appliquent les restrictions de l’extension de sécurité X11 (voir xhost et xauth, pour référence) :

ssh -X [user@]remote_ssh_server

Ou créer le tunnel en supposant un environnement de confiance qui n’appliquera pas l’extension de sécurité X11 :

ssh -Y [user@]remote_ssh_server

Tunnels multiples et sauts d’hôtes multiples

Nous pouvons créer autant de tunnels que nous le souhaitons, en mélangeant les types et les directions. Nous pouvons accomplir cela en ajoutant plus d’options à la ligne de commande :

ssh -X -L 5432::5432 -R 873::873 [user@]remote_ssh_server

Ceci ouvre un tunnel direct vers un serveur PostgreSQL distant, un tunnel inverse vers un serveur rsync local, et permet aux applications GUI de s’écouler vers notre serveur X local.

Et nous pouvons également utiliser des tunnels SSH pour atteindre des serveurs SSH plus éloignés, en créant des tunnels vers eux en perçant autant de couches de pare-feu que nécessaire, en créant le tunnel sur chaque connexion jusqu’à ce que nous puissions atteindre le point souhaité :

ssh -L 8022::22 user@server1
ssh -L 8023::22 -p 8022 user@localhost
ssh -p 8023 utilisateur@localhost

Cette séquence crée, à chaque étape, un tunnel vers le serveur suivant, depuis le serveur1, et le serveur2, jusqu’à ce que le tunnel ouvert sur le port local 8023 nous permette d’atteindre le serveur3.

Fichiers de configuration

Dans des scénarios complexes, la création de plusieurs tunnels sur la ligne de commande peut s’avérer délicate, car elle peut conduire à des lignes de commande vraiment longues.
freestar

C’est pourquoi l’une des plus belles caractéristiques de ssh est d’autoriser tout paramètre de ligne de commande dans les fichiers de configuration. Nous pouvons utiliser le fichier de configuration global du client ssh (situé dans /etc/ssh/ssh_config ou/etc/openssh/ssh_config) ou utiliser le fichier de configuration spécifique de notre utilisateur qui est situé dans ~/.ssh/config. S’il n’existe pas, ce qui est le cas par défaut, nous devrons en créer un nouveau.

Dans ces fichiers, nous pouvons spécifier des configurations par défaut pour chaque point de terminaison couramment utilisé, y compris les tunnels de transfert et les proxies :

host 10.1.4.100
ForwardX11 oui
LocalForward 0.0.0.0:5432 10.1.4.200:5432
RemoteForward localhost:8022 localhost:22
utilisateur baeldung

Cette opération permet de se connecter au serveur SSH distant sur 10.1.4.100, en utilisant l’utilisateur ‘baeldung’ :

X Windows reverse tunnel
Tunnelage direct du port local 5432 à l'hôte distant 10.1.4.200 port 5432
Tunnel inverse/de secours sur le port 8022 dans les interfaces de bouclage du serveur SSH vers notre hôte client local.

De nombreuses autres options sont disponibles, comme la compression, la redirection de l’authentification Kerberos, et bien d’autres encore. En outre, la spécification de l’hôte autorise les caractères génériques.

Tunnels persistants

À propos, un tunnel SSH n’existe que tant que la connexion SSH est maintenue. Même si nous pouvons configurer la fréquence et le délai d’attente pour les « keepalives » de session afin de faciliter la détection des pertes de connexion, il serait agréable d’automatiser complètement la création et la reconnexion des sessions SSH.

Pour cela, un logiciel très pratique est autossh. Cet utilitaire peut créer et recréer automatiquement des sessions SSH. Si nous ajoutons des clés d’authentification, comme indiqué dans notre tutoriel sur les clés SSH, les tunnels s’ouvriront sans intervention de l’utilisateur, tant qu’autossh est en cours d’exécution. Sa syntaxe est la suivante

autossh [-V] [-M port[:echo_port]] [-f] [SSH_OPTIONS]

-V : Montre la version d'autossh
-M : Crée un tunnel direct sur un port, bouclé vers un tunnel inverse, echo_port. Il fournit un mécanisme de vérification de vie. Cependant, avec OpenSSH récent, nous pouvons obtenir des résultats similaires en utilisant les options ServerAliveInterval et ServerAliveCountMax dans le fichier sshd_config
-f : Force autossh à s'exécuter en arrière-plan avant de lancer ssh.
SSH_OPTIONS : Les options que nous utiliserions pour démarrer ssh

Ainsi, pour démarrer une connexion persistante, nous pouvons utiliser :

autossh -X -L 5432::5432 -R 873::873 [user@]remote_ssh_server

Si nous avons défini une configuration d’hôte, la ligne de commande est beaucoup plus simple :
freestar

autossh -f [host]

Conclusion

Cet article a montré quelques trucs sympas que nous pouvons faire avec ssh pour améliorer notre accessibilité à, ou depuis, des hôtes distants en utilisant ses capacités de tunneling.

Cependant, nous devons toujours garder à l’esprit que l’accès par ssh à un hôte élargit sa surface de cyberattaque. Ainsi, l’utilisation de tout type de tunneling peut augmenter les risques, en permettant un mouvement horizontal plus facile à travers notre réseau de serveurs SSH.

Enfin, il existe un type de tunneling encore plus avancé : le tunneling de dispositif tun. C’est encore plus dangereux, car il agit comme un VPN (réseau privé virtuel) à part entière. Ce type de tunnel lie les deux segments de réseau distants où se trouvent les points d’extrémité.

Nous pouvons l’utiliser pour créer des tunnels de couche 2 qui se comportent comme si les deux côtés étaient sur le réseau local ou des tunnels de couche 3. Dans ce cas, chaque côté possède son propre sous-réseau IP et les terminaux SSH doivent être configurés pour acheminer le trafic entre eux.