Tunnels locaux statiques

SSH permet de créer un tunnel entre un port du poste local et un port d'un serveur éloigné. Un logiciel qui se connecte au port local dialogue en réalité avec le port du serveur éloigné.

Syntaxe générale :

ssh -L [interface_locale]:[port_local]:[serveur_distant]:[port_distant] [utilisateur]@[serveur_ssh]

Le premier paramètre, l'adresse IP de l'interface locale associée au port d'entrée du tunnel, est facultatif. S'il est omis, le tunnel est associé à l'adresse 127.0.0.1 (ou selon le paramètre GatewayPorts du fichier de configuration).

Syntaxe simplifiée :

ssh -L [port_local]:[serveur_distant]:[port_distant] [utilisateur]@[serveur_ssh]

Important : dès lors qu'on utilise des noms d'hôte plutôt que des adresses IP pour définir le serveur distant et le serveur SSH, ces serveurs peuvent se trouver sur le même ordinateur ou sur deux machines différentes. Cependant, si le serveur SSH et le serveur final ne sont pas sur le même ordinateur, la connexion est chiffrée du poste local au serveur SSH, mais en clair du serveur SSH au serveur final.

Les exemples ci-dessous associent des ports du poste local au port Web et au port POP de serveurs éloignés par l'intermédiaire d'un serveur SSH.

ssh -L 2080:www.google.fr:80 alex@ssh.exemple.fr
w3m http://localhost:2080

ssh -L 9999:pop.un_fai.fr:110 alex@ssh.exemple.fr

Cas particulier : serveur SSH et serveur final sur le même ordinateur

Lorsque le serveur final et le serveur SSH se trouve sur le même ordinateur, on peut omettre le nom du serveur final dans la ligne de commande en adoptant la syntaxe suivante :

ssh -L [port_local]:localhost:[port_distant] [utilisateur]@[serveur_ssh]

Exemple :

ssh -L 2080:127.0.0.1:80 alex@ssh.exemple.fr
ssh -L 2080:localhost:80 alex@ssh.exemple.fr

Cette commande établit un tunnel entre le port 2080 du poste local et le port 80 de l'ordinateur qui héberge le serveur SSH. Le port local 2080 est ainsi associé au port 80 du serveur. Un navigateur qui se connecte à 127.0.0.1:2080 affiche donc les informations renvoyées par le port 80 du serveur Web.

Les connexions sont chiffrées du port 2080 local au port 22 (par défaut) du serveur SSH, puis en clair du serveur SSH au port 80 de la même machine.

Tunnels dynamiques

SSH permet de créer un tunnel dynamique entre le poste local et le serveur SSH. Ce dernier joue alors le rôle d'un proxy qui relaie vers des serveurs éloignés les connexions établies localement.

Syntaxe :

ssh -D [interface_locale]:[port_local] [utilisateur]@[serveur_ssh]

Exemple :

ssh -D 9999 alex@ssh.exemple.fr

Comme précédemment, l'adresse IP de l'interface locale peut être omise.

Les applications se connectent au port local à l'aide du protocole SOCKS 5 et les requêtes sont transmises au serveur SSH, qui les relaie jusqu'aux serveurs finals. Deux conséquences :

  • Les requêtes semblent provenir du serveur SSH, ce qui masque l'adresse IP du client.
  • Les connexions utilisant un protocole en clair (HTTP, par exemple) sont chiffrées entre le client et le serveur SSH, puis en clair du serveur SSH au serveur final (serveur Web, par exemple).

Pour plus d'informations sur le paramétrage de Firefox pour utiliser un tunnel dynamique avec SOCKS 5, consultez cet article.

Dans l'exemple ci-dessus, le tunnel est ouvert du poste local à un serveur SSH. L'entrée du tunnel est donc associée à l'adresse localhost. Rien n'interdit cependant d'ouvrir un tunnel SSH entre deux serveurs SSH, et de s'y connecter à partir du client, si ce tunnel est partagé (voir ci-dessous la section Partage de tunnels).

Tunnels distants

Un tunnel distant redirige un port d'un serveur éloigné vers un port du poste local sur lequel la commande est exécutée (voire vers un autre poste).

Imaginons un réseau local comportant une passerelle et un serveur public (visible sur Internet) situé dans une DMZ. On peut permettre aux utilisateurs externes de se connecter à un serveur de la passerelle, sans pour autant ouvrir à tout le monde les ports correspondants sur le pare-feu, en créant un tunnel distant entre le serveur public et la passerelle. Les visiteurs se connecteront au serveur public, mais les connexions seront transférées vers la passerelle via un tunnel SSH.

Syntaxe :

ssh -R [port_source]:[serveur_cible]:[port_cible] [utilisateur]@[serveur_ssh]

Par exemple, pour rediriger le port 80 du serveur public vers le port 80 de la passerelle, on exécute la commande ci-dessous sur la passerelle :

ssh -R 80:passerelle.exemple.fr:80 alex@serveur_public.exemple.fr

On peut également rerouter les connexions du serveur public à un autre poste du réseau local par l'intermédiaire de la passerelle en exécutant la commande ci-dessous sur cette dernière :

ssh -R 80:serveur_privé.exemple.fr:80 alex@serveur_public.exemple.fr

Autre possibilité, se connecter en SSH à un poste équipé d'un serveur SSH, mais normalement inaccessible dans le sens entrant en raison d'un pare-feu.

