Le débogage du WiFi

Gazette Linux n°135 — Février 2007

Hervé Ly-Sunnaram

Adaptation française 

Gaël Montreuil

Relecture de la version française 

Article paru dans le n°135 de la Gazette Linux de février 2007.

Article publié sous Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.


Table des matières

Ça marche pour moi
L'approche
Dans le doute, utilisez la force brute
Avancer à l'aveuglette
TCPDUMP à la rescousse
Le Gang parle
Zeroconf
Worldcon
C'est au pied du mur...
Quelques réflexions pour finir
À propos de l'auteur

Ça marche pour moi

Est ce que vous aimez qu'on vous dise quand vous avez un problème « Sur ma machine, ça marche tout seul » ? Je sais, moi non plus. Alors quand Ben Okopnik a écrit sur la Gazette Linux #127:

Je voyage beaucoup et je me connecte à un vaste panel de réseaux locaux sans fil bizarres. De par mon expérience, au moins, se connecter à un réseau sans fil avec Linux est en général aussi simple qu'Edgar le décrit. – Ben

Ça m'a donné l'envie de résoudre un problème que j'avais depuis longtemps : je ne pouvais pas me connecter aux points d'accès WiFi « ouverts ». Je n'avais aucun problème avec tous les points d'accès fermés. Quelqu'un me donne l'ESSID et la clé WEP et c'est parti. Mais balancez moi dans un hôtel, un aéroport ou un café et j'aurai beau bidouiller, impossible de me connecter.

Alors, étant bien décidé, j'ai écrit à Ben et lui ai proposé d'écrire cet article, si The Answer Gang voulait bien m'aider à résoudre mon problème. Ben et le Gang ont rempli leur part du contrat alors voici mon histoire.

L'approche

Tout d'abord, un mot à propos de ma configuration particulière, ainsi vous essayerez de changer des choses pour que ça s'adapte à votre propre installation. Je suis sur un ordinateur portable Dell C600 avec une carte WiFi intégrée non prise en charge. J'utilise donc une carte PCMCIA, une Microsoft MN-520. La machine se lance sous Debian Sarge avec toutes les mises à jour actuelles.

Puisque je pouvais me connecter facilement à n'importe quel point d'accès (PA) fermé, je savais que l'ensemble du matériel, des pilotes et des couches réseau fonctionnaient . Il était quasi-certain que mon problème était un problème de configuration.

Le fichier de configuration principal pour Debian est le fichier /etc/network/interfaces. Ma configuration actuelle contient l'ESSID et la clé WEP, qui a priori ne sont pas nécessaires pour un PA ouvert. Alors j'ai réduit le fichier de configuration à son minimum :

iface wlan0 inet dhcp
wireless-mode managed

Maintenant, un tour au café et regardons ce que nous obtenons dans /var/log/messages :

localhost dhclient: DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 6
localhost dhclient: DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 12
localhost dhclient: DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 11
localhost dhclient: DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 21
localhost dhclient: DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 7
localhost dhclient: DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 4
localhost dhclient: No DHCPOFFERS received.
localhost dhclient: No working leases in persistent database - sleeping.

Pas grand chose à se mettre sous la dent. Je fais quelques recherches Google et je vois que ma machine émet une requête pour avoir une adresse mais qu'elle n'obtient aucune réponse.

Dans le premier courriel que Ben m'a adressé, il a inclus un exemple de négociation d'adresse IP réussie :

Fenrir pumpd[4711]: PUMP: sending discover
Fenrir pumpd[4711]: got dhcp offer
Fenrir pumpd[4711]: PUMP: sending second discover
Fenrir pumpd[4711]: PUMP: got an offer
Fenrir pumpd[4711]: PUMP: got lease
Fenrir pumpd[4711]: intf: device: wlan0
Fenrir pumpd[4711]: intf: set: 416
Fenrir pumpd[4711]: intf: bootServer: 10.0.0.1
Fenrir pumpd[4711]: intf: reqLease: 43200
Fenrir pumpd[4711]: intf: ip: 10.0.0.219
Fenrir pumpd[4711]: intf: next server: 10.0.0.1
Fenrir pumpd[4711]: intf: netmask: 255.255.255.0
Fenrir pumpd[4711]: intf: gateways[0]: 10.0.0.1
Fenrir pumpd[4711]: intf: numGateways: 1
Fenrir pumpd[4711]: intf: dnsServers[0]: 10.0.0.1
Fenrir pumpd[4711]: intf: numDns: 1
Fenrir pumpd[4711]: intf: broadcast: 10.0.0.255
Fenrir pumpd[4711]: intf: network: 10.0.0.0
Fenrir pumpd[4711]: configured interface wlan0

