SSH & IPv6 : « bind: Cannot assign requested address »

Un dernier billet sur SSH, sinon nous (vous et moi) allons être en overdose 😛 .

Si vous avez désactivé IPv6 sur votre machine GNU/Linux dans l'attente que votre FAI vous ouvre les portes du vrai internet IPv6 (sans tunnel 6to4 j'entends) et que vous tentez une redirection locale/distante/dynamique avec SSH, vous obtiendrez le message suivant : "bind: Cannot assign requested address".

Pour résoudre ce petit soucis, il faut dire à votre client SSH de ne travailler que sur le protocole ipv4. Pour cela, il existe au moins deux méthodes, si on en croit le man SSH :

  • Utiliser l'option "-4" lors de votre connexion au serveur :
    ssh -4 -NL8080:127.0.0.1:3128 login@host

    Néanmoins, cette solution est peu pratique étant donné qu'il faut utiliser l'option lors de chaque connexion.

  • Ajouter une ligne "AddressFamily inet" dans le fichier ssh_config.

SSH : du port forwarding au VPN bon marché

Table des matières

Quand je suis sur un réseau insecure (wifi, dont la charte précise que des contrôle techniques de bon usage du réseau peuvent être effectués sans préavis, etc. ), je sécurise mes connexions grâce à SSH et à ses fonctionnalités de port forwarding / tunnels. Dans cet article, je souhaite vous faire un retour sur mes découvertes plus ou moins récentes.

Voici une page web qui explique clairement le principe du port forwarding avec SSH et la différence entre une redirection locale (ssh -L) et une redirection distante (ssh -R) : Tynsoe projects.

La redirection locale

Au commencement, j'utilisais une redirection locale afin de rediriger ma navigation internet sur un proxy Squid se trouvant sur un serveur "at home". Donc une bête ligne de commande comme celle-ci suffisait :

ssh -NL8080:localhost:3128 login@host

Ensuite, je configurais mon navigateur pour utiliser le proxy HTTP/HTTPS suivant :

  • Hôte : 127.0.0.1
  • Port : 6666

Et dans les rares cas ou j'avais besoin d'un autre service, je transférais un autre port en même temps :

ssh -NL8080:localhost:3128 -L2200:serveurSSH:22 login@host

Je pouvais alors surfer tranquillement et me connecter à la machine serveurSSH via l'adresse 127.0.0.1:2200

La redirection dynamique

Ensuite, j'ai voulu utiliser plus de services (mail, messagerie instantané, etc.) et j'ai donc trouvé les limites de la redirection locale de ports (transférer tous ces ports à la mano c'est pas top). De plus, mon serveur proxy était en panne. Mais j'ai découvert la redirection dynamique (ssh -D). Du coup, c'est mon fidèle WRT54GL qui me sert de proxy.

Maintenant, une simple ligne de commande suffit pour avoir accès à tous mes services :

ssh -ND 6666 login@host

Ensuite, il faut définir un proxy SOCKS dans les paramètres de chaque application dont vous avez besoin :

  • Hôte : 127.0.0.1
  • Port : 6666

Remplacez 6666 par le port que vous avez choisi lors de l'initialisation de la connexion SSH.

Se pose une première problématique : que faire si l'application ne possède pas une telle option ?
Se pose ensuite une seconde problématique : certains applications n'utilise pas le proxy pour faire transiter certaines informations. C'est typiquement le cas de la résolution d'un nom de domaine via le protocole DNS. A quoi peut bien servir un tunnel si le réseau insecure arrive encore à voir une partie de notre trafic réseau ?

Ces deux questions trouvent la même réponse : il faut utiliser un programme qui capture les "appels réseau" d'un programme et force la redirection de ceux-ci dans le tunnel SSH. Il en existe plusieurs : tsocks, torsocks, proxychains, etc. . Il fait néanmoins faire attention : certains laisse encore passer les fameuses requêtes DNS entre les mailles de leur filet. Personnellement, j'utilise proxychains et je n'ai jamais rencontré de problèmes.

EDIT 09/01/2011 19h35 : Il faut dire aussi que mon choix pour proxychains a été influencé par les différents inconvénients qui apparaissent sur les alternatives :

  • La version de tsocks disponible sur sourceforge laisse fuiter les résolutions DNS, à moins d'appliquer un patch. De plus, je rencontre beaucoup d'erreur de segmentation avec des applications courantes
  • Torsocks me sort une erreur de segmentation pour quelques uns de mes programmes. Néanmoins, il y a quand même des progrès, par rapport à tsocks, sur ce point là.
  • Dsocks me paraissait un peu "brouillon" avec son script python servant de forwardeur DNS. De plus, le script ne fonctionne pas et me lève des exceptions.
  • Socat est une alternative que je n'ai pas essayé mais qui me parait plus que correcte mais lourde à utiliser.

Le fichier de configuration (/etc/proxychains.conf) est d'une simplicité enfantine. Voici le mien (j'ai supprimé quelques commentaires mais je vous invite à les lire dans votre fichier) :

