Reverse port ssh forwarding

Ou comment accéder à un service local depuis l'extérieur

Ayant récemment eu la fibre à 300mbps symétrique chez moi, j'ai décider de supprimer mon serveur dédié que j'avais depuis quelques années pour tout héberger chez moi.

Le problème étant que chez orange, je n'ai pas d'IP fixe. J'aurais bien évidemment pu utiliser un DNS dynamique, ou même créer un script pour utiliser mon nom de domaine chez mon registar, mais je ne me voyais pas exposer mon IP publique directement sur internet.

J'ai donc chercher une autre solution, ma première idée a été de créer un serveur VPN sur un petit VPS chez scaleway, mais les performances n'était pas au rendez-vous. Autant la vitesse de téléchargement du VPS vers mon serveur était correcte, mais dans l'autre sens c'était catastrophique, je dépassais pas les 50ko/s avec une perte de paquet assez importante.
Malgré de nombreux essais, je n'ai pas réussi à améliorer ces performances.

Après beaucoup de recherche, j'ai donc trouvé un moyen via le ssh forwarding, mais de manière inverse. De base nous utilisons ce système pour pouvoir monter un port externe en local, pour accéder à un service à distance, ou même outrepasser certaines restriction, comme Plex, qui demande un compte premium pour un accès à distance.
Mais avec le reverse forwarding, nous montons un port local, vers un port externe.

Bon allez, on commence

Préparation du VPS

Nous avons un petit paramètre à ajouter sur le service ssh de notre VPS :

GatewayPorts clientspecified

Ce paramètre permet justement l'utilisation du reverse port forwarding. Par défaut il est à no.
Nous avons deux autres possibilités, yes ou clientspecified, le premier permets seulement de monté le port sur toute les interfaces, tandis que le deuxième permet de choisir sur quoi écouter, comme localhost par exemple.

Puis on relance le service :

systemctl restart sshd

Et c'est tout

Sur mon serveur

J'ai par exemple mon jenkins qui tourne sur le port 9010, pour pouvoir le monté sur mon VPS, c'est relativement simple :

ssh -fN -R 9010:localhost:9010 xataz@X.X.X.X
  • -fN permets de laisser ssh en arrière plan.
  • -R permets le montage du port (à l'inverse de -L).
  • RemoteIP:RemotePort:LocalIP:LocalPort ou Destination:Source

Et voilà, le port est monté sur le VPS.
Si par exemple je veux le monter seulement en localhost :

ssh -fN -R localhost:9010:localhost:9010 xataz@X.X.X.X

Pour faciliter la gestion, j'ai créer un petit service systemd nommé sshf (Oui j'ai été très inspiré) :

[Unit]
Description=SSH forwarding for tunnel for %i
Wants=network-online.target

[Service]
User=xataz
Type=forking
ExecStart=/usr/bin/ssh -i /home/xataz/.ssh/id_rsa -fN -R localhost:%i:localhost:%i xataz@X.X.X.X
Restart=always

[Install]
WantedBy=multi-user.target

Et comme ça il me suffit de lancer le service, et de l'activer :

systemctl start sshf@9010
systemctl enable sshf@9010

Conclusion

Grace à mon reverse proxy que j'ai mis sur le VPS, je peux maintenant accéder à mes services qui sont directement chez moi, et ceux sans exposer mon IP.