®om's blog { un blog libre }

Authentification automatique à un réseau WiFi avec NetworkManager

Certains réseaux WiFi sont ouverts (sans clé de sécurité) mais nécessitent une authentification. C’est souvent le cas des points d’accès dans les gares, les hôtels, les campings… Cela concerne également les réseaux ouverts tels que FreeWifi.

Une fois connecté à un tel réseau, lorsqu’avec votre navigateur vous tentez d’accéder à n’importe quel site, vous êtes redirigé vers une page d’authentification demandant votre identifiant et votre mot de passe (parfois il ne s’agit que d’accepter des conditions d’utilisation). Après avoir renseigné ces informations, vous êtes authentifié et pouvez accéder à Internet normalement.

Mais il faut avouer que s’authentifier manuellement à chaque connexion est pénible. D’autant plus que la redirection HTTP vers la page d’authentification ne fonctionne… que pour HTTP. Ainsi, alors que vous êtes connecté au réseau Wifi, votre client mail ne parviendra à récupérer les mails, votre client XMPP n’arrivera pas à se connecter au serveur… mais sans message indiquant la cause du problème.

Le but de ce billet est de mettre en place une authentification automatique lors de la connexion au réseau.

Authentification en ligne de commande

La première étape est de pouvoir réaliser cette authentification en ligne de commande, à partir de l’identifiant et du mot de passe. C’est très simple, il suffit d’imiter ce que fait le navigateur lors du clic sur le bouton Valider.

Pour cela, deux choses sont nécessaires : l’URL de la page de validation d’authentification et les champs de formulaire qu’elle utilise.

Pour les connaître, il faut regarder le code source de la page sur laquelle vous êtes redirigés, en particulier la balise form. Voici un exemple de ce que vous pouvez obtenir (le HTML n’est pas toujours super propre sur ce genre de pages) :

<form method="post" action="http://10.9.0.1:8000/">
Login <input name="auth_user" type="text">
Password <input name="auth_pass" type="password">
<input type="checkbox" name="regagree" value="valeur"
onClick="ChangeStatut(this.form)"> J'accepte le règlement
<input name="redirurl" type="hidden"
value="http://www.google.com/search?ie=UTF-8">
<input type="submit" name="accept" value="Continuer" disabled>
</form>

Tout y est. La valeur de l’attribut action est l’URL de validation, et le nom des champs utilisés est dans l’attribut name de chaque balise input.

Dans cet exemple, seuls auth_user et auth_pass semblent utiles, mais parfois le serveur effectue des vérifications (étranges) supplémentaires. Ici, il vérifie qu’il y a bien un attribut accept qui vaut Continuer (allez savoir pourquoi).

À partir de ces champs, nous allons construire la chaîne des paramètres sous la forme :

champ1=valeur1&champ2=valeur2&champ3=valeur3

et l’envoyer au serveur en POST, par exemple grâce à la commande POST (en majuscules, ça surprend un peu pour une commande shell) :

POST http://10.9.0.1:8000/ <<< 'auth_user=IDENTIFIANT&auth_pass=MOT_DE_PASSE&accept=Continuer'

Si la page d’authentification est en HTTPS, il faudra installer le paquet libcrypt-ssleay-perl, ou alors utiliser wget :

wget -qO- https://10.9.0.1:8000/ --post-data='auth_user=IDENTIFIANT&auth_pass=MOT_DE_PASSE&accept=Continuer'

Voilà, nous avons reproduit en ligne de commande le comportement du navigateur pour l’authentification. Nous devons maintenant faire en sorte que cette commande soit exécutée dès la connexion au réseau WiFi.

Exécuter un script lors de la connexion

NetworkManager (le gestionnaire de connexion par défaut d’Ubuntu) permet d’exécuter des scripts lors de la connexion ou la déconnexion. Pour cela, il suffit de placer le script dans /etc/NetworkManager/dispatcher.d/ et de le rendre exécutable.

Le script est appelé avec deux paramètres :

  • $1 : l’interface réseau concernée par la connexion ou la déconnexion (wlan0 par exemple) ;
  • $2 ayant pour valeur soit up (pour la connexion), soit down (pour la déconnexion).

Nous voulons exécuter la commande POST uniquement lors de la connexion de wlan0, et seulement pour le réseau concerné (par exemple celui ayant le nom MonLieuDeVacances).

Il est possible de récupérer le nom du réseau (l’ESSID) auquel nous sommes connectés grâce à iwconfig :

