Stéphane.
NetworkArchivé

sKUBE — un routeur de voyage qui met tout le monde derrière un VPN

Un Raspberry Pi à deux radios : point d’accès d’un côté, Wi-Fi du lieu de l’autre, tunnel OpenVPN au milieu. Le routage tenait ; la page qui annonçait « Sécurisé » ne vérifiait rien.

Technologies employées

  • Raspberry Pi 3
  • Raspbian
  • hostapd
  • dnsmasq
  • OpenVPN
  • iptables
  • PHP 5
  • Apache
  • Bootstrap
  • Shell

À l’automne 2016, en parallèle de MyGlassBox, j’ai construit un second objet : un boîtier qu’on emporte en déplacement. On le branche, on s’y connecte, il se raccorde au Wi-Fi de l’hôtel et fait passer tout le trafic dans un tunnel chiffré. Un téléphone, une tablette, un ordinateur portable : tous protégés d’un coup, sans rien configurer sur chacun d’eux. Le routage fonctionnait. La page qui affichait « Sécurisé » en vert, elle, ne vérifiait absolument rien.

Le problème

Sur un réseau public, chaque appareil doit être protégé individuellement : une application VPN sur le téléphone, une autre sur la tablette, une configuration sur l’ordinateur — et un abonnement qui limite souvent le nombre de connexions simultanées. La télévision de la chambre ou la liseuse, elles, n’ont rien du tout.

L’idée de sKUBE est de déplacer le problème d’un cran : protéger le réseau plutôt que chaque appareil. Un seul objet à configurer, un seul tunnel, et tout ce qui s’y connecte en bénéficie sans le savoir.

Deux radios, deux sorties

C’est là que le montage devient intéressant, et c’est la partie que je referais telle quelle.

Routage à deux radios du boîtier sKUBELes appareils du voyageur se connectent au point d’accès du boîtier, porté par sa première radio. Le boîtier se raccorde au Wi-Fi du lieu par sa seconde radio. Le trafic sort alors par deux chemins possibles : soit directement vers ce Wi-Fi, soit à travers un tunnel OpenVPN monté par dessus. Les appareils restent sur le même réseau dans les deux cas.appareils4 clients au plussKUBEwlan0 — point d’accès172.24.1.1wlan1 — client Wi-FiNAT · openvpnWPA2Wi-Fi du lieuhôtel, gare, cafétunnel OpenVPNtun0en clairchiffré, monté par-dessusun seul réseau, quelle que soit la sortie
Les appareils ne changent jamais de réseau : ils restent sur le point d’accès du boîtier. C’est la sortie qui bascule, du lien direct au tunnel.

Le boîtier porte deux interfaces sans fil. La première, wlan0, diffuse son propre réseau : c’est là que se connectent les appareils du voyageur, avec un serveur DHCP limité à quatre adresses et un nom local résolu sur le boîtier lui-même. La seconde, wlan1, se comporte en client ordinaire et rejoint le Wi-Fi de l’hôtel.

Entre les deux, du NAT. Et par-dessus, quand on l’active, un tunnel OpenVPN qui devient la nouvelle sortie.

sKUBE/iptables.txt
iptables -t nat -A POSTROUTING -o wlan1 -j MASQUERADE
iptables -A FORWARD -i wlan1 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i wlan0 -o wlan1 -j ACCEPT

iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -A FORWARD -i tun0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i wlan0 -o tun0 -j ACCEPT

Ce qui compte ici, c’est que les appareils ne changent jamais de réseau. Ils restent sur le point d’accès du boîtier, avec la même adresse et la même passerelle. Activer ou couper le VPN ne provoque aucune reconnexion chez eux : seule la route de sortie change. C’est ce qui rendait l’objet utilisable par quelqu’un qui ne sait pas ce qu’est une table de routage.

La radio qui a coûté le plus cher

Faire d’un Raspberry Pi un point d’accès demande une clé Wi-Fi capable du mode AP. Celle que j’avais utilisait un composant Realtek, et le pilote standard ne savait pas le faire. Il a fallu compiler une version de hostapd distribuée par le fabricant, avec son propre pilote.

Le prix se lit dans la configuration finale.

RéglagePilote standardVersion Realtek retenueCe que cela change
Pilotenl80211rtl871xdrvUn hostapd compilé à la main à installer
Protocolewpa=2 — WPA2 seulwpa=3 — WPA et WPA2Le WPA d’origine redevient accepté
ChiffrementCCMP seulTKIP en appairageTKIP est cassé, et il tire le reste vers le bas
Sortie du cartonFonctionneCompilation avant démarrageImpossible à industrialiser tel quel