Ben utilise pump plutôt que « dhcpd mais on voit clairement que sa machine envoie une requête discover, qui entraine une réponse du PA avec un dhcp> offer. Cela n'est qu'une adresse proposée que votre machine est libre de refuser (toutefois je ne vois pas pourquoi vous le feriez ).

Note

Ça pourrait bien avoir un drôle de goût, ou une odeur carrément insolite. Ou peut-être que tu as déjà une interface configurée avec cette IP. On ne sait jamais :p – Ben

Dans le doute, utilisez la force brute

L'aphorisme de Ken Thompson est de mise ici. Je ne pouvais pas avoir une connexion avec les outils automatiques alors j'ai opté pour une configuration manuelle. Je savais que j'avais besoin de l'ESSID pour le réseau du PA alors j'ai commencé à chercher des outils qui pouvait le découvrir sans connexion.

Tout d'abord, j'ai essayé la commande iwlist. Cet outil utilise la radio de la carte WiFi et guette ce que l'on appelle les Beacon Frames. Ce sont simplement des messages émis qui préviennent de la présence d'un PA. Un problème d'iwlist est qu'il est en écoute non continue : on obtient une liste de tout ce qui est émis sur le moment où il écoute. Même si on peut simplement répéter la commande iwlist, je me sentais plus à l'aise avec un outil qui écoute en continu.

Cet outil était Kismet. J'ai utilisé APT pour l'installer mais j'ai quand même dû éditer le fichier de configuration (/etc/kismet/kismet.conf) pour lui dire d'utiliser ma carte pilotée par Host-AP. Une fois configuré, Kismet m'a montré en continu une liste à jour des PA dans mon voisinage et m'a dit lesquels étaient ouverts et lesquels étaient masqués (ce qui se fait d'habitude simplement en n'émettant pas l'ID du réseau, connu sous le nom de SSID ou ESSID). Et ça n'a pas manqué, l'un des PA ouverts utilisait le nom du café comme ESSID.

Donc, cela signifie que ma machine peut voir le PA du café. Même la force du signal semblait bonne. Alors pourquoi je ne pouvais pas recevoir de réponse à ma requête DHCPDISCOVER ?

Cette méditation aboutit à la révélation : le WiFi est un système radio et ce n'est pas parce que j'entends bien le PA que le PA m'entend. Après tout, un PA a généralement un émetteur puissant, mais un émetteur PCMCIA (comme celui de ma carte WiFi) est quand même assez limité en puissance.

Avancer à l'aveuglette

Puisque je ne peux pas changer la puissance d'émission de ma carte, je me suis rapproché du PA. Maintenant, j'ai :

localhost pumpd[1275]: PUMP: sending discover 
localhost pumpd[1275]: got dhcp offer 
localhost pumpd[1275]: PUMP: sending second discover
localhost cardmgr[1068]: + Operation failed.
localhost cardmgr[1068]: + Failed to bring up wlan0.

(Comme vous pouvez le voir, je suis passé de dhcpd3 à pump, en me basant sur les suggestions du Gang). Ça semble prometteur puisque j'ai maintenant une offre mais j'ai maintenant une seconde requête discover qui échoue. Qu'est ce que ça signifie tout ça?

Je pense que le premier discover est utilisé pour recueillir les informations du PA (ESSID, etc.) qui sont ensuite utilisées pour faire la négociation d'adresse IP en question.

A ce stade, j'étais en quelque sorte frustré par le manque d'informations contenues dans les journaux. Mais une des raisons pour lesquelles j'utilise Linux est parce que le système ne cache aucun secret. On peut toujours avoir plus d'informations même s'il faut recompiler le noyau. Il était temps d'arrêter d'avancer à l'aveuglette.

TCPDUMP à la rescousse

À ce stade, The Answer Gang était aussi avide d'informations que moi. Ils voulaient voir les traces tcpdump. Tcpdump est un outil réseau de très bas niveau. Il surveille les interfaces physiques sous-jacentes (ethernet, radio, pigeon voyageur, tout ce qui transporte effectivement les bits).

Tcpdump est normalement lancé sur une interface réseau existante mais dans mon cas, en plus de ne pas en avoir, je ne pouvais pas en obtenir. C'était tout l'objet de ma quête. Alors le Gang a partagé l'incantation qui s'imposait : tcpdump -vvv -i any. (Vous pouvez utiliser plus ou moins de drapeaux v pour plus ou moins de détails.)

Alors il s'agissait maintenant, dans l'ordre suivant, d'apporter la machine, de commencer à prendre les fichiers d'enregistrement, de lancer tcpdump et d'enregistrer la sortie dans un fichier puis d'insérer la carte.

Ayant capturé le trafic qui avait échoué, je l'ai transféré au Gang. (Ben tenait à ce que je fasse du copier-coller. Trop souvent, ils reçoivent des données transcrites à la main qui ont été corrompues par un gros doigt). Puisqu'ils ont fait un très bon travail en parcourant les données tcpdump, je vais le copier-coller ici.

Le Gang parle

La sortie TCPDUMP est indentée par un '>'. L'explication de Ben Okopnik suit.

> 15:08:58.385577 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:02:2d:74:4a:fa, length: 300

Ok, ici on a ton émission « toutes stations » pour DHCP

> 15:08:58.395954 arp who-has 169.254.1.51 tell 169.254.1.1
> 15:08:58.397085 arp who-has 169.254.1.51 tell 169.254.1.1
> 15:08:58.398200 arp who-has 169.254.1.51 tell 169.254.1.1

Attendez une minute, il y a anguille sous roche. 169.254.X.X? C'est une IP qui est auto-assignée à une interface qui a demandé une affectation DHCP mais qui a échoué. Notez qu'elle n'est pas assignée par le serveur mais par ton noyau. (fais une recherche Google de APIPA pour plus d'infos. C'est un comportement Windows ridiculement courant, j'aurais dû le détecter plus tôt.) La requête ARP est la vérification habituelle : « Avant que j'affecte cette IP à cette interface, est-ce que quelqu'un l'utilise? ».

