Connexion sécurisée à un environnement data science : tunnel SSH

Travailler sur le cloud

En data science, lorsqu'on travaille sur le cloud, il est fréquent de déployer une interface de développement (tel que Rstudio ou un notebook Jupyter) accessible via un navigateur à l'aide de docker par exemple.

L'IDE est alors accessible à l'adresse IP de la machine sur le port spécifié, à condition d'ouvrir le port de la machine vers l'extérieur. Pour cela, il suffit de créer une règle de firewall permettant d'ouvrir ce port et de filtrer sur les IP sources (les IP pouvant accéder à L'IDE). Malgré ce filtre sur les IP autorisées, un pirate pourrait facilement accéder à cette machine en se faisant passer pour votre adresse IP (avec une attaque du type Man In The Middle par exemple) ou tout simplement en utilisant la même connexion Wi-Fi (cas d'une connexion partagée).

Cette pratique n'est donc pas très sécurisée : lorsque l'on traite des données sensibles, il est important que personne d'autre ne puisse y accéder.

A Affini-Tech, nous utilisons plusieurs méthodes pour sécuriser nos interactions avec des machines sur le cloud. Dans cet article, nous allons nous intéresser au tunnel ssh.

Tunnel SSH

Un tunnel SSH permet de rediriger un port d'une machine vers une autre : on parle de port forwarding.

Local port forwarding

Imaginons que je souhaite me connecter au port 8787 d'une machine virtuelle pour faire du R via Rstudio.

Je lance mon docker sur ma VM à l'aide de la commande suivante :

docker run -d -p 8787:8787 -v /path/to/my/rstudio/work:/home/rstudio/work affinitech/rstudio

Sur la machine distante, Rstudio est accessible sur le port 8787 (utilisation classique de docker) et me permet de développer. Je vais donc utiliser un tunnel SSH pour me connecter sur le port 8787 distant depuis mon poste de travail local avec la commande suivante :

ssh -L 8787:localhost:8787 -N <nom_utilisateur>@<ip_machine>

L'option -L de la commande ssh permet d'effectuer la redirection du port 8787 de la machine virtuelle vers mon port local 8787 : on parle de local port forwarding. A noter que l'on pourrait très bien rediriger sur un autre port de notre machine (en changeant le port à droite). L'option -N permet de n'effectuer aucune action (commande) sur la machine.

Je peux maintenant me connecter à mon environnement Rstudio hébergé sur ma machine virtuelle à l'adresse http://localhost:8787

SOCKS proxy (Dynamic Port Forwarding)

Je sais maintenant me connecter de manière sécurisée à un port de ma machine virtuelle. Mais aujourd'hui, je dois travailler sur un cluster Hadoop et accéder aux différents ports du master pour développer sur un IDE, accéder à l'interface d'Ambari, surveiller l'exécution de mes jobs avec YARN, ...

Je pourrais rediriger chacun des ports un à un avec la commande précédente. Cependant, ceci est fastidieux et si j'ai besoin d'accéder à un nouveau port il faudra que je lance une nouvelle commande.

Une bonne solution est de mettre en place un tunnel SSH sur une machine et d'y créer un proxy SOCKS. Il faudra ensuite configurer le navigateur pour se connecter au proxy et il sera alors possible d'accéder à tous les ports de la machine distante de manière sécurisée.

Pour cela la commande ssh est la suivante :

ssh -D 1080 -N <nom_utilisateur>@<ip_machine>

L'option -D permet la redirection dynamique du port 1080 local (port conventionnel pour un SOCKS proxy).
Remarque : l'option -C pourrait être ajoutée pour compresser la donnée et ainsi gagner en bande passante.

Ensuite, la configuration du navigateur peut se faire via l'interface ou en ligne de commande. Avec chrome, voici la commande à lancer sur un système OS X :

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome  --proxy-server="socks5://localhost:1080" \
  --user-data-dir=/tmp/

Pour une machine linux ou windows il suffit juste de changer chemin vers l'application Chrome sur votre machine.

Avec GCP

Sur une machine virtuelle google, pour ne pas s'embêter avec les clés SSH, on peut directement utiliser le cloud SDK en rajoutant les flags ssh nécessaires.

  • Dans la première configuration :
    gcloud compute ssh  --zone=<zone> --ssh-flag="-L 8787:localhost:8787" --ssh-flag="-N" --project <nom-projet> <nom-machine>
    
  • Dans la deuxième configuration :
    gcloud compute ssh  --zone=<zone> --ssh-flag="-D 1080" --ssh-flag="-N" --project <nom-projet> <nom-machine>