Le tunnel SSH, la solution pour accéder à vos équipements derrière une connexion mobile

Afin de pallier à l'épuisement des adresses IPv4, les opérateurs mobiles recourent à la technique du "CG-NAT", qui a l'effet d'un pare-feu empêchant l'accès depuis l'extérieur à un équipement connecté avec une offre mobile grand-public.

Voici une solution de contournement.

A l'exception de quelques offres (par exemple ce routeur 4G entreprises associé à une adresse IPv4 "publique"), les offres mobiles grand public actuelles sont basées sur le "CG-NAT" (Carrier Grade - Network Address Translation), qui consiste à regrouper des centaines ou milliers de clients mobiles sur une seule adresse IPv4 publique, à laquelle seront rattachées autant d'adresses privées que nécessaires, lesquelles ne permettent pas les connexions entrantes.

Autrement dit, quand votre équipement vous indique que votre adresse IP est la "10.21.194.19", il s'agit d'une adresse privée non routable et quand une page telle que celle mise à disposition par LaFibre.info vous indique que votre adresse publique est "92.184.104.243", vous devez savoir que vous ne pouvez pas utiliser cette dernière en connexion entrante.

Ainsi, que votre besoin soit ponctuel (à travers un partage de connexion) ou permanent (utilisation d'un routeur 4G pour un bureau ou équipement autonome disposant d'une clé 4G comme un Raspberry pi par exemple), vous devrez recourir à une solution de contournement pour permettre ces connexions entrantes.

Description du cas pratique

Dans le cadre de cet article, je considèrerai l'usage suivant :

  • un Raspberry pi, pour lequel je souhaite accéder à la ligne de commande depuis l'extérieur,
  • un routeur 4G doté d'une sim associée à une offre mobile grand public,
  • un serveur VPS "lambda" (accessible à partir de quelques euros par mois, par exemple chez SHPV) et doté d'une IPv4 publique,
  • n'importe quel mobile doté d'une application telle que JuiceSSH, ou ordinateur disposant de Putty s'il s'agit de Windows ou GNU/Linux.

Les adresses, ports, identifiants utilisés sont les suivants :

  • adresse du VPS : 185.212.222.222
  • port d'écoute du VPS : 2022
  • utilisateur autorisé en connexion SSH sur le VPS : toto
  • port de connexion depuis le VPS : 22022
  • port d'écoute du Raspberry : 222
  • utilisateur autorisé en connexion SSH sur le pi : toto

Je précise ici que les numéros de port, adresses IPv4 ou autres présentés dans l'article ne sont bien évidemment pas ceux que j'utilise, il appartient à chacun d'effectuer un minimum de travail de documentation et d'analyse afin d'adapter ses propres paramètres.

Paramétrage des ports sur le VPS et le Raspberry

Sur le VPS, l'opération est simplissime, il convient d'ajouter, en root, un port d'écoute SSH dans le fichier "/etc/ssh/sshd_config", par exemple le 2022, en supposant qu'un utilisateur "toto" est déjà créé et en mesure de se connecter en SSH.