iwconfig wlan0 | grep -o 'ESSID:".*$' | sed 's/^ESSID:"\(.*\)".*$/\1/'

Il faut donc créer un script dans /etc/NetworkManager/dispatcher.d/10auth :

sudo vi /etc/NetworkManager/dispatcher.d/10auth

ayant cette structure :

#!/bin/bash
if [ "$1 $2" = 'wlan0 up' ]
then
    essid=$(iwconfig wlan0 | grep -o 'ESSID:".*$' | sed
's/^ESSID:"\(.*\)".*$/\1/')
    case "$essid" in
        'MonLieuDeVacances')
            POST http://10.9.0.1:8000/ <<< 'auth_user=IDENTIFIANT&auth_pass=MOT_DE_PASSE&accept=Continuer' ;;
        'MaGare')
            POST http://192.168.0.1 <<< 'accept_cgu=1' ;;
    esac
fi

Et le rendre exécutable :

sudo chmod +x /etc/NetworkManager/dispatcher.d/10auth

Script pour FreeWifi

Les pages d’authentification varient d’un réseau à l’autre, il faut donc adapter les paramètres de connexion selon le service utilisé.

Voici le script à utiliser (en adaptant votre identifiant et votre mot de passe) pour le réseau FreeWifi (très connu) :

#!/bin/bash
if [ "$1 $2" = 'wlan0 up' ]
then
    essid=$(iwconfig wlan0 | grep -o 'ESSID:".*$' | sed 's/^ESSID:"\(.*\)".*$/\1/')
    case "$essid" in
        'FreeWifi')
            wget -qO- https://wifi.free.fr/Auth --post-data='login=IDENTIFIANT&password=MOT_DE_PASSE' ;;
    esac
fi

Tunnel SSH

Ces réseaux ouverts, gérant éventuellement une authentification HTTP, ne sont pas chiffrés : n’importe qui écoutant ce qui transite dans les airs pourra récupérer tout le contenu de votre trafic. Si vous avez un ordinateur allumé chez vous (sur un réseau “sûr”) accessible en SSH, je vous conseille de faire passer toutes les connexions dans un tunnel chiffré.

Le principe est simple : dès que vous accédez à un serveur (par exemple en tapant l’URL dans un navigateur web), l’ordinateur ne va pas s’y connecter directement, il va transmettre les informations en passant par un tunnel chiffré à votre serveur SSH, qui lui va s’y connecter, et vous renvoyer la page à travers le tunnel. Techniquement, le tunnel est un proxy SOCKS écoutant sur un port local (par exemple localhost:3128).

Pour démarrer le tunnel :

ssh monserveur -CND3128

Pour configurer le système afin qu’il utilise le tunnel SSH, Système → Préférences → Serveur mandataire (gnome-network-properties), puis configurer comme sur la capture d’écran :

proxy

Dans l’onglet Hôtes à ignorer, rajouter l’adresse de la page d’authentification.

Ainsi, toutes les connexions des logiciels utilisant les paramètres proxy du système passeront par le tunnel. Il est également possible de configurer ceci dans chaque logiciel individuellement (s’ils le proposent).

Pour Firefox, il est également recommandé dans about:config de passer la variable network.proxy.socks_remote_dns à true, afin que les DNS soient résolus également de l’autre côté du tunnel (sur le réseau “sûr”).

Vous trouverez plus d’infos sur mon billet concernant SSH.

Conclusion

La connexion à des points d’accès WiFi publics demandant à chaque fois une authentification ou une acceptation des conditions d’utilisation devient rapidement insupportable. Il est donc appréciable de l’automatiser.

De plus, ces réseaux ne sont pas “sûrs”, n’importe qui peut écouter le trafic. Il est donc nécessaire de le chiffrer en passant par un réseau de confiance, par exemple avec un tunnel SSH.

Commentaires

Eric G.

Article très interessant, j’était confronté à ce problème lors de l’installation de arch à ma cité U (page d’authentification de m***)

Merci !

Mille fois merci pour cet article. Je ne compte pas le nombre de fois où j’ai lancé par mégarde mon navigateur avec sa session sauvegardée, me retrouvant aussitôt avec 150 onglets “page de connexion FreeWifi” (avec bien sûr impossibilité de revenir en arrière via l’historique (mais peut-être que ce problème ne se pose plus avec les nouvelles versions de firefox qui gèrent différemment les historiques de session ? Pas testé.)).