# Strict - Each connection will be done via chained proxies
# all proxies chained in the order as they appear in the list
# all proxies must be online to play in chain
# otherwise EINTR is returned to the app
strict_chain

# Quiet mode (no output from library)
quiet_mode

# Proxy DNS requests - no leak for DNS data
proxy_dns

[ProxyList]
socks5 127.0.0.1 6666

Il ne vous reste plus qu'à utiliser proxychains :

proxychains firefox
proxychains thunderbird
proxychains filezilla
proxychains pidgin
...
sudo proxychains apt-get update/install

Il ne vous reste plus qu'à modifier les raccourcis de votre menu (Gnome, KDE, etc.) afin d'inclure proxychains dans la commande à lancer pour les programmes dont vous souhaitez qu'il passent via le tunnel SSH.

A noter quand même que certains logiciels jouent le jeu et ne laisse pas filer les requêtes DNS, même sans utiliser proxychains. C'est le cas par exemple de Firefox, une fois la valeur "true" passée à l'option booléenne "network.proxy.socks_remote_dns" dans le about:config. Par contre, je n'ai pas constaté d'améliorations en faisant la même manipulation sous Thunderbird.

EDIT 09/01/2011 22h00 : Pour plus d'information sur le transfert des requêtes DNS via un proxy SOCKS, voir cet article : SSH, redirection dynamique, proxychains et DNS.

Vous comprenez que votre meilleur ami ici sera Tsark/Wireshark (ou n'importe quel autre programme d'analyse du trafic réseau), afin de tester qu'aucun flux transite en clair. Il apparait évident de procéder à ces tests avant d'aller dans le réseau insecure. Un iptables correctement paramétré permet également d'éviter les fuites causées par les démons ou par les programmes que l'utilisateur aurait oublié de proxyfier. Voir ce billet à ce sujet : Configuration rapide d’iptables pour les réseaux insecures.

ÉDIT 23/02/2011 22h45 :

Lorsque vous n'utilisez pas votre tunnel SSH, la connexion est fermée automatiquement. Pour maintenir la connexion, il suffit de se rappeler de la notion de keepalive.

Encore une fois, je ne réinventerai pas la roue puisqu'une recherche sur Google vous conduira sur ce blog : Aaron Toponce : Keeping Your SSH Connection Alive.

J'ajouterai cependant que vous pouvez définir le paramètre "ServerAliveInterval" dans le fichier /etc/ssh/ssh_config, ce qui évite de le répéter lors de chaque connexion. Personnellement, je définis un intervalle de 5 minutes soit 300 secondes : c'est amplement suffisant pour maintenir la connexion.

Si toute cette méthode vous semble encore trop contraignante, il vous reste encore la possibilité de vous monter un VPN avec OpenVPN. Je me suis penché sur cette alternative mais, malheureusement, mon WRT54GL n'a pas assez d'espace libre pour accueillir la libssl nécessaire au fonctionnement d'OpenVPN. Donc je n'ai pas creusé le sujet plus loin. Néanmoins, excellents tutoriel existent sur le net.

Un VPN bon marché avec SSH

Il y a quelques jours, je me disais qu'il devait y avoir un moyen de s'amuser avec SSH et les interfaces tun/tap. Je me tourne vers mon ami Google afin d'avoir une idée sur la marche à suivre. Je découvre alors que d'autres personnes ont eu mon idée depuis bien longtemps et notamment les développeurs d'openSSH qui permet, depuis sa version 4.3, de créer un tunnel de niveau 3 grâce aux interfaces virtuelles tun. Si j'étais un "artiste" ou un patent troll, je porterai plainte ... oser me voler mon idée que je n'avais pas à l'époque, c'est quand même scandaleux ! 😉 .

