Sommaire
Cher journal,
j'aimerais te présenter un petit projet pour monter très facilement ton propre tunnel SSH à la maison, comme un grand: https://github.com/second-reality/reverse-tunnel
Pour résumer, cela permet de faire transiter un trafic donné via ssh. Cela offre différentes possibilités:
- utiliser un protocole non sécurisé (comme ftp) sur un réseau ouvert, en passant via une machine relai, sans risque d'interception.
- accéder à une machine non disponible publiquement sur le net, via une machine relai (publique).
- crée un ersatz de VPN pour accéder à des données bloquées dans ton pays (si tu disposes d'un serveur à l'étranger).
- et bien d'autres choses…
Le cas qui m'intéresse, c'est le deuxième. À savoir, accéder à la machine du boulot depuis chez moi, facilement.
Voici un résumé bien plus complet: https://wiki.korben.info/Tunnel_SSH
Exemples
Accès à une machine derrière un relai
Imaginons que je possède une machine_publique
accessible sur le net à l'adresse 80.80.80.80
moule@machine_publique> ./server.sh 6666 myserver:22
-----------------------------------------------------
Running ssh server as moule
Listening on port 6666
Authorized destinations: myserver:22
Authorized keys file: /home/user/.ssh/authorized_keys
-----------------------------------------------------
Server listening on 0.0.0.0 port 6666.
Depuis n'importe où sur le net, on ouvre le tunnel:
user@some_machine> ./access.sh moule 80.80.80.80 6666 10000 myserver 22
Et, depuis un autre terminal:
user@some_machine> ssh -p 10000 localhost
Welcome to the world of Moules!
user@myserver>
Il faut bien sûr que la clé publique de user
soit dans les authorized_keys
de moule
sur machine_publique
et sur myserver
.
Reverse tunneling for fun!
On imagine maintenant qu'on désire accéder à une machine work
depuis home
(ip 95.95.95.95). Le port 6666 de home
est ouvert sur le net.
moule@home> ./server.sh 6666 localhost:*
Depuis le boulot:
serious@work> ./give_access.sh moule 95.95.95.95 6666 10000 localhost 22
Un peu plus tard, en rentrant:
moule@home> ./access.sh moule localhost 6666 15000 localhost 10000
moule@home> ssh serious@localhost -p 15000
serious@work>
On peut donc remonter le tunnel créé depuis work
. C'est ce qu'on appelle du reverse tunneling. Et c'est précisément ce qui m'intéressait au départ!
Autres possibilités
On peut bien sûr accéder à autre chose qu'un serveur ssh (redirection http, imap, …)
La sécurité par l'exemple
Pour illustrer à quoi sert la restriction de destinations, voici un exemple (entièrement en local) ouvrant un tunnel vers le port 22 de github.com.
user@pc> ./server.sh 6666 localhost:*
user@pc> ./access.sh user localhost 6667 10000 github.com 22
On voit apparaître sur le terminal du serveur:
Postponed publickey for user from 172.17.0.1 port 37252 ssh2 [preauth]
Accepted publickey for user from 172.17.0.1 port 37252 ssh2: RSA
user@pc> ssh git@localhost -p 10000
ssh_exchange_identification: read: Connection reset by peer
Sur le terminal du serveur:
Received request to connect to host github.com port 22, but the request was denied.
Sur le terminal ouvrant l'accès:
channel 1: open failed: administratively prohibited: open failed
On refait cette fois l'expérience en autorisant la destination github.com:22
user@pc> ./server.sh 6666 localhost:* github.com:22
user@pc> ssh git@localhost -p 10000
Hi second-reality! You've successfully authenticated, but GitHub does not provide shell access.
Cette fois, cela fonctionne bien!
Ainsi, on possède un contrôle très fin sur ce qui peut-être ouvert depuis une machine extérieure.
Description
La petite originalité de ce projet, c'est l'utilisation de Docker pour conteneuriser le serveur SSH.
Je voulais une solution qui:
- soit techniquement sûre
- soit simple et sans installation
- ne dépende pas d'une distribution particulière
- même en cas d'intrusion par un attaquant, que celui-ci ne puisse pas accéder à mes données, clés, ou celles d'une machine ayant ouvert un tunnel.
- ne demande pas de bidouiller mon sshd_config
- n'expose pas le serveur ssh de ma machine sur internet.
- que mon serveur ssh ne soit pas nécessairement executé par root
- permette de contrôler finement les destinations des tunnels
Aussi étonnant que celui puisse paraître, en dehors de quelques projets similaires sur Github (pour lesquels j'ai une confiance assez réduite), je n'ai pas vraiment trouvé d'outil dédié.
Quelques heures plus tard, le résultat est:
- un seul port est exposé sur Internet (redirection sur ma freebox), celui publié par le conteneur.
- les destinations des tunnels sont explicitement nommées
- J'ouvre mon serveur au besoin (et mon client essaye continuellement de s'y connecter).
- j'ai appris quelques trucs sur Docker et OpenSSH au passage.
Fichiers intéressants:
- le Dockerfile, contenant la config du serveur SSH: https://github.com/second-reality/reverse-tunnel/blob/master/Dockerfile
# run sshd on port $SSH_PORT, only allowing $AUTHORIZED_USER to connect
# and only authorizing forwarding to $AUTHORIZED_DESTINATIONS
# User running this is the one running the container
ENTRYPOINT /usr/sbin/sshd -p "$SSH_PORT" -D\
# show log of connections on stderr
-e\
# keep clients alive
-o ClientAliveInterval=180 -o ClientAliveCountMax=2\
# restrict local tunneling to only some destinations
# This is the heart of security!
-o PermitOpen="$AUTHORIZED_DESTINATIONS"\
# allow anyone to access forwarded ports and not only localhost
-o GatewayPorts=yes\
# only allow a specific user to connect (the one running container)
-o AllowUsers="$AUTHORIZED_USER"\
# prevent execution of any command
-o ForceCommand="/No/Shell/Available/ONLY_TUNNELING_IS_POSSIBLE"\
# other params (man sshd_config)
-o UsePAM=no\
-o PasswordAuthentication=no\
-o AllowStreamLocalForwarding=no\
-o AllowAgentForwarding=no\
-o AllowTcpForwarding=yes\
-o AuthenticationMethods=publickey\
-o MaxAuthTries=1\
-o PermitRootLogin=no\
-o PermitTunnel=yes\
-o PrintMotd=no\
-o PidFile=none\
- le server.sh, contenant la commande de lancement du conteneur: https://github.com/second-reality/reverse-tunnel/blob/master/server.sh
docker run --rm=true -p $ssh_port:$ssh_port $terminal\
-v $authorized_keys:$authorized_keys:ro\
-v /etc/passwd:/etc/passwd:ro \
-v /etc/group:/etc/group:ro \
-e SSH_PORT=$ssh_port\
-e AUTHORIZED_DESTINATIONS="$authorized_destinations"\
-e AUTHORIZED_USER="$USER"\
-u $(id -u)\
reverse-tunnel || die "running server failed"
Pièges
Il existe plusieurs pièges possibles dans un projet comme celui-ci:
- oublier de bloquer la possibilité d'exécuter une commande sur le serveur SSH. Cela peut augmenter la surface d'attaque en cas d'intrusion.
- oublier de bloquer les destinations: Si on ne limite pas les destinations, on peut accéder à un port de la machine hôte (et à tout son LAN globalement), hors du conteneur! (oups!)
- Des petites blagues (classiques avec Docker) sur les droits des fichiers accédés dans le conteneur.
Conclusion
N'hésitez pas à jouer en local, ça fonctionne de la même façon! Il est notamment intéressant de jouer sur les destinations autorisées.
Note: Ouvrir un tunnel SSH vers une machine personnelle depuis votre lieu de travail peut-être considéré comme une faute professionnelle. Il s'agit d'une brèche de sécurité importante dans l'infrastructure de votre entreprise.
Si vous avez des retours, des critiques, ou des suggestions, je suis preneur! Si vous avez besoin d'un coup de main pour l'utilisation, je peux aussi aider.
Happy tunneling!
# On est en 2020
Posté par Enzo Bricolo 🛠⚙🛠 . Évalué à 5.
Faut arrêter d’utiliser FTP. Il y a déjà SFTP et FTPS, on n’a pas vraiment besoin de FTP dans un tunnel SSH.
[^] # Re: On est en 2020
Posté par ptit_poulet . Évalué à 4.
Oui et non.
Moi je vois l'avantage de faire passer tout et n'importe quoi dans le tunnel de façon transparente. Et de l'extérieur on verra juste une connexion ssh et rien d'autre. Pas besoin non plus d'avoir 36 services en écoute sur l'extérieur juste le service ssh, le reste sera simplement en écoute sur localhost par exemple.
[^] # Re: On est en 2020
Posté par Pierrick Bouvier . Évalué à 2.
Je suis en accord avec toi, j'ai simplement pris ftp comme exemple d'un protocole "classique" non sécurisé.
# diminuer la surface d'attaque
Posté par palm123 (site web personnel) . Évalué à 3.
utiliser une Debian light comme Minideb ou Debian-stretch, ou une Alpine Linux, par exemple
ウィズコロナ
[^] # Re: diminuer la surface d'attaque
Posté par Pierrick Bouvier . Évalué à 1.
J'imagine que tu faisais référence à Debian-slim en parlant de Debian-stretch, que j'ai en effet mis en place à la place de buster (buster -> buster-slim). Merci!
Quant à Alpine, malgré tout le hype autour de cette distribution dans le monde docker, je reste assez sceptique du résultat, notamment d'un point de vue sécurité. Je préfère encore une distribution fiable, basée sur des composants éprouvés, plutôt qu'une surcouche à busybox.
[^] # Re: diminuer la surface d'attaque
Posté par Psychofox (Mastodon) . Évalué à 4.
En quoi busybox n'est pas fiable et éprouvé ?
[^] # Re: diminuer la surface d'attaque
Posté par Pierrick Bouvier . Évalué à 2.
Mon commentaire était en effet un peu gratuit.
En réalité, lorsque j'ai entendu parler de Alpine Linux (pour Docker) cette année, j'ai aussi vu un certain mouvement de devs qui la quittent afin de revenir vers des distributions plus "mainstream", notamment depuis l'arrivée des images réduits ubuntu et debian.
Dans les problèmes reportés:
- soucis liés à la sécurité: https://www.alpinelinux.org/posts/Docker-image-vulnerability-CVE-2019-5021.html
- problème de performance: https://superuser.com/questions/1219609/why-is-the-alpine-docker-image-over-50-slower-than-the-ubuntu-image
- problème dès qu'on a besoin d'un paquet non disponible sous Alpine (et il y en a bien peu que sous debian)
Bien sûr, ces liens sont vieux, et peut-être le projet est-il plus mature. Bien sûr, on peut trouver le même genre d'articles sur Debian.
Mais clairement, adopter Alpine pour le simple besoin d'une plus petit image, en dépit du reste, me convainc assez peu.
Je ne visais pas Busybox, mais plutôt, un "bricolage" autour de Busybox.
[^] # Re: diminuer la surface d'attaque
Posté par Anonyme . Évalué à 3.
Ou même tout compiler en statique et utiliser les images Distroless.
[^] # Re: diminuer la surface d'attaque
Posté par Pierrick Bouvier . Évalué à 1.
Après plusieurs recherches, j'ai finalement opté pour l'approche distroless, développée chez Google.
L'idée est de faire un dockerfile multi stage, pour ne garder que le serveur ssh et ses dépendances.
De cette façon, le conteneur final ne possède ni shell, ni binaire superflu. La surface d'attaque est donc très réduite, voire nulle. À mes yeux, ce modèle est plus viable que simplement réduire la taille de sa distribution.
https://github.com/GoogleContainerTools/distroless
Une vidéo présentant l'idée: https://www.youtube.com/watch?v=lviLZFciDv4
Et le résulat:
https://github.com/second-reality/reverse-tunnel/commit/3680dc34d69727bad88b3be154a9b3d7862ee8c6
# Stunnel dynamique
Posté par Alex G. . Évalué à 2.
En lisant j'ai mieux compris la différence avec stunnel.
Stunnel va faire le tunnel vers une série de connexions paramétrées en avance.
Alors qu'avec ton projet, c'est le client qui décide du tunnel qu'il veut créer, le serveur ne fait que vérifier que c'est autorisé.
Très intéressant. C'est deux cas d'utilisation distinct.
[^] # Re: Stunnel dynamique
Posté par Pierrick Bouvier . Évalué à 2.
À ma connaissance, stunnel ne fait qu'ajouter une couche SSL à une connexion existante (pour un client, ou un serveur), et rien d'autre.
Typiquement, tu as un serveur qui ne parle que http. Tu peux utiliser stunnel pour avoir SSL "gratuitement" par dessus.
Pour vulgariser:
cat mon_fichier | stunnel | OVER_INTERNET | stunnel | cat, donne mon fichier, mais transmis de façon chiffré.
Un tunnel SSH permet davantage. Il offre bien sûr le chiffrement de la connexion, mais de plus, il offre un tunnel qu'on peut établir dans les deux sens, ainsi que la notion de port forwarding (rediriger un port distant sur un autre local et inversement).
Du coup, je dirai plutôt que stunnel est fait pour "décharger" le calcul de SSL sur un point d'entrée donné, et avoir un serveur qui parle en "clair" derrière. En tout cas, je l'avais connu dans ce contexte (car c'est souvent compliqué et error-prone de gérer SSL dans ton appli).
[^] # Re: Stunnel dynamique
Posté par Alex G. . Évalué à 2.
Oui ce que tu dis est exact. Mais le cas d'utilisation c'est aussi effectivement de sécuriser des connections de logiciels (éventuellement) tiers, alors que ceux-ci l'ignorent complètement.
Je l'utilise en production car il est très résilient et facile à déployer.
# Ais je compris ?
Posté par Christophe B. (site web personnel) . Évalué à 2. Dernière modification le 08 janvier 2020 à 11:37.
Bonjour,
Petites questions :
Tu n'as pas la possibilité de passer par un VPN professionnel ou mieux pas d'accès SSH à ton boulot
C'est peut être pas toi qui gère les accès externes
Ou tu ne veux pas de trace de tes connexions ;) ce qui peut être intéressant …
Sans rire c'est SSH le problème ou la machine personnelle ?
ftp + ssh C'est possible depuis quand ? (non pas sftp …)
parfois je me dis qu'il faudrait quand même que je me tienne au courant de certaines évolutions …
Sinon
je trouve l'idée intéressante, ne serait que pour reculer les limites d'utilisation d'un outils comme SSH, à étudier …
[^] # Re: Ais je compris ?
Posté par Pierrick Bouvier . Évalué à 0. Dernière modification le 08 janvier 2020 à 14:54.
Je n'ai pas d'accès SSH ni de VPN au boulot. N'étant pas IT, c'est difficile pour moi de pousser une telle décision.
Mon but, c'est juste de pouvoir lancer une commande que j'aurais oublié facilement depuis la maison, et avoir le résultat le lendemain.
Le problème, c'est la machine personnelle. Elle ne correspond pas à la politique IT de ta boîte, et ça peut faire criser certains d'ouvrir une connexion à l'intérieur du réseau "sécurisé" de ta boîte depuis ta machine. Si un jour j'ai un souci (ça demanderait du deep packet inspection au minimum), je pourrais clairement défendre ma solution. Et puis au fond, c'était juste fun comme idée ;)
Le protocole n'est pas ssh + ftp. C'est ftp, redirigé à travers une connexion ssh. Derrière, ton serveur à la maison transfère en clair avec le FTP final. Mais tu peux avoir un peu plus de confiance en ton FAI que dans le wifi du café du coin.
Ce que tu dis le fait ne pas laisser de traces est pertinent aussi. Un tunnel SSH est très couramment utilisé pour laisser une backdoor sur une machine sur laquelle un attaquant s'est introduit.
[^] # Re: Ais je compris ?
Posté par Christophe B. (site web personnel) . Évalué à 2.
Si j'ai bien compris :
tu laisse un tunnel de ton boulot vers ta machine relais
puis tu passes par ta machine relais pour te connecter
Dans ce cas rajoute un couche Tor pour te connecter a ta machine relais depuis chez toi (avec Tails en VM par exemple)
comme cela si c'est détecté ils penseront qu'ils s'agit d'une attaque de méchant pirate …
Ceci dit dans une entreprise "normale" il n'y en pas 36 capable de bricoler ce genre de choses un "petit peu technique" … donc tu es facilement repérable … (connexion a linuxfr.org, magazine linux mag ou Misc dans ton sac ou sur ton bureau, T-shirt anonymous … )
C'est toujours l'humain qui est faillible
[^] # Re: Ais je compris ?
Posté par Pierrick Bouvier . Évalué à 1.
Plus exactement, ma machine du boulot essaye (constamment, 1 fois/30sec) d'ouvrir un tunnel vers une ip que je contrôle.
Lorsque je veux y accéder, j'ouvre le serveur sur ma machine perso, le tunnel est alors créé. Je ne laisse pas ma machine perso allumée constamment, et encore moins le serveur ouvert.
Je peux alors me connecter à la machine du boulot.
Je ne cherche pas spécialement à me cacher (sinon écrire un article en mon nom sur linuxfr serait quelque peu stupide), mais si un jour on vient me voir, j'aurais de quoi échanger techniquement.
[^] # Re: Ais je compris ?
Posté par groumly . Évalué à 5.
ils vont t’adorer les gars qui vont faire le prochain audit sécurité de la boîte!
Linuxfr, le portail francais du logiciel libre et du neo nazisme.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.