Un grand merci, un article clair et bien structuré. Bravo.

®om

@gnuzer

Je ne compte pas le nombre de fois où j’ai lancé par mégarde mon navigateur avec sa session sauvegardée, me retrouvant aussitôt avec 150 onglets « page de connexion FreeWifi »

Effectivement, ça m’est arrivé lors de l’écriture de cet article, quand je me suis connecté en FreeWifi avant de mettre en place l’authentification automatique…

@gnuzer

mais peut-être que ce problème ne se pose plus avec les nouvelles versions de firefox

Malheureusement, non, ça m’est arrivé avec Firefox 5.0.

(Enfin, tu me diras, Firefox 6, 7 et 8 devraient bientôt arriver)

reboutte

Article intéressant mais je me méfie des automatismes, surtout s’ils concernent une connexion wifi à un hotspot…

Attention au “faux” host spot de votre opérateur.

Pour info

http://www.crack-wifi.com/tutoriel-rogue-ap-les-dangers-des-hotspots-wifi.php

®om

@reboutte

Article intéressant mais je me méfie des automatismes, surtout s’ils concernent une connexion wifi à un hotspot…

Je me suis posé la question lorsque j’ai automatisé l’authentification, mais après réflexion, s’il y a un risque lorsque c’est automatisé, il y a exactement le même risque lorsqu’on se connecte manuellement : si l’on se connecte automatiquement à un faux hotspot et qu’il parvient à récupérer nos identifiants, il l’aurait fait exactement de la même manière en présentant une fausse page de connexion.

Pour les pages d’authentification en HTTP, il n’y a absolument aucune sécurité (que ce soit manuel ou automatique), on n’a aucune idée de la “fiabilité” du point d’accès, et n’importe qui peut récupérer les identifiants (un man-in-the-middle ne déclenche aucune alerte).

Pour les pages en HTTPS (comme FreeWifi), il y a quand même le certificat SSL qui est supposé éviter les man-in-the-middle (certificat + chiffrement).

@reboutte

Pour info

http://www.crack-wifi.com/tutoriel-rogue-ap-les-dangers-des-hotspots-wifi.php

Merci pour le lien.

Par contre, on met souvent en avant les risques pour les coordonnées bancaires :

le meme type de scénario est possible si, connecté à un hotspot, vous vous rendez sur le site de votre banque […] Il est alors facile pour le pirate de récupérer vos coordonnées bancaires, identifiants, mots de passe, bref tout ce qui transitera sur le réseau.

D’ailleurs, lorsque j’ai demandé l’accès WiFi sur mon lieu de vacances, sous mon identifiant et mon mot de passe était précisé que le réseau n’était pas chiffré (ce qui est vrai), et donc qu’il ne fallait pas utiliser des coordonnées bancaires.

Pourtant, même sur une connexion non fiable (c’est d’ailleurs le but), le HTTPS garantit la confidentialité et l’authenticité… Pourquoi y aurait-il un risque pour les données bancaires ? Il faudrait modifier les autorités de confiance sur le poste du client, ou casser le SSL… Je ne dis pas que c’est impossible, mais c’est quand même d’un autre niveau…

Quant à la conclusion de l’article, elle est un peu extrême :

N’UTILISEZ JAMAIS LES HOTSPOTS WIFI. On vous aura prévenu.

On pourrait dire exactement la même chose pour Internet : ne vous connectez pas à Internet, vous éviterez de vous faire pirater votre ordinateur…

guigui

Bonjour, je m’efforce de faire un script qui fonctionne pour le réseau de ma fac, mais certaines subtilités m’échappes…

Voila ce qu’on peut trouver dans la balise form :