Voici les tutoriels qui m'ont éclairés sur le sujet :

J'ai évidemment voulu tester tout ça, en utilisant la méthode manuelle (sans ifup), avec une machine virtuelle, avant une mise en production sur mon WRT54GL. Il n'y a aucune difficulté et ça fonctionne très bien (avec la machine virtuelle).

Malheureusement, dropbear, le serveur ssh allégé fourni par défaut avec OpenWRT, ne supporte pas ce type de tunnel. Installer OpenSSH sur mon routeur pose le même problème que celui de l'installation d'OpenVPN : la nécessaire libssl est trop lourde.

Donc je suis contraint d'utiliser un tunnel dynamique pour sécuriser mes connexions depuis un réseau insecure. Pour l'instant, cela me convient. Mais il faudra quand même que je songe à greffer une carte mémoire à mon WRT54GL.

Une dernière chose : comme signalé dans les commentaires de Debian Administration ou sur la page de la Community Ubuntu Documentation, la méthode de VPN over SSH n'est pas la meilleure solution du fait que le protocole SSH repose sur TCP et que l'on va faire circuler des trames TCP dans ce tunnel. Cette solution est impeccable quand il n'y a pas de problèmes sur le(s) réseau(x) traversé(s), mais dans le cas d'une perte de paquet, on assiste à un effondrement interne de la connexion. C'est pour cela qu'il veut mieux utiliser un VPN basé sur OpenVPN, configuré en UDP, bien entendu.

Je vous invite à lire ces deux documents, le deuxième étant la traduction, en français, du premier, afin d'avoir plus d'informations sur le sujet :

Note : dans cet article, je me préoccupe des systèmes UNIX/UNIX-like. Mais sous Windows, PuTTY permet la redirection locale, distante et dynamique. Ensuite, il doit exister des équivalents de proxychains, torsocks. Enfin, cygwin doit permettre de monter un VPN over SSH mais je ne me suis pas renseigné sur ce point.

SSH : X11 forwarding

Table des matières

SSH permet d'obtenir bien plus qu'un simple shell distant sécurisé. Entre autre, il permet de déporter, de manière sécurisée bien entendu, l'affichage de toute application graphique, même un bureau complet. Je ne suis pas un fan de l'utilisation d'un serveur X sur une machine ayant un rôle de serveur mais, pourtant, des utilisateurs m'ont récemment demandé la possibilité d'avoir un accès graphique complet à un serveur sous Fedora.

Connexion simple et directe

Par connexion simple et directe, j'entends que le client se connecte directement au serveur, sans serveur SSH intermédiaire.

Voici un schéma pour bien comprendre (source : kuxon.org) :
schema connexion SSH simple et directe

Préparatifs

Si votre client est sous GNU/Linux

Mode X11Trusted ou mode X11Untrusted ?
Pour tout savoir du mode X11 trusted/untrusted, je vous recommande ce site : HSC : SSH et redirection X11. Je vous conseille également la lecture du site suivant, plus récent et peut-être plus accessible : Wednesday Why: Trusted and Untrusted X11 Forwarding with SSH.

Pour résumer : "It should be possible to run almost all clients as untrusted, leaving the trusted category for screencapture and screencast programs, macro recorders, and other specialized utilities." (cf : deuxième lien donné ci-dessus). Il convient donc d'utiliser le mode untrusted (ssh -X) plutôt que trusted (ssh -Y) afin d'augmenter un peu la sécurité.

Mais c'est plus compliqué que cela. Si la ligne "ForwardX11Trusted yes" est présente dans votre fichier ssh_config (coté client donc), alors ssh -X revient au même que ssh -Y : cela correspond au mode trusted. Veuillez donc a ce que la directive "ForwardX11Trusted" soit bien à "no" dans le fichier ssh_config du client et utilisez l'argument -X de SSH sauf si le client X11 n'est pas compatible avec le mode untrusted auquel cas, utilisez l'argument -Y.

