Les bornes
Les bornes WiFi sont des Linksys WRT54G. Ce sont des bornes très utilisées car Linksys a accepté d'en libérer le firmware (logiciel embarqué) sous GPL. Il est donc possible de modifier entièrement le fonctionnement de celles-ci. Le système d'exploitation utilisé est une version embarquée de Linux. Les possibilités sont donc infinies.
Chaque borne dispose d'une interface WiFi et de cinq interfaces filaires. Elles sont configurées comme un switch.
Nous nous sommes basés sur la version whiterussian du firmware Open WRT. Ce firmware est libre et très modulaire. On utilisait auparavant un firmware basé sur la version Alchemy de Sveasoft. Cf ../MigrationVersOpenWrt pour les raisons du changement et les différences.
Par rapport au firmware d'origine de Linksys, on notera les changements suivants :
Changement total de l'architecture (cf ../MigrationVersOpenWrt)
- Un serveur SSH a été ajouté et nous sert à nous connecter sur la borne pour effectuer certaines opérations de maintenance. L'identification se fait uniquement à l'aide de clefs. La borne ne contient alors aucune donnée secrète et un vol n'apportera donc aucune information à l'attaquant.
Pour se connecter depuis ragnarok.crans.org, il suffit de faire :
ssh -i /etc/wifi/ssh/wifi valhalla.wifi.crans.org
Un client HTTP SSL permettant d'effectuer les mises à jour (cf ../OpenBsd). Il y a également un certain nombre de démons que l'on décrira plus loin : un proxy ARP, un proxy DHCP et un proxy DNS.
- Le serveur Web embarqué à l'origine n'est plus présent ainsi que la plupart des autres services, comme par exemple le serveur TFTP qui permettait de mettre à jour la borne à distance. Cela signifie que la seule interface d'administration restante est le serveur SSH et le client SSL wifi-update.
- Le noyau a été modifié pour inclure les possibilités de bridge
filtrant à la borne (avec les patchs bridge-nf). De nombreux moteurs et cibles ont été rajoutés à netfilter.
Les applications supplémentaires
Des applications spécifiques au Cr@ns ont été développées pour les bornes. Nous allons les décrire brièvement.
Wifi-update
Les bornes disposent d'un client SSL HTTP qui leur permet de récupérer les mises à jour. Cette application fait appel à la librairie MatrixSSL qui est une implantation embarquée du protocole SSL. Les bornes disposent d'un certificat permettant de vérifier qu'elles discutent bien avec Ragnarok.
Cette application est programmée en C et n'effectue aucune allocation dynamique : elle ne dispose donc pas de fuites mémoires qui risqueraient de la faire planter. Tous les cas d'erreur sont de plus testés et une erreur de communication entraîne rupture puis tentative de reconnexion. Les scripts qui prennent trop de temps à s'exécuter sont de plus arrêtés sauvagement. La sortie des scripts sont remontés via syslog à ragnarok.
Toutes les minutes, ce client va interroger le serveur sur la présence d'une nouvelle mise à jour. Le serveur étant un serveur Web classique, il sait déjà indiquer s'il existe une mise à jour plus récente que la dernière mise à jour obtenue.
Plus de renseignements sur ../OpenBsd.
Le processus s'appelle wifi-udpdate et prend le nom de la machine distribuant la mise à jour.
Le proxy ARP
Afin de répondre aux exigences de sécurité concernant le déni de service, présentées dans la page dédiée à la ../SécuritéWifi, une application permettant de filtrer les requêtes ARP a été développée. Nous verrons plus loin que le firewall ne laisse pas passer les requêtes ARP. Nous disposons à la place d'une application qui écoute sur chacune des interfaces et relaie les requêtes ARP d'une interface à l'autre après les avoir vérifiées. Elle dispose également d'une protection contre le flood et d'une vérification du sens des requêtes.
Cette application lit la correspondance MAC/IP à partir d'un fichier envoyé par wifi-update à la borne. Elle est programmée en C et les allocations dynamiques sont strictement contrôlées. Toutes les erreurs sont traitées au mieux. Cette application utilise directement les Linux Socket Filter (LSF) ce qui lui permet d'être particulièrement efficace et économe en mémoire.
Il fait également office de proxy ARP : comme les clients ne doivent parler qu'avec le routeur, si une requête ARP se pointe et qu'elle n'initie pas un lien entre un client et le routeur (ou l'inverse), elle est altérée de façon à rediriger le client vers le routeur (qui transmettra). Ainsi, le router peut appliquer la politique de sécurité, même quand deux clients discutent entre eux.
Le processus s'appelle arp-forwarder. Il prend deux arguments au moins, l'interface fil et l'interface sans-fil (dans cet ordre).
Enfin, elle s'occupe également de remettre en place le lien wifi s'il tombe.
Le proxy DHCP et DNS
Le proxy DHCP interroge directement ragnarok et relaie sa réponse aux clients concernés. Il s'agit de dhcp-forwarder. Il n'est pas aussi complet que dhcrelay (issu de ISC), mais il est beaucoup plus léger. Le processus s'appelle dhcp-fwd.
Le proxy DNS est le programme DNSmasq configuré pour toujours renvoyer l'adresse IP de ragnarok. Ainsi, toute requête en clair donnera l'IP de Ragnarok.
Le processus s'appelle dnsmasq. Voir la page de man associée.
Un agent d'authentification
Chaque borne dispose également d'un agent d'authentification chargé d'expulser les utilisateurs non reconnus sur la base de l'adresse MAC. Cette fonctionnalité n'apporte aucune sécurité (puisqu'il suffit de spoofer une adresse MAC connue), mais elle permet de savoir facilement quand une borne reconnaît un utilisateur.
Le processus s'appelle auth-mac. Il prend comme argument l'interface wifi.
Il permet également de remonter des informations sur les clients autorisés : régulièrement, il écrit dans le fichier /tmp/auth-mac.dump les couples client-RSSI.
Un processus pour choisir la fréquence
Afin de réduire la difficulté de la configuration des bornes en ce qui concerne l'épineux choix de la fréquence, chaque borne scanne régulièrement les alentours pour trouver une fréquence de libre. C'est le processus channel-chooser qui s'occupe de ça. Il respecte la distance impérative des 4 canaux et élimine les bornes trop éloignées si aucune fréquence n'est disponible. Il se lance en donnant deux arguments : l'interface wifi et un entier codant l'ensemble des canaux qu'il peut choisir : 8191 pour tous les canaux (c'est un champ de bits).
Les résultats sont remontés par syslog, ce qui permet en plus de cartographier de manière basique les alentours de la borne et ainsi détecter les bornes "pirates" ou les bornes de l'ENS.
Le processus est normalement conçu pour converger vers l'utilisation des fréquences 1, 5, 9 et 13 (il leur donne la priorité sur les autres fréquences). La priorité est donnée à la fréquence actuelle. Il est également possible de restreindre le spectre des fréquences que la borne peut choisir.
Voici le résultat du processus dans une zone encombrée :
Apr 11 16:18:15 freya.wifi.crans.org channel-chooser[236]: Found SSID "abc" on channel 1, RSSI : -85 dBm Apr 11 16:18:15 freya.wifi.crans.org channel-chooser[236]: Found SSID "Cr@ns" on channel 1, RSSI : -91 dBm Apr 11 16:18:15 freya.wifi.crans.org channel-chooser[236]: Found SSID "Cr@ns" on channel 1, RSSI : -91 dBm Apr 11 16:18:15 freya.wifi.crans.org channel-chooser[236]: Found SSID "Cr@ns" on channel 5, RSSI : -72 dBm Apr 11 16:18:15 freya.wifi.crans.org channel-chooser[236]: Found SSID "Cr@ns" on channel 5, RSSI : -82 dBm Apr 11 16:18:15 freya.wifi.crans.org channel-chooser[236]: Found SSID "Cr@ns" on channel 9, RSSI : -77 dBm Apr 11 16:18:15 freya.wifi.crans.org channel-chooser[236]: Found SSID "Cr@ns" on channel 13, RSSI : -88 dBm Apr 11 16:18:15 freya.wifi.crans.org channel-chooser[236]: Current channel : 1 ; choosen channel : 13
- Aucune fréquence n'était disponible. Les bornes avec un RSSI inférieur à -90 dBm ont été écartées et le canal 13 a été le premier disponible. La borne a donc changé de canal.
Les bornes étant plus sensibles que les cartes wifi, elles sont capables de voir au-delà de leur radius effectif. Ainsi, on peut penser que l'on prend en compte les recouvrements partiels de zones.
Sortie de ps
Voici la sortie de ps sur une des bornes (en mode hotspot) :
root@audhumla:~# ps PID Uid VmSize Stat Command 1 root 380 S init 2 root SW [keventd] 3 root RWN [ksoftirqd_CPU0] 4 root SW [kswapd] 5 root SW [bdflush] 6 root SW [kupdated] 7 root SW [mtdblockd] 32 root SWN [jffs2_gcd_mtd4] 53 root 424 S syslogd -C 16 -L -R 138.231.148.1 55 root 328 S klogd 58 root 544 S /bin/ash --login 557 nobody 368 S /usr/sbin/dnsmasq -A /#/138.231.148.1 -h -R -i br0 572 root 424 S /usr/sbin/dropbear -s 583 root 388 S /usr/sbin/crond 600 root 368 S /usr/bin/arp-forwarder -l vlan3 -w eth1 -N 138.231.14 609 root 348 S /usr/bin/arp-forwarder -l vlan4 -w wl0.1 -N 10.231.14 620 root 324 S /usr/bin/auth-mac -i eth1 -H 631 dhcp-fwd 304 S dhcp-fwd -c /tmp/dhcp-fwd.conf 642 dhcp-fwd 304 S dhcp-fwd -c /tmp/dhcp-fwd-hotspot.conf 655 root 496 S /usr/bin/wifi-update wifi-update.crans.org 1315 root 380 R ps
Le firewall
Les bornes disposent en interne d'un firewall. Elles agissent comme un pont filtrant, c'est à dire comme un équipement de niveau~1 mais capable de comprendre les niveaux supérieurs. C'est une fonctionnalité rendue possible par le patch bridge-nf sur les noyaux Linux.
Par défaut, aucune requête n'est autorisée à traverser le pont. Au niveau 1, les actions suivantes sont menées :
- tous les paquets multicast sont jetés,
- tous les paquets non IP sont jetés,
- pour les paquets IP restant, on vérifie l'adresse MAC cible (qui doit être celle du routeur ou non selon le sens du paquet)
Le fait de ne laisser passer que les paquets IP nous assurent que ceux-ci circuleront dans la table FORWARD de Netfilter et pourront donc être filtrés par celui-ci.
Au niveau 2, l'idée est de s'assurer que seuls les flux depuis et vers le routeur sont autorisés. On effectue le maximum de vérification sur ce point pour éviter que quelqu'un ne viole cette politique de sécurité (implantée en partie au niveau 1). Schématiquement, le firewall est le suivant :
- les paquets ESTABLISHED ou RELATED sont acceptés,
la correspondance MAC-IP est vérifiée pour la source1,
- toutes les communications DNS sont redirigées sur le serveur local.
Le firewall fait appel à certaines fonctions avancées comme la possibilité de choisir l'interface du bridge avec l'extension physdev, la possibilité de gérer des ensembles avec l'extension ipset.
Voici le contenu du firewall une fois initialisé. Il n'est pas bien gros car les bornes ne sont pas très puissantes. Il s'assure juste que tout passe par le routeur qui, lui, va appliquer la politique de sécurité. On pourra consulter l'historique de cette page pour un firewall plus complet qui était utilisé auparavant.
Table filter
Chain FORWARD (policy DROP) target prot opt source destination ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED LAN2WIFI all -- anywhere anywhere PHYSDEV match --physdev-in vlan3 --physdev-out eth1 WIFI2LAN all -- anywhere anywhere PHYSDEV match --physdev-in eth1 --physdev-out vlan3 LAN2WIFI_HOTSPOT all -- anywhere anywhere PHYSDEV match --physdev-in vlan4 --physdev-out wl0.1 WIFI2LAN_HOTSPOT all -- anywhere anywhere PHYSDEV match --physdev-in wl0.1 --physdev-out vlan4 Chain LAN2WIFI (1 references) target prot opt source destination DROP all -- anywhere anywhere MAC ! 00:0C:F1:FA:F1:4B ACCEPT all -- anywhere anywhere Chain LAN2WIFI_HOTSPOT (1 references) target prot opt source destination DROP all -- anywhere anywhere MAC ! 00:0C:F1:FA:F1:4B ACCEPT all -- anywhere anywhere Chain OUTPUT (policy ACCEPT) target prot opt source destination DROP all -- anywhere anywhere state INVALID ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED Chain WIFI2LAN (1 references) target prot opt source destination DROP all -- anywhere anywhere MAC 00:0C:F1:FA:F1:4B DROP all -- anywhere anywhere !set mac-ip src ACCEPT all -- anywhere anywhere Chain WIFI2LAN_HOTSPOT (1 references) target prot opt source destination DROP all -- anywhere anywhere MAC 00:0C:F1:FA:F1:4B ACCEPT all -- 10.231.148.1 anywhere MAC 00:0C:F1:FA:F1:4B ACCEPT all -- !10.231.148.1 anywhere MAC ! 00:0C:F1:FA:F1:4B DROP all -- anywhere anywhere
Table nat
Principalement pour rediriger les requêtes DNS
Chain PREROUTING (policy ACCEPT) target prot opt source destination REDIRECT udp -- 138.231.148.0/22 anywhere PHYSDEV match --physdev-in eth1 udp dpt:53 redir ports 53
Description des fichiers importants
Les fichiers de init.d
Ils sont lancés dans l'ordre. Une partie n'est présente qu'après la première mise à jour.
/etc/init.d/S50dropbear : démarrage du serveur SSH
/etc/init.d/S41hotspot : mise en place de l'interface hotspot
/etc/init.d/S45firewall : lancement d'un firewall minimaliste
/etc/init.d/S46firewall : démarrage du firewall "complet"
/etc/init.d/S70auth-mac : lancement de auth-mac
/etc/init.d/S80wifi-update : lancement de wifi-update
/etc/init.d/S10boot : construction du système de fichiers la première fois
/etc/init.d/S70arp-forwarder : lancement de arp-forwarder
/etc/init.d/S65cron : mise en place du cron
/etc/init.d/S05nvram : initialisations de certaines variables NVRAM propres à OpenWRT (cf ../VariablesNvram)
/etc/init.d/S11nvram : initialisation des variables NVRAM propres au CRANS (cf ../VariablesNvram)
/etc/init.d/S70dhcp-fwd : lancement du relai DHCP
/etc/init.d/S99done : fin du boot (on éteint la led)
/etc/init.d/S60ntpclient : mise à l'heure
/etc/init.d/S40network : initialisation du réseau
/etc/init.d/S50dnsmasq : lancement de DNSmasq
/etc/init.d/S90prompt : mise en place du prompt avec IP et nom.
Le reste
/etc/nvram.updates : utilisé par /etc/init.d/S11nvram pour mettre à jour la NVRAM
Les sources
Le firmware pour le CRANS, issu de whiterussian est dispo dans la branche tla bernat@luffy.cx--2005-public/wrt54g--crans--1
Cela se compile comme ça :
$ make cransconfig $ make
Le firmware est ensuite le fichier bin/openwrt-wrt54g-squashfs.bin ou bin/openwrt-brcm-2.4-squashfs.trx (le premier sert pour le serveur TFTP au boot, le second pour l'outil mtd).
Installer le firmware
Le firmware se trouve généralement dans //mnt/firmware-wifi/wrt54g--crans--1--patch-146/bin/openwrt-wrt54g-squashfs.bin sur zamok.
La première fois
L'installation du firmware la première fois se fait par tftp, une fois la borne bootée (on utilise donc le serveur TFTP inclus dans le firmware standard et non celui du loader car par défaut, il n'attends pas). On doit utiliser le client TFTP modifié par linksys.
- Attendre que la borne ait bootée
- Se configurer avec l'IP 192.168.1.2
- Envoyer le firmware :
$ ./linksys-tftp 192.168.1.1 linksys-tftp> trace linksys-tftp> put firmware.bin admin
La borne reboote en tant que non-configure.wifi.crans.org (il ne faut pas la débrancher)
- Elle reboote de nouveau sous son nom
Se connecter en ssh dessus et supprimer le fichier /etc/lastupdate (elle sera à jour plus rapidement) ou alors faire un touch /var/www/wifi-update/<nom de la borne>.wifi.crans.org.tar.gz
Une autre solution
La solution est d'utiliser l'interface web de la borne, il suffit de se mettre en 192.168.1.2 et se connecter sur 192.168.1.1 une fois que la borne a booté. Le login par défaut est vide et le mot de passe est admin.
Si le flashage foire vraiment
Par la suite
Il faut utiliser le script /etc/wifi/scripts/update-borne.py. Il faut se placer dans le répertoire qui contient le firmware (important). Voici un exemple d'utilisation :
for b in audhumla valhalla var vor thrud; do python /etc/wifi/scripts/update-borne.py openwrt-brcm-2.4-squashfs.trx $b.wifi.crans.org \ '#1 sam sep 24 13:22:24 CEST 2005' & done ; wait
Cela met à jour plusieurs bornes en même temps. Il faut utiliser le .trx et non le .bin !
Le dernier argument du script est le résultat de uname -v. Cela permet de ne pas mettre à jour une borne qui l'est déjà. Le script refuse de mettre à jour une borne s'il y a des clients dessus.
En cas de problèmes
Si un firmware est mal flashé, on peut le remettre comme si c'était la première fois, sauf que la commande put doit être envoyée au démarrage de la borne (on utilise le serveur TFTP du loader). Il suffit d'appuyer sur entrée quand la LED indiquant la présence du lien réseau entre la borne et le portable qui flashe la borne s'allume.
Un tournevis peut aussi être utile en dernier recours.
Si elle ne réponds jamais au pings sous le petit nom de 192.168.1.1 (c'est a dire que le bootloader n'attends pas) se référer a la page http://wiki.openwrt.org/OpenWrtDocs/Troubleshooting sachant que nous n'avons pas d'interface JTAG
1 Cette fonctionnalité utilise ipset qui permet de faire de manière très rapide cette correspondance MAC-IP.