En d'autres termes, on dirait que ton système n'accuse jamais réception des communications avec le serveur DHCP hormis l'assignation ESSID. Et encore! C'est sûrement ton système qui effectue cette assignation, suite tout simplement à la détection de beacon.

Ou bien... Bon, c'est idiot, mais se pourrait-il que le serveur IP du café soit en fait configuré pour être 169.254.1.1? Dans ce cas, il est bien possible que ta machine était tout simplement en train de rejeter cette affectation et ce avec raison. Donc: ce /16 est une plage d'adresse réservée. Pas 'réservé' comme dans 10.x.x.x ou 192.168.x.x mais comme dans 'n'utiliser pour rien d'autre que les requêtes DHCP qui ont échoué'.

C'est une explication bizarre mais possible. Regardons si ça tient la route :

> 15:09:02.080455 IP 169.254.1.1.bootps > 255.255.255.255.bootpc: BOOTP/DHCP, Reply, length: 293

Bon, en fait il y a bien quelque chose avec l'adresse IP 169.254.1.1 qui te répond. Very bizarre...

> 15:09:02.083702 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:02:2d:74:4a:fa, length: 548
> 15:09:06.083860 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:02:2d:74:4a:fa, length: 548
> 15:09:13.082798 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:02:2d:74:4a:fa, length: 548
> 15:09:19.895539 IP 169.254.1.31.53127 > 255.255.255.255.2222: UDP, length: 106

… et quelque chose avec une autre IP dans cette plage réservée (169.254.1.31) répond. Ouais, ça commence à ressembler à un réseau drôlement mal configuré.

> 15:09:21.896457 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:02:2d:74:4a:fa, length: 548

Ça, ce sont toutes des réponses de ta machine, qui disent peut-être « nan, je peux pas utiliser cet IP. T'as pas autre chose? » et cette requête n'est jamais honorée. Je ne suis pas certain de ça mais ça y ressemble.

Je voudrais remercier The Answer Gang pour cette analyse. J'aurais passé des semaines à chercher tous ces paquets dans les RFC et autres spécifications.

Zeroconf

A ce stade, il apparaît que le PA que j'essaye d'utiliser est mal configuré. Il utilise une plage d'adresses IP qui est censée n'être utilisée par personne. Mais réfléchissons un petit peu. Si cette configuration est invalide, comment se fait-il que d'autres personnes peuvent utiliser ce PA sans erreur (je l'ai même fait essayer par un ami sur son ordinateur portable sous SUSE et: « sur cette machine, ça marche sans problème ».)

Nous avons besoin de creuser un peu plus. A ce stade, comme il se trouve que j'avais laissé tomber la liste de la messagerie électronique concernant ce problème, je vais revenir aux délibérations du Gang en cours. D'après Kapil'Hari Paranjape, mon tcpdump était en train de capturer une session zeroconf. Voilà l'explication :