Il n'y a rien a installer. Il ne reste plus qu'à vous connecter à votre serveur SSH :

ssh -X login@host
Si votre client est sous Windows

PuTTY permet également le X11 forwarding. Il faut aller dans le menu "SSH" puis dans "X11". Il faut cocher la case "Enable X11 forwarding". Pour choisir le protocole d'authentification en tout connaissance de cause, je vous conseille la lecture de ce site : Configuring PuTTY.

Ensuite, il vous faut une implémentation du serveur X pour Windows. A ma connaissance, il y a Xming ou Cygwin/X.

Ensuite, il ne vous reste plus qu'à initier la connexion au serveur SSH (bouton "Open").

Utiliser des applications graphiques

Forwarder quelques applications

Que votre client soit sous GNU\Linux ou sous Windows, vous pouvez lancer un programme graphique en utilisant cette syntaxe (dans le shell distant bien sûr) :

programme >/dev/null 2>&1 &

Par exemple :

firefox >/dev/null 2>&1 &

Explications : ">/dev/null 2>&1" permet de rediriger la sortie standard et la sortie d'erreur vers /dev/null afin de ne pas être saturé par des messages de debug/erreur. "&" permet de mettre l'application en arrière plan et donc de libérer le terminale et donc de pouvoir taper d'autres commandes (qu'elles lancent un programme graphique ou pas).

Forwarder un environnement graphique complet

Je pense que ce n'est pas la meilleure solution. Cela surcharge le trafic réseau inutilement car vous savez très bien les applications que vous voulez lancer et vous pouvez donc les lancer avec la méthode précédente. Si vous tenez à utiliser cette solution, activer au moins la compression de la connexion, lors de la connexion au serveur SSH, avec l'argument -C de ssh :

ssh -XC login@host

Avec gnome :

gnome-session >/dev/null 2>&1 &

