Créer son propre ngrok avec docker

Introduction

Il y a quelques temps, j’ai lu un article expliquant comment créer et héberger son propre ngrok. À l’époque je ne savais même pas en quoi consistait ngrok.

Il s’avère que ngrok est un service permettant de rendre des site webs hébergés localement, accessible publiquement sur internet. C’est par exemple très pratique pour pouvoir tester un site encore en développement depuis un smartphone sans avoir besoin de déployer l’application, ou simplement pour pouvoir montrer son travail rapidement à quelqu’un n’étant pas sur le même réseau.

Le hic, c’est qu’il ma fallu 1 ou 2 heures pour réussir à appliquer le contenu de l’article. Certaines infromations spécifiques à mon ordinateur étaient manquantes, notamment la configuration SSH. Lorsque c’est faisable j’essaie toujours de modifier le moins possible les fichiers de configuration, surtout quand il s’agit de choses très spécifiques qui n’ont pas vraiment de sens en dehors d’un certain périmètre. Comme je ne versionne pas ces fichiers, je sais que je vais oublier tout cela très rapidement..

Après avoir finalement réussi, j’ai décidé de dockerisé cette solution de manière à la rendre portable et facile à installer pour les prochaines fois.

Voici la solution en image :

Schéma architecture docker

La partie gauche de l’image concerne “ngrok”. La partie droite est l’application que vous souhaitez rendre disponible sur internet.

Après l’écriture de cet article je me suis rendu compte que d’autres internautes ont également été inspiré par le premier billet. Voici un lien vers un article similaire.

Tous les fichiers utilisés dans ce tuto sont disponibles depuis ce repository github.

Prérequis

  • un serveur ouvert sur internet
  • docker et docker-compose installés à la fois en local ainsi que sur votre serveur

Configuration côté serveur

  • Sur le serveur créons le fichier docker-compose.yml avec le contenu suivant.
version: '3.7'

services:

  nginx:
    image: nginx:1.15.8
    ports:
      - 3333:3333
      - 8082:80
    volumes:
      - ./nginx_app.conf:/etc/nginx/conf.d/default.conf

  ssh_reverse_tunneling:
    build:
      context: .
      dockerfile: Dockerfile_sshd
    ports:
      - "2222:22"

J’ai ici décidé d’exposer les ports 8082 et 2222 car je suppose que les ports 80 et 22 sont déjà utilisés sur votre serveur par un serveur web et ssh.

Si vous êtes pointilleux et observateur vous devez vous demander : pourquoi il y a t’il des guillemets autour du port 2222 mais pas dans le cas des ports 8082 et 3333 ? Si - en plus d’être pointilleux et observateur - vous êtes aussi curieux, alors la réponse à cette question se trouve sur github avec cette issue : https://github.com/docker/compose/issues/3109

  • Comme indiqué dans le fichier docker-compose.yml, il faut aussi créer le fichier Dockerfile_sshd.

Vous pouvez suivre la documentation officiellede docker pour avoir plus d’informations à ce propos. N’oubliez pas de changer le mot de passe.

FROM ubuntu:16.04

RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:youyoupassword' | chpasswd
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN echo 'AllowTcpForwarding yes' >> /etc/ssh/sshd_config
RUN echo 'GatewayPorts yes' >> /etc/ssh/sshd_config

# SSH login fix. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd

ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

Les seuls choses que j’ai modifié du contenu de la documentation docker sont les valeurs de gatewayports et allowtcpforwarding à yes. Plus d’infos sur cette page

  • Enfin, juste comme Jacob Errington l’indique dans son blog, créez le fichier nginx_app.conf
server {
    access_log /var/log/nginx/$host;

    location / {
	    proxy_pass http://ssh_reverse_tunneling:3333/;
	    proxy_set_header X-Real-IP $remote_addr;
	    proxy_set_header Host $host;
	    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
	    proxy_redirect off;
    }

    error_page 502 /50x.html;
    location = /50x.html {
	    root /usr/share/nginx/html;
    }
}

Toujours sur votre serveur, exécutez docker-compose up -d et faites une requête HTTP à votre serveur sur le port 8082. Par exemple http://your.server.net:8082/

Voici la page qui devrait s’afficher:

Erreur nginx

Configuration côté client (votre laptop)

Si ce n’est pas dejà le cas, il vous faut simplement une application fonctionnant localement sur n’importe quel port.

Voici un moyen de lancer une page web en quelques secondes sur le port 8888 :

docker run --rm -p 8888:80 rothgar/microbot:v1

On créer un tunnel entre notre application en local et notre service “ngrok” sur le serveur en lancant la commande suivante :

ssh -N -R 0.0.0.0:3333:localhost:8888 root@your.server.net -p 2222

Je vous encourage fortement à lire l’article de Jacob Errington qui explique cette partie mieux que je ne pourrais le faire.

Tapez votre mot de passe (youyoupassword si vous ne l’avez pas changé…) puis ouvrez la page http://your.server.net:8082/ une nouvelle fois. Cela devrait fonctionner!

Microbot website

Si cet article vous a rendu service, n’hésitez pas à starrer ce repo en guise de remerciement ! ⭐