Dans cet article, nous regardons comment jouer avec le port forwarding de SSH.

Monter un client/serveur minimal

Nous disposons de deux machines A et B. Nous mettons en place un serveur d’écoute minimal sur la machine B grâce à l’outil netcat que je vous invite à découvrir si vous ne le connaissez pas.

donut@B: nc -l 50001

Du côté de A qui joue le rôle du client, on peut se connecter sur B grâce à telnet via la commande :

donut@A: telnet B 50001

Désormais, tout ce qui est tapé dans l’un des deux terminaux sera affiché dans l’autre. Magique :)

Dans ce contexte A joue le rôle du client et B le rôle du serveur, ainsi que l’illustre le petit diagramme ci-dessous.

Serveurs A et B, cas 1

Bref, tout va bien dans le meilleur des mondes mais soudain, vous vous heurtez à deux difficultés potentielles :

  • vous découvrez avec stupeur que le protocole telnet n’est absolument pas chiffré et que donc un intrus pourrait tout à fait intercepter vos communications
  • pour une raison quelconque, le port 50001 de la machine B n’est plus accessible depuis l’extérieur : A ne peut plus s’y connecter

Dans ces deux situations, ssh peut vous venir en aide via le port forwarding (ou redirection de port en français). C’est ce que nous allons voir maintenant. Dans la suite, il est crucial de bien distinguer les rôles de client/serveur selon qu’on parle de notre serveur minimal ou bien du serveur ssh.

Redirection de port locale

Dans ce premier cas de figure, le serveur ssh tourne sur la même machine que notre serveur minimal, à savoir B.

  A B
Netcat Client Serveur
SSH Client Serveur
donut@A: ssh -N -L 2001:localhost:50001 B

L’option -N signifie qu’on ne souhaite pas exécuter de commande via ssh mais juste mettre en place une redirection de port. L’option -L signifie une redirection de port directe. Ici nous avons mis comme argument 2001:localhost:50001, ce qui signifie “met en place une redirection de port du port local 2001 vers le port distant 50001 de la machine B. Le schéma TCP/IP associé est alors le suivant.

Serveurs A et B, cas 2

Maintenant nous pouvons nous connecter à la machine B avec telnet via la commande :

donut@A: telnet localhost 2001

Les deux terminaux sur A et B communiquent de nouveau ! L’énorme différence par rapport au cas précédent est que :

  1. les communications entre A et B sont désormais chiffrées par ssh
  2. nous ne passons plus du tout par le port 50001 de la machine B

Si le serveur ssh est accessible sur B et que sa configuration autorise la redirection de port (via le paramètre AllowTcpForwarding du fichier sshd_config pour OpenSSH) alors on se rend compte qu’on peut accéder à n’importe quel port de la machine B via une commande ssh correctement construite. Il est à noter que par défaut OpenSSH autorise la redirection de port.

Dans le cas d’étude que nous venons de voir, serveur minimal (netcat) et serveur ssh tournent sur la même machine. Si tel n’est pas le cas (serveur ssh sur A par exemple), alors la commande ci-dessus échouera puisqu’un ssh vers B sera impossible. Nous verrons toutefois qu’un client ssh sur B pourra se connecter sur le serveur ssh A de telle sorte qu’un client telnet sur A pourra tout de même se connecter sur le serveur netcat B (respirez profondément et relisez tranquillement). C’est l’enjeu de la section suivante.

Redirection de port distante

Dans ce contexte, la machine B héberge toujours le serveur netcat mais cette fois-ci le serveur ssh tourne sur A.

  A B
Netcat Client Serveur
SSH Serveur Client

Sur la machine B, le client SSH va se connecter sur A en utilisant une redirection de port distant e afin de permettre au client telnet de A de se connecter au serveur Netcat sur B.

donut@B: ssh -N -R 2001:localhost:50001 A

L’argument -N joue le même rôle que précédemment, l’argument -L est ici remplacé par -R qui signifie que le port 2001 est distant : il sera créé sur A (et non plus la machine cliente ssh B). Le diagramme TCP/IP est alors le suivant :

Serveurs A et B, cas 3

Un utilisateur de A pourra alors se connecter au serveur Netcat sur B via un telnet local :

donut@B: donut@A: telnet localhost 2001

Sécurisation d’une caméra IP

Je dispose d’une petite caméra IP motorisée. Cette dernière est accessible par une interface web basique en http. Comme d’une part, je ne sais pas trop ce qui tourne derrière et que, d’autre part, les mots de passe transitent en clair, je n’ai pas du tout envie de l’ouvrir sur l’extérieur. Ca tombe bien, j’ai un raspberry qui traîne :)

Ma caméra IP C est donc située sur mon réseau privé, de même que mon raspberry B. Ma caméra écoute sur le port 81. Sur le raspberry tourne un serveur SSH potentiellement accessible de l’extérieur. Sur mon poste client A, situé n’importe où, il me suffit donc de taper dans un premier temps :

$ ssh -N -L 51123:ip-camera:81 ip-du-raspberry

Il me suffit ensuite de me connecter à la caméra depuis A, en me connectant sur le port 51123 de la boucle locale. Ceci est illustré dans les figures ci-dessous, toutes deux obtenues depuis la machine A : en haut, je suis connecté directement à la caméra; en bas je suis connecté à la boucle locale. Magique !

Camera IP, acces direct

Camera IP, acces via ssh