Avec KDE (je n'ai pas testé puisque notre serveur Fedora est équipé de Gnome) :

startkde >/dev/null 2>&1 &

Là aussi, peu d'importance que le client soit sous un Unix ou sous un Windows.

Connexion via un serveur SSH intermédiaire

Il peut arriver que le serveur sur lequel on veut récupérer l'affichage soit derrière un pare-feu et que le seul moyen de traverser le pare-feu soit un autre serveur SSH.

Voici un schéma pour mieux comprendre ce qui va suivre (source : kuxon.org) :
schema connexion SSH complexe

En tout cas, seul l'étape de connexion au serveur change, le reste est identique. Le choix entre le mode trusted/untrusted reste d'actualité, avec les même enjeux qu'avec une connexion SSH directe.

On se connecte d'abord au serveur SSH qui sert de relai (serveur A sur l'image d'illustration) en activant le port forwarding local :

ssh -L2200:serveurB:22 loginA@serveurA

Puis on se connecte au serveur B, en activant le X11 forwarding :

ssh -X loginB@127.0.0.1 -p 2200

Cette commande est à taper sur le client, pas dans le shell distant de A, évidemment. loginA est le login sur le serveur A et loginB ... le login sur serveurB.

Et si on avait 2 serveurs intermédiaires ?

Le principe reste le même :

ssh -L2200:serveurB:22 loginA@serveurA
ssh -L22000:serveurC:22 loginB@127.0.0.1 -p 2200
ssh -XC loginC@127.0.0.1 -p 22000

Par contre, dans ce cas précis, l'empilement des couches réseau est abominable ... mais on a pas tous les jours besoin de se connecter en mode graphique et encore moins en passant via 2 serveurs intermédiaires.

Une dernière chose que vous devez vous demander : pourquoi avoir utiliser les images du site kuxon.org et ne pas appliquer la méthode que ce site propose ? Tout simplement parce que je n'ai pas réussi à faire fonctionner la méthode présentée par ce site.

Je signale également que l'idée d'utiliser le port forwarding afin de déporter l'affichage à travers un deuxième serveur SSH intermédiaire m'est venue à la consultation de cette page web où cette méthode y est écrite, succinctement : UNIX One-Liners.

VirtualBox : configurations réseau possibles

Pour mes expériences diverses, j'adore utiliser des machines virtuelles. Je suis fan de VirtualBox OSE (et bientôt de KVM/Qemu 😉 ). Ce billet se propose de résumer les différentes configurations réseau possibles avec VirtualBox.

Avant tout, je vous conseille la lecture de la documentation de VirtualBox qui a le mérite d'être bien fournie sur le sujet : Chapter 6. Virtual networking.

Réseau interne : permet de créer un réseau virtuel, limité aux machines virtuelles qui y ont été explicitement ajoutées. Sous GNU/Linux, la sécurité est encore plus grande puisque seules les machines virtuelles crées par le même utilisateur (la comparaison est faite sur l'UID) peuvent être reliées entre elles. Les machines virtuelles peuvent communiquer entre elles sans restrictions mais elles ne peuvent pas communiquer avec l'hôte. Ce mode permet de tester des configurations réseau sans dommages sur le vrai réseau. On peut aussi imaginer un petit laboratoire permettant d'étudier les vers (disséquer sans risque, voir la propagation sur un réseau ...).

NAT : je me sers de ce mode quand je souhaite accéder seulement à Internet ou à d'autres services fournis sur mon réseau (exemple : un serveur web). L'hôte et l'invité partage la même adresse IP : la machine virtuelle est donc transparente sur le réseau : il n'y a pas de nouvelle machine. Par défaut, il est impossible de joindre l'invité depuis l'hôte. Cependant, on peut utiliser le port forwarding afin d'accéder à un ou plusieurs ports de l'invité. Voir la doc concernant le port forwarding. Cette idée du port forwarding m'a été donnée, pour la première fois, lors de la lecture du blog de Gauthier Garnier.

Cependant, le port forwarding n'est pas toujours la meilleure solution lors de simulation réseau. Pour cela, il existe un autre mode :

Accès par pont : VirtualBox bypass la pile réseau de l'hôte et accède directement à la carte réseau choisie. Vu du réseau, une nouvelle machine apparait. L'invité à accès au reste du LAN, à internet (comme avec le mode NAT quoi). Mais en plus, l'hôte (et les autres machines du LAN) peut avoir accès à la machine virtuelle sans port forwarding.

Je me sers de ce mode pour faire des expériences plus complexes entre l'invité et l'hôte et/ou mon LAN réel. Mais, parfois, je n'ai pas de routeur ni de commutateur connecté a mon hôte mais juste un modem. Dans ce cas précis, je n'arrive pas à faire communiquer mon invité et mon hôte en mode "accès par pont". Cela fonctionne en mode "NAT" mais je ne peux pas accéder comme je veux à l'invité via le réseau (comprendre : le port forwarding a des limites). Pour cela, il existe encore un autre mode :

Réseau privé hôte : Il s'agit d'un mix entre le mode "réseau interne" et le mode "accès par pont" : une ou plusieurs machines virtuelles peuvent communiquer entre elles et avec l'hôte sans limites. Néanmoins, les machines virtuelles n'ont pas accès au LAN réel ni à Internet. Cela peut néanmoins s'arranger :

Étape 1 : Transformer votre hôte en passerelle.

$ sudo -i
# echo 1 > /proc/sys/net/ipv4/ip_forward
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# exit

Si vous voulez conserver l'ip forwarding après un reboot de l'hôte, pensez à décommenter la ligne "net.ipv4.ip_forward=1" dans le fichier /etc/sysctl.conf. Pour remettre les actions par défaut dans la table NAT, pensez à la commande :

sudo iptables -t nat -P POSTROUTING ACCEPT

Etape 2 : Ajoutez une route par défaut à l'invité :

sudo route add -net default gw IPHote

N'oubliez pas de remplacer IPHote par l'adresse IP de l'interface créée par VirtualBox sur l'hôte.

Il ne vous reste plus qu'a configurer les DNS (/etc/resolv.conf) et c'est terminé.

Remarque : je n'ai traité que le cas où le système hôte et le système invité sont des Unix. Je n'ai pas testé les cas avec un Windows comme invité ou comme hôte mais voici quelques pistes vers lesquelles chercher si ça vous intéresse.

  • Si votre hôte est un Windows et votre invité est un Unix, il faudra suivre ceci (marche aussi pour les dernières versions de Windows d'après ce qu'on m'a dit) pour l'étape 1. L'étape 2 ne change pas.
  • Si votre hôte est un Unix et votre invité un Windows, seul l'étape 2 change. La ligne de commande doit être quelque chose comme :
    route add 0.0.0.0 mask 0.0.0.0 IPHote
  • Si votre système hôte et votre système invité sous tous les deux des Windows, il faudra suivre les deux points ci-dessous.

Réseau VDE : ce mode apparait dans la liste quand le logiciel VDE est installé sur l'hote. Virtual Distributed Ethernet (VDE) est un commutateur virtuel. Il permet de relier les machines virtuelles (et même l'hôte selon la manière dont il est configuré) entre elles et offre les fonctions supplémentaires d'un commutateur (VLAN, STP, etc.). Il permet de faire un réseau encore plus réaliste. Allez sur le wiki du projet VDE pour avoir plus d'informations.

Sinon, pour cloner un disque dur virtuel (.vdi) afin de l'utiliser dans une autre machine virtuelle (par exemple), c'est par là : http://www.mdl4.com/2010/05/how-to-copy-clone-a-virtualbox-vdi-in-ubuntu/

ÉDIT du 07/08/2011 à 0h45 : Et pour accéder aux dossiers partagés avec GNU/Linux comme système invité, il suffit de faire :

mount -t vboxsf sharename mountpoint

Où "sharename" est le nom du partage tel que vous l'avez défini lors de sa création. "mountpoint" doit bien éviter exister dans le système de fichiers. Exemple :

mount -t vboxsf docs /mnt/docs

Source :Documentation officielle de Virtualbox.
Fin de l'édit

Chez les Moldus

Récemment, j'ai dépanné des Moldus de l'informatique. J'ai du :

  • Faire reconnaitre une carte PCI Wifi achetée d'occasion par un Windows XP. Rien de bien sorcier ... sauf quand la carte en question n'a pas été vendue avec ses pilotes et que le nouveau propriétaire ignore sa marque/son modèle. Quand en plus la carte prend en charge uniquement le WEP, on se retrouve à expliquer pourquoi ce n'est pas une bonne idée de remplacer une clé USB Wifi qui gère le WPA2 par une carte PCI Wifi qui ne gère que le WEP et les conséquences que cela a sur la sécurité du réseau domestique. Mais, en étant un tout petit peu pédagogue, on s'en sort :).
  • Faire en sorte que le lecteur/graveur CD/DVD reprenne du service. Là aussi, rien de bien compliqué : le lecteur/graveur fonctionnait au boot de l'ordinateur et le gestionnaire des périphériques indiquait un code d'erreur 19 "Windows ne peut pas démarrer ce périphérique matériel car ses informations de configuration (dans le registre) sont incomplètes ou endommagées. (Code 19)". Il suffit ensuite de suivre l'aide de Microsoft et notamment la méthode n°1. Toutefois, je n'ai pas supprimé la clé mais toutes les valeurs s'y trouvant.
  • Faire (encore) un peu de pédagogie et expliquer pourquoi ce n'est pas une bonne idée de fusionner les deux partitions qui étaient crées à l'origine sur le disque dur mais, au contraire, s'en servir pour séparer documents et système d'exploitation.

Mais surtout, et c'est le point principal de ce billet : comment définir une musique (au format MP3), transférée via Bluetooh, en tant que sonnerie sur un Samsung Galaxy S. Par défaut, on peut choisir la sonnerie parmi une liste restreinte. L'appareil est évidemment équipé avec un Android "untouched"/ "unrooted", si j'ose dire.

Comme à chaque fois que je ne sais pas, je me retourne vers le nain Ternet et son ami Google. J'apprend que, contrairement à ce qu'on m'avait dit, il ne faut pas un ordinateur pour transférer la sonnerie sur le mobile. Je sélectionne un tutoriel qui explique tout cela parmi tans d'autres : Mettre un MP3 en sonnerie/alarme/notification.

Il suffit de créer les dossiers depuis l'application de gestion des fichiers du téléphone puis de déplacer la musique voulue du répertoire "bluetooh" vers le répertoire créé. Il faut néanmoins adapter la dernière partie de ce tutoriel puisque les menus ne sont pas identiques entre un HTC et un Samsung. De plus, les sonneries peuvent faire plus de 30 secondes sans problème.