Mes bornes Wi-Fi avaient tout vu ; leur filtre niait les faits
RouterOS sort du radiotap et des codes de raison depuis la radio en service ; son filtre de deauth, lui, sait surtout produire un silence très convaincant.
Ethernet a rendu le diagnostic réseau presque civilisé. On branche un analyseur, on capture des paquets, on suit une conversation. Le Wi-Fi a repris la même idée en ajoutant des canaux, des puissances, des retransmissions, des trames de gestion et des clients qui peuvent décider de partir sans déposer de préavis.
Une fois la trame 802.11 acceptée par le point d’accès, déchiffrée et livrée au réseau local, une grande partie de cette histoire disparaît. Le sniffer du routeur voit alors de l’Ethernet propre. Il peut prouver qu’un paquet IP est passé ; il ne sait plus dire si la station s’est désassociée, si la borne l’a chassée ou si l’échange de clés s’est arrêté au milieu.
C’est pour conserver ces informations que les captures Wi-Fi utilisent notamment le pseudo-en-tête radiotap : canal, débit, puissance et autres métadonnées radio précèdent la trame 802.11. Wireshark en expose aujourd’hui une collection assez généreuse. La méthode habituelle consiste donc à trouver une carte compatible avec le mode moniteur, négocier avec son pilote, la caler sur le bon canal et la poser au bon endroit. Le sans-fil retrouve ainsi une propriété historique de l’informatique : pour diagnostiquer le matériel que l’on possède déjà, il faut d’abord acheter un autre matériel.
J’allais précisément commander un adaptateur USB quand une commande RouterOS a rendu l’achat beaucoup moins urgent.
Le mauvais sniffer disait vrai
Mon réseau utilise trois MikroTik cAP ax cAPGi-5HaxD2HaxD, relevés en RouterOS 7.22.3, 7.21.4 et 7.21.1. Trois versions pour trois machines identiques : la reproductibilité commence par une collection. Deux radios sont pilotées localement, la troisième par CAPsMAN. Je cherchais pourquoi certains clients changeaient mal de borne. La donnée décisive était un code de raison 802.11, pas un ping qui reprendrait après la bataille.
Le premier outil essayé, /tool/sniffer, confirmait la documentation et mon pessimisme. Même lancé sur l’interface Wi-Fi, il produisait des charges déchiffrées présentées comme de l’Ethernet. Aucune balise, aucune authentification, aucune désassociation. Le sniffer n’était pas cassé ; il répondait parfaitement à une question située une couche trop haut.
La famille moderne de pilotes wifi-qcom porte pourtant un second outil :
/interface/wifi/sniffer wifi1 duration=25s pcap-file=radio.pcap
Le fichier rapatrié a tranché immédiatement :
pcap capture file — 802.11 with radiotap header
On y trouvait des balises, des probes, RTS, CTS, block acknowledgements, des trames trigger 802.11ax, et surtout les trames de gestion que l’autre capture avait proprement repassées. La documentation MikroTik dit bien que ce renifleur place l’interface en réception passive, reste sur son canal configuré et peut écrire un PCAP ou diffuser en TZSP. J’avais lu « packet sniffer » dans un menu, conclu qu’il n’existait qu’un packet sniffer, et failli acheter du matériel pour compenser mon sens de la navigation.
Vingt-cinq secondes et une raison 3
Une capture de vingt-cinq secondes sur la radio 2,4 GHz a rendu 64 trames : vingt probes, dix-neuf charges QoS, vingt-quatre null-data de veille et une deauthentication. Cette dernière portait :
wlan.fixed.reason_code = 0x0003
signal = -57 dBm
Raison 3 : la station quitte l’ESS. Au même instant, le compteur de clients est passé de quatre à trois, puis revenu à quatre. La borne n’avait pas expulsé un objet moribond ; l’objet avait annoncé son départ, avec une puissance tout à fait honorable. Le problème n’était donc pas un trou radio au moment observé.
Cette seule trame valait davantage que plusieurs heures de journaux « client disconnected » : elle disait qui avait pris l’initiative. Et elle avait été capturée par la borne en train de servir les autres clients, sans changement de canal ni coupure visible.
Sur la radio 5 GHz, le débit était nettement moins contemplatif : environ 15 000 trames par seconde et 70 Mbit/s dès qu’un transfert circulait. Le radiotap conservait dbm_antsignal, channel.freq et datarate. La capture entendait aussi les autres cellules du même réseau sur le même canal, ainsi qu’une adresse localement administrée à −37 dBm : un appareil non associé, très proche, sous MAC aléatoire.
La borne savait donc répondre à deux questions que j’avais rangées dans la colonne « adaptateur externe » : pourquoi une station part, et qui sonde à proximité. Il restait à éviter qu’une réponse de douze secondes pèse cent mégaoctets.
TZSP, ou le tuyau d’incendie sur UDP/37008
stream-address envoie les trames à distance en TZSP, sur UDP/37008 par défaut. Dans une mesure réelle, douze secondes ont produit 112 609 datagrammes et 105,8 Mo, soit environ 70 Mbit/s. Une fonction de surveillance permanente venait d’être découverte ; elle avait simplement le débit d’un flux vidéo pour signaler qu’un téléphone avait envoyé un probe.
Le paquet TZSP est heureusement sobre. Un en-tête de quatre octets précède des étiquettes terminées par TAG_END, puis commence le radiotap brut :
01 00 00 7e | 00 00 00 01 | 00 00 30 00 6f 08 00 40
^ TZSP ^ étiquettes ^ radiotap v0, longueur 48
Un petit récepteur peut donc retirer l’enveloppe, écrire un PCAP DLT_IEEE802_11_RADIO et laisser tshark faire le travail sérieux. Le témoin a converti 24 588 trames ; types, canaux et puissances ont survécu. Le format n’était pas seulement reconnu par file, il restait exploitable après le transport.
RouterOS propose stream-rate, mais il borne des paquets par seconde sans choisir lesquels méritent de survivre. La vraie solution devait être le filtre sur la borne : conserver associations, authentifications, actions, probes et déconnexions ; jeter le torrent de données et d’acquittements.
Le filtre qui se trompe en silence
Le paramètre filter accepte une chaîne. Sa grammaire ressemble assez à libpcap pour inspirer confiance et assez peu à libpcap pour faire perdre une après-midi. type mgt et subtype beacon étaient acceptés sans erreur mais ne rendaient rien. size>0, qui aurait constitué une tautologie dans une autre grammaire RouterOS, se taisait aussi.
Le piège n’était pas seulement syntaxique. Un filtre faux sur un canal vivant et un filtre juste visant un événement rare produisent exactement le même résultat : aucun paquet. L’absence, cette grande imitatrice de la réussite.
Le bon protocole d’essai consistait à commencer par un événement abondant. beacon ne rendait que les balises ; probe-req que les probes ; data, ack, rts, cts et block-ack isolaient chacun leur famille. La grammaire, les opérateurs ==, !=, &&, || et les champs d’adresse étaient donc bien actifs.
J’ai ensuite composé le filtre séduisant :
filter="deauth || disassoc || assoc-req || assoc-resp || auth || probe-req || action"
Six secondes sans filtre rendaient 848 trames. Avec lui : zéro. Première lecture, optimiste : ces événements sont rares. Quelques jours plus tard, une deauthentication injectée depuis une carte en mode moniteur a fourni le témoin qui manquait. Sans filtre, la borne l’a entendue 80 fois sur 80 à −60 dBm. Avec filter=deauth, zéro. Au même instant, filter=beacon rendait 165 trames.
Le mot-clé deauth était donc un non-correspondant silencieux. Le paquet existait, le capteur le voyait, le filtre l’effaçait, et aucun message ne distinguait cette situation d’une soirée paisible. Les autres mots rares de la composition n’ont pas tous été éprouvés contre un événement positivement présent ; ils ne peuvent donc pas encore porter une surveillance fiable.
La leçon n’est pas « testez vos filtres », phrase que l’on pourrait imprimer sur un mug sans aider personne. Le détail à retenir est plus utile : sur les cAP ax et versions RouterOS mesurées, beacon et probe-req correspondent, mais deauth ne correspond pas même face à une trame injectée et reçue. Une capture non filtrée autour de l’incident reste nécessaire pour les codes de raison.
Voir ailleurs exige de couper ici
Le renifleur a une limite physique rassurante : il reste sur le canal de service. Il ne voit pas les voisins sur les autres canaux et ne capture pas les propres émissions de la radio. Il écoute beaucoup, pas l’univers entier.
RouterOS fournit d’autres instruments. flat-snoop balaie les fréquences et rend points d’accès et stations, avec signal, bruit, SNR, méthodes d’authentification, suites cryptographiques et drapeau d’adresse localement administrée. spectral-scan rend des bins de 5 MHz avec MAGN et PEAK en dBm ; spectral-history dessine la même matière en cascade ASCII. C’est un petit laboratoire radio déjà vissé au plafond.
Mais une radio qui balaie ne sert plus ses clients. La facture a été mesurée sur quatre objets connectés :
| Outil | Chute observée | Retour complet |
|---|---|---|
flat-snoop |
4 → 0 | environ 80 s |
spectral-history |
3 → 0 | environ 20 s |
spectral-scan |
4 → 3 | environ 80 s |
Rien n’est resté cassé. Cela ne transforme pas ces commandes en tâches de fond : ce sont des mesures que l’on décide de payer. Le sniffer, lui, n’a déconnecté aucun client pendant les captures. Sur la borne gérée à distance par CAPsMAN, la commande locale répondait simplement failure: not allowed malgré un compte doté de la politique sniff ; les deux bornes à gestion locale acceptaient.
Le matériel que je n’ai finalement pas économisé
Les coordonnées utiles tiennent sur quelques lignes :
outil /interface/wifi/sniffer, pas /tool/sniffer
sortie PCAP 802.11 + radiotap
flux TZSP sur UDP/37008
portée canal de service, réceptions seulement
filtre fiable éprouver chaque mot contre une trame positivement présente
balayage flat-snoop / spectral-*, avec déconnexion des clients
J’ai obtenu le code de raison recherché sans achat, suivi le flux jusqu’à Wireshark et mesuré le coût exact des outils qui balaient. J’ai aussi découvert qu’un filtre officiellement accepté pouvait supprimer précisément l’événement qu’il prétendait sélectionner. Le réseau n’était pas devenu plus mystérieux ; la syntaxe avait seulement réussi son imitation du calme radio.
L’adaptateur USB garde donc un emploi. Lui seul peut parcourir les canaux sans arracher les clients d’une borne en production, et il fournit les événements nécessaires pour éprouver les filtres de la borne. La bonne nouvelle est que je n’avais pas besoin de l’acheter pour répondre à la question initiale. La mauvaise est que l’infrastructure possédait déjà un excellent analyseur 802.11 et avait choisi de le ranger à une commande de distance du sniffer portant le nom évident. Même le matériel de diagnostic respecte les traditions de l’interface réseau.