Sous zeroconf (RFC 3927) deux machines peuvent s'interconnecter si elles utilisent des adresses dans la plage 169.254.0.0/16. Donc ce qui se passe peut-être :

  1. Le point d'accès essaye de communiquer avec vous en utilisant zeroconf

  2. Si vous établissez un lien zeroconf, il a besoin ensuite d'informations d'authentification.

  3. Au moment de l'authentification, il fournit une adresse DHCP « réelle ».

Donc, vous devez autoriser DHCP à échouer et ensuite établir une adresse zeroconf choisie « au hasard ». (le paquet zeroconf de Debian fait ça).

Ce que je dis sur « l'authentification » semble s'appliquer aux systèmes qui ne sont pas complètement ouverts. Les aéroports par exemple font souvent payer pour la connectivité à une page Web. Vous obtenez alors une IP temporaire via zeroconf, pour aller ensuite où vous voulez avec votre navigateur. Cette requête est redirigée à la page « payez d'abord ». Une fois que vous avez payé, vous obtenez une adresse IP « réelle » et vous êtes sur le Net.

À ce stade, j'ai commencé à regarder le support Debian pour zeroconf. Il s'avère que tout zeroconf est seulement en état « instable » et je préfère ne pas l'utiliser. La Debian stable possède un outil « zcip » qui est censé s'occuper précisément de ce problème; je l'ai donc installé.

Mais en vain. J'ai pu aller un peu plus loin et j'ai eu une « vraie » adresse IP mais je n'ai pas pu accéder au monde extérieur. Si proche...

Worldcon

Arrivé là, d'après le Gang, j'étais dans un café vraiment mal équipé et le mieux était d'aller bosser ailleurs. En plus, c'est à ce moment-là que je suis parti en vacances à la World Science Fiction Convention d'Anaheim en Californie. J'ai fait une première escale à l'aéroport de Salt Lake City qui a un réseau WiFi ouvert. Il faut payer pour l'utiliser mais j'ai pensé que je pouvais au moins tester la partie connectivité.

Et figurez-vous que sur ma machine, ça a marché pile comme il faut . Ça, ça m'énerve.

J'ai refait l'expérience sur le réseau WiFi de l'hôtel et ça a encore marché.

À ce stade, j'ai réalisé que mon but était atteint : je pouvais me connecter à des PA WiFi ouverts. C'est vrai, il y avait le cas isolé de ce café auquel je ne pouvais pas me connecter, mais apparamment c'était leur problème. Ou peut-être juste un support incomplet de Zeroconf sur Debian.

J'ai aussi pu mobiliser un ingénieur réseau local pour m'aider; il est allé à ce café avec son ordinateur Linux. Sa connexion a échoué également, ce qui m'a conforté dans l'idée que c'était bien le PA qui posait problème. Bien que cela pourrait être instructif de m'acharner sur ce PA jusqu'à ce que je comprenne ce qu'il se passe, ce n'était pas le but que je m'étais fixé au départ.

C'est au pied du mur...

... qu'on voit le maçon. Mon copain, le gars du réseau, m'a recommandé un autre café qu'il utilise régulièrement. Et figurez-vous que ça a marché.

Alors voilà le journal qui montre mon résultat final:

De /var/log/deamon.log:

localhost cardmgr[1239]: + Internet Systems Consortium DHCP Client V3.0.1
localhost cardmgr[1239]: + Copyright 2004 Internet Systems Consortium.
localhost cardmgr[1239]: + All rights reserved.
localhost cardmgr[1239]: + For info, please visit http://www.isc.org/products/DHCP
localhost cardmgr[1239]: + 
localhost cardmgr[1239]: + wifi0: unknown hardware address type 801
localhost cardmgr[1239]: + wifi0: unknown hardware address type 801
localhost cardmgr[1239]: + Listening on LPF/wlan0/00:50:f2:c3:aa:07
localhost cardmgr[1239]: + Sending on   LPF/wlan0/00:50:f2:c3:aa:07
localhost cardmgr[1239]: + Sending on   Socket/fallback
localhost cardmgr[1239]: + DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 3
localhost cardmgr[1239]: + DHCPOFFER from 192.168.0.1
localhost cardmgr[1239]: + DHCPREQUEST on wlan0 to 255.255.255.255 port 67
localhost cardmgr[1239]: + DHCPACK from 192.168.0.1
localhost cardmgr[1239]: + bound to 192.168.0.4 -- renewal in 982546229 seconds.

Et l'enregistrement Tcpdump.log:


