VNC inversé et traversée de pare feu
Par Mathieu le samedi 10 juillet 2010, 11:33 - Informatique - Lien permanent
Ce billet décrit en détail comment mettre en place un dispositif de contrôle à distance via le logiciel VNC, fonctionnant en mode inversé (le client est serveur et le serveur est client) en traversant les deux pare feu à la fois autour du client et du serveur, en se servant d'une machine relais.
Définitions
Dans la suite de l'article je vais utiliser le terme « client » pour désigner la machine qui va réaliser le contrôle, et « serveur » pour la machine à administrer. Comme nous fonctionnerons en VNC inversé, ça sera le serveur qui demandera la connexion au client qui écoutera les demandes de connexion.
Prérequis
- La machine « cliente », celle qui contrôlera la première, doit être sous Linux, ou un autre système intelligent. Il est aussi possible je pense d'avoir un truc comme cygwin, ou alors un moyen efficace de créer des tubes SSH.
- La machine relais doit avoir un accès SSH, avec la bonne configuration de ce dernier pour qu'il autorise les tunnels à ressortir, mais nous y reviendrons.
Problématique
Comment mettre en place un contrôle à distance sachant que :
- Les deux machines sont derrière un NAT qui nous empêche d'entrer.
- Que nous n'avons pas accès aux NAT pour forwarder des ports.
- La prise de contrôle doit être décidée par le client, sans avoir besoin que le serveur intervienne, ou que l'utilisateur lance le serveur.
Nous avons ici un triple problème : le NAT du serveur nous empêche de rentrer, on ne peut pas ouvrir de ports, et le NAT du client nous empêche aussi de rentrer, nous empêchant de créer la connexion « inversée » (où c'est le client qui écoute et le serveur qui connecter).
Heureusement nous avons sous la main un serveur tiers pour faire relais, et la machine cliente implémente la norme POSIX (comprendre : l'OS est un unix et il est intelligent).
Solution
Voici comment on va procéder :
- Mettre en place un VNC inversé sur le client, mais qui écoute ... en local.
- Créer un tube SSH du port d'écoute local vers le serveur relais.
- Expliquer au serveur relais de faire sortir le tube.
- Faire se connecter la machine à administrer sur le port ouvert du relais, forwardé par nos soins.
Installation du client et du serveur
- Le serveur : la machine serveur étant sous windows, on va utiliser UltraVNC, disponible ici : http://www.uvnc.com/download/index.html
- Le client : la machine cliente est sous Linux, on va utiliser vnc4viewer, qui est dans les paquets de la plupart des distributions
Vérification de la configuration du relais
Alors là je suis désolé pour ceux qui n'ont pas d'accès root sur le relais, il leur sera impossible de vérifier à moins de créer le tube SSH et de vérifier qu'il ressort (en lui parlant dedans avec netcat par exemples).
Le serveur SSH doit en effet posséder le GatewayPorts activé, pour que les sockets SSH puissent être bindés vers l'extérieur et non pas accessibles seulement en local. Il doit bien y avoir un moyen de crée un second tube pour faire sortir la socket locale pour contourner ce problème, mais ici j'ai fait au plus simple : j'ai rajouté GatewayPorts yes dans la configuration, et relancé le serveur SSH.
Vérifiez donc la présence de la ligne suivante dans votre /etc/ssh/sshd_config
:GatewayPorts yes
Lancement du client et essai du tube
Si tout s'est bien déroulé, vous avez installé vnc4viewer sur le client linux, et vous êtes prêt à le lancer.
Donc, lancez le avec la commande vncviewer -listen
Lançons maintenant le tube, la commande est ésotérique mais je vais essayer de l'expliquer : ssh -f -R*:5500:localhost:550 monlogin@serveurrelais.com sleep 3600
- Le -f indique que nous voulons créer un tube SSH
- -R indique le sens du tube, même si les sockets sont bidirectionnelles, il faut indiquer où est l'entrée (qui écoute) et où est la sortie (qui envoie des données en réponse)
- Le * signifie qu’on écoute tous les hôtes en sortie, et pas seulement localhost, c’est nécessaire dans notre cas pour que le serveur windows puisse s'y connecter (mais il agit alors comme un client, puisque on est en inversé, c'est pour ça qu'il va se connecter sur l'entrée, vous suivez ?)
- localhost indique l'endroit où brancher l'entrée, ici localhost c'est le serveur relais, on s'y connecte et au lieu de rediriger le tube vers un éventuel autre serveur, on crée le tube local 4le trait vert du dessin5 pour router sur la bonne sortie sur la même machine
- ensuite 5500 c'est le port de sortie, de l'autre côté, c'est la machine linux avec le client qui écoute (puisque on est en inversé)
- La suite indique à quel serveur on va se connecter et avec quel login
- Enfin, le sleep 3600 est la commande à faire exécuter par le serveur pour maintenir le tube ouvert ; en effet, le client SSH permet de créer un tube à usage unique, juste pour une commande, comme on veut y faire passer plein de trucs dedans, on va lancer cette commande qui ne fait rien mais qui permet au tube de rester ouvert. La valeur 3600 correspond à 1h.
ssh -f -Rportdistant:hoteacontacter:portlocal moi@machinedistante commandealancer
dans un sensssh -f -Fportlocal:hoteacontacter:portdistant moi@machinedistante commandealancer
dans l' autre sens
Lancez la commande précédemment décrite, et essayez le tube. Pour essayer le tube, faites simplement :
netcat serveurrelais.com 5500
Si tout fonctionne, vous devriez voir le client en écoute vous dire qu'il a reçu de la visite :Sat Jul 3 18:17:12 2010
CConn: Accepted connection from 0.0.0.0::45907
Lancement automatique du serveur vers le client en écoute
J'ai choisit de créer une « Tâche planifée » Windows pour que le serveur sous windows tente de contacter le client à travers le tube.
La commande à lancer est toute simple : "c:\Program Files\UltraVNC\winvnc.exe" -connect ipserveurrelais::5500
Conclusion
Nous avons mit en place un système particulier : le serveur est client, le client est serveur, le serveur contacte le client à intervalles réguliers, et c'est le client qui décide quand le serveur va être contacté. Ce branchement peut servir à mettre en place une backdoor sur l'ordinateur serveur, cependant le changement de résolution et de fond d'écran lors de l'établissement de la connexion avec le client devrait faire tiquer celui qui utilise le serveur à ce moment là.
Notes, références, etc
- http://www.harobed.org/index.php?2007/10/14/185-vnc-inverse-prise-de-controle-a-distance
- http://www.uvnc.com/index.html
- http://doc.ubuntu-fr.org/vnc
- http://doc.ubuntu-fr.org/ssh_vnc
Commentaires
Je me demande pourquoi tu parles de pare-feu au début, mais mis à part ça c'est une utilisation peu classique mais efficace des tunnels SSH. C'est un peu dommage d'avoir à changer la config du serveur SSH pour exterioriser le port du tunnel. Ça n'aurai pas été nécessaire si la station Windows avait été capable de faire un tunnel SSH avec la station intermédiaire.
Mis à part ça, je me demande s'il n'y a pas un moyen de faire des redirections NAT dynamiques : tu fais une requête au serveur NAT pour qu'il redirige pour une connexion un port donné vers toi. Parce que sans ça les connexions DCC d'IRC, les envois de fichiers MSN et tout le reste ne devraient pas être faisable. Je vais m'informer là dessus, je te tiens au courant.
Bien que ça ait le mérite de faire un article à part entière, je vais essayer de faire bref.
Il se trouve que la traversée de NAT est un problème assez fréquent pour que beaucoup de monde se soit penché dessus. Seul problème, les normes sur le NAT étant bien trop pauvres, aucune de ces technique ne fonctionne sur tous les cas. Il faut donc varier et ruser.
En voici une liste pas vraiment exhaustive :
À la vue du nombre faramineux de technique plus ou moins respectueuse des normes, c'est à se demander ce que fait l'IETF. Il est très probable que la technique NAT PMP soit celle qui sera appliquée dans un futur proche.
Rappelons aussi que l'IPv6 permet de se passer des NAT. On se demande quand les FAI s'y mettrons.