Le fichier d’installation garde la trace de l’hésitation : le bloc nl80211 en WPA2 et CCMP y est présent, entièrement commenté, juste sous celui qui a été retenu. J’avais donc écrit la bonne configuration, puis je l’ai désactivée pour que la radio veuille bien démarrer.

C’est un arbitrage que je comprends encore : sans point d’accès, il n’y a pas de produit du tout. Mais il aurait dû mener à un changement de composant, pas à un affaiblissement du chiffrement. Vendre un objet de sécurité dont le propre réseau accepte TKIP est une contradiction dans les termes.

La page qui ne mesurait rien

Le portail de configuration est un site Bootstrap servi par le boîtier : chercher un réseau, s’y connecter, renommer son point d’accès, activer le VPN, consulter l’état.

Page web sur fond gris clair : le logo sKUBE, le mot « Sécurisé » en vert, puis une chronologie avec deux coches vertes indiquant « VPN Connecté — TyphoonVPN » et « Fonction — Liaison chiffrée, déblocage de sites actif », et un bouton orange « Déconnexion ».
La page d’état telle qu’elle s’affichait. Le vert, les coches et le nom du fournisseur : tout y est écrit en dur dans le HTML.

Cette capture est le défaut le plus intéressant du projet. Le fichier qui produit cette page ne contient aucune requête, aucun appel système, aucune vérification : le mot « Sécurisé », les deux coches vertes et le nom du fournisseur sont du texte figé. Les horodatages affichés à côté de chaque étape sont eux aussi écrits en dur.

Autrement dit, l’écran qui devait rassurer l’utilisateur affichait le même message que le tunnel soit monté, tombé ou jamais démarré. Combiné à l’absence de coupe-circuit, cela donne le pire scénario possible pour un objet de ce type : le trafic passe en clair, et l’appareil affirme le contraire.

Les autres faiblesses

Elles sont du même âge et de la même famille que celles de MyGlassBox, avec lequel ce projet partage son plan d’adressage et son installeur.

  • Le script de lancement du tunnel reçoit le nom du fichier de configuration sans aucun échappement et le passe au shell. Le portail écrivant cette valeur, une entrée bien choisie faisait exécuter autre chose.
  • Les identifiants du fournisseur VPN vivent dans un fichier texte, au sein d’une arborescence web dont les droits ont été ouverts en grand par l’installeur.
  • Le compte de service web reçoit sudo sans mot de passe — parce qu’il doit piloter wpa_supplicant, hostapd et OpenVPN. Une liste blanche de quelques commandes aurait suffi.
  • Le script censé remonter le réseau au démarrage est installé dans les services et déclaré au boot… alors que toutes ses lignes sont commentées. Le raccordement automatique après une coupure de courant ne fonctionnait donc pas, et rien ne le signalait.

Le modèle envisagé

Comme pour le miroir, une note de novembre 2016 décrit le modèle visé : du hardware as a service, l’objet vendu avec un abonnement qui finance le service VPN. J’y avais relevé le point qui condamnait l’idée à mon échelle — ce modèle exige d’avancer la fabrication, la distribution et le service pendant des mois avant le moindre équilibre.

Deux images de carte mémoire sont conservées à côté du code. Elles disent bien où en était le projet : un objet qu’on pouvait dupliquer et donner à essayer, pas encore un produit qu’on pouvait vendre.

Enseignements

  1. Protéger le réseau plutôt que chaque appareil reste la bonne idée : un seul point à configurer, et tout ce qui s’y connecte en profite, y compris ce qui n’a pas de client VPN.
  2. Garder les appareils sur un réseau stable et ne faire bouger que la route de sortie : la bascule devient invisible pour l’utilisateur.
  3. Sans coupe-circuit, un tunnel qui tombe ne coupe rien — il laisse repartir le trafic en clair. La règle directe ne doit exister que tant que le tunnel n’est pas exigé.
  4. Un voyant vert écrit en dur est un mensonge : un indicateur d’état doit interroger ce qu’il prétend décrire.
  5. Un composant qui impose d’affaiblir le chiffrement pour fonctionner est à remplacer, pas à accepter — surtout sur un objet vendu pour sa sécurité.
  6. Un service déclaré au démarrage mais dont le contenu est commenté ne provoque aucune erreur : rien ne distingue « ça marche » de « ça ne fait rien ».

sKUBE est le plus court de mes projets de cette période et, curieusement, celui dont je me sers le plus souvent comme référence. Il tient en une idée juste, un routage correct, et une poignée de raccourcis qui suffisent à annuler la promesse du produit. C’est un rappel commode que sur un objet de sécurité, la partie qui ment n’est jamais le chiffrement — c’est ce qu’on affiche autour.