Le fichier sshd_config devra donc comporter in fine au minimum la ligne suivante (il ne s'agit pas du contenu in extenso) :

  • # What ports...
  • Port 2022

Il faut ensuite relancer le service SSH "/etc/init.d/ssh restart".

Même chose sur le Raspberry, en ajoutant par exemple le port 222 (et l'utilisateur toto).

Tunnel SSH ponctuel (pas d'authentification par clé)

Si l'on souhaite mettre en place un tunnel SSH ponctuel, il convient de lancer la commande suivante depuis le Raspberry pi :

ssh -p 2022 -R 22022:127.0.0.1:222 toto@185.212.222.222

Ainsi, le service ssh se connectera au VPS (185.212.222.222) sur le port 2022 (-p 2022) avec l'utilisateur toto. Après avoir entré le mot de passe attaché à cet utilisateur, un tunnel inversé (-R) sera mis en place vers le port 222 (port d'écoute SSH sur le Raspberry) à partir du port 22022 sur le VPS à travers l'adresse localhost (127.0.0.1). Il suffit alors de se connecter au VPS, puis de lancer la commande :

ssh -p 22022 toto@127.0.0.1

pour obtenir l'invite de connexion de l'utilisateur toto sur le pi.

Ce tunnel sera SSH sera précaire, car soumis aux aléas suivants (liste non exhaustive) :

  • déconnexion au bout de quelques minutes en cas d'inactivité de la connexion,
  • coupure en cas de changement d'IPv4 publique,
  • ...

Il est possible de s'assurer de la validité du tunnel depuis le pi avec la commande suivante :

netstat -tupan | grep 222

Une analogie à ce tunnel SSH est la suivante : votre habitation est protégée par un ensemble de portes non déverrouillables et de fenêtres dotées d'un film réfléchissant (pare-feu / CG-NAT), et vous ouvrez volontairement une lucarne vers la maison voisine, dont vous possédez la clé, et à travers seul vous, grâce à un mot de passe (celui du pi) pouvez voir ce qui se passe chez vous.

Tunnel SSH permanent

Le paramétrage est beaucoup plus lourd, car il convient de :

  1. remplacer l'authentification par mot de passe par un échange de clés (clé privée sur le pi, clé publique associée envoyée sur le VPS, voir par exemple cet article) avec phrase de passe,
  2. lancer après chaque redémarrage du pi l'agent ssh afin de mettre en mémoire une fois pour toutes la phrase de passe,
  3. et enfin recourir à la commande autossh en remplacement de ssh pour remettre en place automatiquement le tunnel ssh lorsqu'il tombe, avec la commande suivante :

autossh -fNC -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i ~/.ssh/id_rsa -R 22022:127.0.0.1:222 toto@185.212.222.222 -p 2022

Je n'ai mon pi que depuis quelques jours et ne suis pas un utilisateur aguerri de GNU/Linux, la mise en place de ce tunnel SSH permanent a donc représenté un travail de recherche et de paramétrage conséquent, suite à quoi le service tourne sans interruption depuis plusieurs jours.

J'espère ne pas avoir commis d'erreur en traduisant mes propres ports et adresses vers ceux utilisés dans l'article (!). Je suis à la disposition des personnes intéressées pour tout complément d'information, notamment sur les particularités liées au tunnel permanent.

 

(lire également ce fil sur le forum LaFibre)

4 commentaires

  1. dntoine

    Wahouuuuu !!
    j'ai cherché longtemps un moyen de contourner ce problème avec les connexions 4G, merci !!
    je n'ai pas encore mis en pratique mais en lisant le tuto cela m'a l'air cohérent, je garde précieusement le lien de cette page dans mes favoris car j'en aurai besoin un jour c'est sûr !!
    TOP !!

  2. gblanchet03

    J'ai découvert ces jours-ci (début septembre 2023) votre méthode. Et je l'ai mis en oeuvre pour controler mon réseau interne. J'ai une freebox delta fibre avec ip fixe et un routeur 4G TpLink Archer MR 600 avec une sim freemobile sans ip fixe. J'ai de plus activé un raspberrypi sur lequel la carte eth0 est sur le réseau de la delta 192.168.3.0 et la wlan0 sur le réseau 192.168.1.0 du tplink. Et c'est c'est sur ce raspberry que j'ai établi un tunnel permanent vers mon VPS chez SHPV (très sympas et trés réactifs).
    Je suppose que le tunnel établi lorsque la fibre fonctionne va basculer à travers le tplink si celle-ci tombe.
    Et ainsi avoir accès, depuis l'xtérieur à toutes mes machines. Un arp -a sur le raspberry m'indique celles qui sont up ou non.
    Trés cordialement et merci beaucoup.
    Gérard Blanchet

  3. Aunisien

    Bonjour,
    je découvre ce tuto qui me donne des idées car je suis bloqué avec ma connexion fibre SFR qui fournit l'IP en CGNat, je ne me suis pas penché sur la connectivité Ipv6 que je ne maitrise pas du tout.

  4. Lasdou

    Bonjour et merci pour cette astuce, je viens de l'implémenter pour accéder à un raspberry pi situé derrière une box 4G comme vous. Pour que la connection ssh ne tombe pas j'ai utilisé autossh comme indiqué dans cette documentation. Et petite note importante, afin de garantir que le processus autossh soit corretement relancé en cas de reboot du raspberrypi j'ai ajouté une ligne dans le fichier /etc/rc.local et cela fait très bien le job.
    Merci encore pour cet article fort utile.

Écrire un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec une *

Quelle est le dernier caractère du mot mkjs7l5 ? :