Sur le poste interne, ouvrez un tunnel distant du poste externe vers localhost. Ensuite, sur le poste externe, vous pouvez vous greffer sur le tunnel existant pour établir une connexion avec le poste interne, même si ce dernier est situé derrière un pare-feu qui n'autorise pas les connexions entrantes provenant d'Internet.

1. Ouverture du tunnel distant :

Commande sur le client (derrière le pare-feu) :

ssh -R 2222:127.0.0.1:22 alex@ssh.exemple.fr

Un serveur SSH doit être installé sur le client pour que ce dernier puisse répondre à l'ouverture d'une connexion SSH au travers du tunnel inversé. Dans l'exemple ci-dessus, il faut qu'un serveur SSH soit associé au port 22 de l'interface 127.0.0.1. Si le serveur SSH écoute à une autre interface, il faudra modifier la commande en conséquence.

2. Réutilisation du tunnel distant :

Sur le serveur, pour afficher la liste des sessions ouvertes :

last -1

alex  pts/0  client.exemple.fr Thu Jan 21 19:28  still logged in

Pour afficher des infos sur une session :

ps -t pts/0

  PID TTY          TIME CMD
 4401 pts/0    00:00:00 bash

Pour se reconnecter au client à partir du serveur :

ssh -p [port_serveur] [utilisateur]@localhost

Exemple :

ssh -p 2222 alex@localhost

Partage de tunnels

Par défaut, les ports transférés ouverts sur le client (tunnel local ou dynamique) ou sur le serveur (tunnel distant) ne sont associés qu'à l'adresse 127.0.0.1. Il est cependant possible de les partager pour permettre à d'autres ordinateurs de les utiliser.

Tunnel local partagé :

ssh -g -L [interface]:[port_local]:localhost:[port_serveur] [utilisateur]@[serveur_ssh]

ssh -g -L [interface]:[port_local]:[serveur_distant]:[port_serveur] [utilisateur]@[serveur_ssh]

Si aucune interface n'est précisée, le paramètre -g associe le tunnel à toutes les interfaces réseau de l'ordinateur.

Exemples :

ssh -g -L 192.168.0.2:2025:localhost:25 alex@serveur_ssh.exemple.fr

Cette commande ouvre un tunnel entre le port 2025 du poste local et le port 25 du serveur SMTP exécuté sur le même ordinateur que le serveur SSH. Le tunnel est associé à l'interface réseau 192.168.0.2. Les ordinateurs tiers qui se connectent à 192.168.0.2:2025 dialoguent ainsi avec serveur_ssh.exemple.fr:25.

ssh -g -L 192.168.0.2:2080:www.google.fr:80 alex@serveur_ssh.exemple.fr

Cette commande ouvre un tunnel entre le port 2080 du poste local et le serveur SSH, et l'associe à l'interface réseau 192.168.0.2. A partir du serveur SSH, les connexions sont transmises en clair jusqu'au port 80 de l'adresse www.google.fr Quand un navigateur d'un poste tiers se connecte à l'adresse 192.168.0.2:2080 (il faut évidemment que le pare-feu le permette), la page Web de www.google.fr apparaît.

Autre possibilité : dans le fichier de configuration (~/.ssh/config ou /etc/ssh/ssh_config), ajoutez l'option GatewayPorts yes.

Tunnel dynamique partagé

Syntaxe :

ssh -g -D [interface]:[port_local] [utilisateur]@[serveur_ssh]

Exemple :

ssh -g -D 192.168.0.2:9999 alex@serveur_ssh.exemple.fr

Si le pare-feu le permet, tous les postes du réseau local peuvent par exemple surfer sur le Web par l'intermédiaire de ce tunnel SSH en déclarant un proxy SOCKS 5 dans Firefox.

Tunnel distant partagé

Dans le fichier /etc/ssh/sshd_config du serveur, ajoutez l'option GatewayPorts yes. L'option PermitOpen permet de limiter les adresses IP et les ports vers lesquels les transferts de ports sont autorisés.

Sur le client :

ssh -R 2222:192.168.1.2:22 alex@serveur_ssh.exemple.fr

Sur un 2ème client :

ssh -p 2222 serveur_ssh.exemple.fr

Cette connexion est renvoyée vers le port 22 du 1er client par l'intermédiaire du port 2222 du serveur SSH.

Autre solution, dans le fichier /etc/ssh/sshd_config du serveur, ajoutez l'option GatewayPorts clientspecified. Ce paramètre permet au client qui ouvre le tunnel distant de définir l'interface à laquelle le port transféré doit être associé.

Sur le client :

ssh -R 192.168.1.3:2222:192.168.1.2:22 alex@serveur_ssh.exemple.fr

Le port 2222 sera accessible par les postes tiers.

ssh -R 127.0.0.1:2222:192.168.1.2:22 alex@serveur_ssh.exemple.fr

Ici, le port 2222 ne sera accessible qu'en local.

ssh -R 2222:192.168.1.2:22 alex@serveur_ssh.exemple.fr

Même chose quand aucune interface n'est définie expressément.

Options utiles

  • -N permet d'établir un tunnel sans ouvrir de terminal sur le serveur SSH.
  • -f permet de lancer ssh en arrière-plan.

Exemple :

ssh -f -N -L 2080:127.0.0.1:80 alex@ssh.exemple.fr

Documentation