<form action="/auth/index.html/u" autocomplete="off" method="post" onsubmit="return validate();">
    <div id="titre"><p><img class="img-box" src="https://wifi.u-bourgogne.fr/lock.png"/>  Formulaire de connexion</p></div>
    <div id="login">
        <div id="logo"><a href="http://www.u-bourgogne.fr/"><img id="logo" src="https://wifi.u-bourgogne.fr/ub.gif"/></a></div>
        <div class="row">
            <label for="username">Nom d'utilisateur :</label>
            <input id="username" name="username" tabindex="1" size="20" autocomplete="false" type="text" value=""/>
        </div> 
        <div class="row">
            <label for="password">Mot de passe :</label>
            <input id="password" name="password" tabindex="2" size="20" autocomplete="false" type="password" value=""/>
        </div>
        <div class="row">
            <label for="fqdn">Population :</label>
            <select id="fqdn" name="fqdn" tabindex="3">
                <option value="u-bourgogne.fr">Personnel de l'uB</option>
                <option value="etu.u-bourgogne.fr">Etudiant de l'uB</option>
                <option value="dijon.iufm.fr">IUFM de Bourgogne</option>
                <option value="iut-dijon.u-bourgogne.fr">IUT de Dijon</option>
                <option value="iut-chalon.u-bourgogne.fr">IUT de Chalon</option>
                <option value="iut-auxerre.u-bourgogne.fr">IUT d'Auxerre</option>
                <option value="isat.u-bourgogne.fr">ISAT de Nevers</option>
                <option value="invites.u-bourgogne.fr">Visiteur</option>
            </select>
        </div>
        <div class="btn-row">
            <input id="submit" class="test" type="submit" onmouseover="onSubmitOver();" onmouseout="onSubmitOut();" value="Se connecter" tabindex="3"/>
        </div>
    </div>
</form>

Dans l’attribut action, pas d’url de validation mais une adresse locale… Comment faire ?

®om

@guigui C’est l’URL relative à ta page courante.

Utilise la page http://le_serveur/auth/index.html/u.

(bizarre d’ailleurs le /u après le .html)

guigui

Rebonjour, mon script ne fonctionne pas, il donne :

#!/bin/bash
if [ "$1 $2" = 'wlan0 up' ]
then
    essid=$(iwconfig wlan0 | grep -o 'ESSID:".*$' | sed 's/^ESSID:"\(.*\)".*$/\1/')
    case "$essid" in
        'universite')
            POST http://www.u-bourgogne.fr/auth/index.html/u <<< 'username=gt846930&password=grossebite&fqdn=etu.u-bourgogne.fr&submit=Se connecter' ;;
        'Fac_dijon')
            POST http://192.168.0.1 <<< 'accept_cgu=1' ;;
    esac
fi

Firefox m’affiche tout de même la page de connexion du hotspot et je doit taper mes identifiants et mot de passe… Peut être que je n’ai pas bien compris la fin de la balise form ?

®om

@guigui Ça c’est du mot de passe !

Pour voir ce qu’il se passe, commente la ligne POST du script, et lorsque tu n’es pas encore authentifié au réseau, exécute cette commande manuellement dans un shell. Sur la sortie standard tu auras la page de résultat, ça te donnera peut-être des indications.

guigui

Zut ! Je voulais pas le mettre, une mauvaise blague d’un ami… (je suis pas crédible). Je test.

Ginsens

Merci pour le script et les infos - tuto très clair et bien utile. Juste une petite question, je suis assez régulièrement confronté au même problème d’identification mais pas nécessairement en wifi. Certaines universités / labo demandent une authentification régulière même directement branché en RJ-45… tu saurais comment adapter ton script à une connexion filaire ?

Merci,

Ginsens

®om

@Ginsens À la place de wlan0, mets eth0.

Par contre, tu ne peux plus tester le nom du point d’accès, donc soit tu exécutes l’authentification à chaque fois (quelque soit l’endroit où tu te connectes par câble), soit tu tentes d’identifier la connexion de ton université (par exemple en fonction de l’adresse IP qui t’es attribuée).

yan

A noter, pour ceux qui se méfient de la sécurité de la page de connection… qu’il existe des scripts/client de connection qui vérifient explicitement le certificat présenté pour les hot-spot de nos FAI.

C’est une précaution supplémentaire… surtout si une page de rogue AP inclut une redirection http, qui va ici passer totalement inapercue (pas d’alerte certificat autosigné suspect) si je ne m’abuse?

[…] qu’à mettre cette commande dans un script shell, de le rendre exécutable et d’utiliser le Network Manager ou bien Wicd (Proprieté de la connexion, Scripts, Post-connecion script) ou le fichier de […]

Hophop

Bonjour à tous,

Est-il possible d’effectuer la même opération sous Windows 7 ? Je précise d’emblée que je suis un néophyte en la matière, mais devoir sans cesse m’authentifier pour accéder à internet depuis mon université m’horripile au plus haut point et me pousse à m’atteler à la tâche.

D’avance merci pour vos réponses.

Poster un commentaire

Nom : (requis)
E-mail : (optionnel, non publié)
Site web : (optionnel)
Quelle est la 3e lettre du mot blog ? (antispam)

Les commentaires sont formatés en markdown.