tcpdump: WARNING: Promiscuous mode not supported on the "any" device
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 96 bytes
18:43:38.008431 IP (tos 0x0, ttl  32, id 33709, offset 0, flags [DF], length: 576) 192.168.0.1.bootps > 192.168.0.4.bootpc: BOOTP/DHCP, Reply, length: 548, xid:0xfbfc2356, flags: [none]
Your IP: 192.168.0.4
Client Ethernet Address: 00:50:f2:c3:aa:07
sname "M-^?" [|bootp]
18:43:38.017371 IP (tos 0x0, ttl  32, id 32941, offset 0, flags [DF], length: 576) 192.168.0.1.bootps > 192.168.0.4.bootpc: BOOTP/DHCP, Reply, length: 548, xid:0xfbfc2356, flags: [none]
Your IP: 192.168.0.4
Client Ethernet Address: 00:50:f2:c3:aa:07
sname "M-^?" [|bootp]

2 packets captured
2 packets received by filter
0 packets dropped by kernel

Quelques réflexions pour finir

Au départ, je n'avais pu me connecter à aucun des nombreux PA que j'avais essayés. Ensuite, celui que j'avais choisi pour une session de débogage concentrée s'est avéré être mal configuré. Mais finalement, j'ai réussi à tout faire marcher et la prochaine fois qu'un PA ouvert me fait échec, je saurai que ce n'est pas ma faute. Plus important, je saurai ce qu'il faut faire pour voir ce qu'il se passe et j'aurai de bonnes chances de réparer ça.

Mais cela est une illustration de certaines particularités de la communauté Linux et de la communauté des logiciels libres en général. L'avantage le plus évident est l'existence de groupes tels que The Answer Gang. Alors qu'il n'y a aucune garantie que quelqu'un vous aide sur votre problème particulier, c'est bien plus probable que ça arrive qu'avec n'importe quel produit propriétaire, même si vous payez pour le support technique.

Une autre différence importante est la transparence de Linux par rapport aux autres. J'ai pu facilement tracer l'activité du noyau à partir du moment où j'ai inséré la carte PCMCIA jusqu'au moment où j'ai obtenu mon adresse IP réelle. Je suis également persuadé que ce niveau de transparence est toujours disponible puisque j'ai le code source de n'importe quel bit de logiciel utilisé. L'accès aux sources peut ne pas être une aide pour ceux qui ne sont pas programmeurs mais ajouter simplement des instructions kprintf a un pilote n'est vraiment pas une tâche si ardue que ça. Cette liberté me permet d'ajouter de la transparence là où rien n'existait auparavant.

Et enfin, je pense que vous devez reconnaître combien la puissance du choix est importante quand on débogue. A chaque étape, je pouvais choisir parmi plusieurs outils à utiliser. Quand iwlist ne me convenait pas, je pouvais facilement prendre Kismet à la place.

Je ne remercierai jamais assez The Answer Gang pour leur aide. Je les remercierai donc en aidant à mon tour les autres, comme l'a préconisé Robert Heinlein avec son « pay it forward ». Donc, j'espère que la prochaine personne qui a ce type de problème trouvera mon article et l'aide dont elle a besoin.

À propos de l'auteur

Jeff Root

Le premier ordinateur de Jeff Root a été un IBM System 3, programmé en FORTRAN IV avec des cartes perforées de 64 colonnes. Son premier amour a été son Apple ][e, qui est encore occasionellement utilisé aujourd'hui. Jeff n'a jamais appris le BASIC, car il prefére le « pas le droit à l'erreur » du langage machine.

Jeff a commencé à utiliser Linux avec Yggdrasil, une distribution uniquement utilisable à partir du CD à l'époque du noyeau 1.1.13. Une nécéssité, puisque l'ordinateur de Jeff n'avait pas de disque dur. Il est maintenant un fanatique du système Debian GNU/Linux mais garde sous le coude une clé Damn Small Linux

Il travaille actuellement comme programmeur pour un fabricant de de semiconducteurs à Pocatello, Idaho. Dans une vie antérieure il a testé des bombardiers pour l'USAF.

Adaptation française de la Gazette Linux

L'adaptation française de ce document a été réalisée dans le cadre du Projet de traduction de la Gazette Linux.

Vous pourrez lire d'autres articles traduits et en apprendre plus sur ce projet en visitant notre site : http://www.traduc.org/Gazette_Linux.

Si vous souhaitez apporter votre contribution, n'hésitez pas à nous rejoindre, nous serons heureux de vous accueillir.