9P, le protocol parfait pour l'IoT
1. Intro

Ceci est la transcription d'un talk donné à l'Open source Expérience 2024 à Paris.
Il fait écho à un article publié dans MISC en 2020: 9P, le protocole parfait pour l’IoT, archivé ici.
Vous pouvez voir la video ici:
ou sur youtube. Vous pouvez télécharger les slides.
2. Plan 9 and Inferno

Je suis content que le speaker d'avant ait parlé de sécurité, et d'interphones qu'on pouvait pirater, parce que moi aussi je vais vous parler de sécurité. Et je vais vous montrer comment 9P peut régler la plupart des problèmes de sécurité de l'IoT.
9P, c’est quoi ?
9P, c’est issu d’un système d’exploitation qui s’appelle Plan 9.
Plan 9, c’est quoi ? C’est un système d’exploitation qui vient des Bell Labs. Bell Labs, c’est… bon, je vous fais un peu d’histoire.
Au début du XXe siècle, Bell avait le monopole du téléphone aux États-Unis. Les États-Unis n’aiment pas les monopoles. Ils ont dit à Bell… L’État américain a fait un procès à Bell, et le résultat de ce procès, c’est que Bell pouvait garder le monopole du téléphone, mais en échange, ils ne devaient pas faire de business en dehors du téléphone.
Ça a marché pendant plusieurs dizaines d’années. Et avec tout le pognon qu’ils avaient grâce à ce monopole, ils ont financé la recherche. Et cette recherche, ça a donné au Bell Labs : le transistor, le laser, Unix, le langage C… C’est là où travaillait Shannon quand il a créé la théorie de l’information. Ils ont 15 prix Nobel, des prix Turing… enfin, c’est un truc de malade. C’est le labo du XXe siècle.
Les gens qui ont fait Unix, au bout de 20-30 ans, se sont dit : « Ok, on a créé Unix sur une machine qui avait 16 ko de RAM[ou 8, je sais plus, enfin un truc ridicule.] Aujourd’hui, ça ne marche plus. Les abstractions qu’on avait, notamment en ce qui concerne le réseau, ne tiennent plus.
Donc ce qu’on veut maintenant, c’est créer un nouveau système d’exploitation. On ne va pas s’embarrasser de rétrocompatibilité POSIX et compagnie. On oublie, et on fait notre système à nous. »
Ils ont quand même gardé certains trucs, mais pas tout. Et donc la tagline, c’était : on veut faire un Unix à partir de plein de petits micro-ordinateurs qui sont partout, plutôt que de créer un système à partir de plein d’Unix, chacun avec leur noyau, leur machin.
Je vous reparlerai de tout ça dans quelques instants.
Si vous voulez une take moderne sur le truc, il y a une étudiante qui a écrit ce texte [Hayes 2024]. Je vous laisse le photographier, copier, machin… Ça explique pourquoi, en 2020, on peut se soucier d’un système qui a été créé dans les années 80.
Et là, vous reconnaissez peut-être Dennis Ritchie et Rob Pike — deux grands ingénieurs de l’époque.
3. In IoT, the S stands for security

Avant de parler de 9P et de comment ça marche, je vais vous parler de l’IoT. Et je vais enfoncer des portes ouvertes en disant que dans l’IoT, il n’y a pas de sécurité. C’est un gros désastre, et il faudrait essayer de régler ce problème-là.
3.1. Mirai

Quand je dis que c’est un désastre, je ne parle pas de nulle part : il y a dix ans, j’étais "cybercop", à l’Unité nationale cyber en France. Et en 2016, est arrivé Mirai. Je sais pas si vous en avez entendu parler ?
Mirai, c’est un gros botnet qui s’installait sur les imprimantes, les routeurs, les caméras… et qui bombardait des cibles avec des paquets non légitimes. Juste pour vous donner une idée : le code source de Mirai est disponible.
Je voulais vous montrer cette partie du code source de Mirai que vous pouvez aller voir : il y a une liste de credentials, et il les essaye un par un. Il y a "root:root", "admin:admin", "root:password", "root:123456", etc. Et juste avec 60 couples login/mot de passe courants, ils ont réussi à créer un botnet de plusieurs centaines de milliers de machines, capable de libérer 1 Tbit/s de puissance de frappe.
Ça, c’est le logo du groupe qui a trouvé Mirai et qui l’a un peu fait tomber. Mais jusqu’en 2018–2019, on avait encore des descendants de Mirai qui étaient actifs. Et si vous croyez que la situation a changé, c’est que vous n’êtes pas au courant. En fait, rien n’a changé du tout.
On peut toujours, soit avec des failles, soit avec des logins par défaut, s’introduire dans ces machines. Bon, maintenant c’est un tout petit peu mieux : la plupart des objets connectés arrivent avec un login qui dépend du client, du numéro de série… mais ce n’est pas beaucoup mieux non plus.
3.2. Typical IoT architecture

Voilà à quoi ressemble une architecture IoT typique.
Comme on a une toute petite machine, on va prendre un petit noyau. Donc on commence à modifier le noyau Linux en enlevant certains composants.
Le problème, c’est qu’à partir de là, on n’est plus dans la mainline. Donc, généralement, il n’y a pas de mises à jour automatiques. Quand il y a une mise à jour du noyau, elle ne s’applique pas à votre truc. Vous avez donc un noyau obsolète.
Même chose pour la libc : glibc fait plusieurs dizaines, voire centaines de mégaoctets. Donc on ne l’utilise pas. On prend musl, qui est plus petite. Mais pour que ça rentre pile-poil, vous la triturez. Et du coup, elle ne peut plus se mettre à jour. Elle est donc obsolète, elle aussi.
Vous avez des credentials par défaut. Et ce qui est horrible dans l’IoT, c’est qu’il faut à tout prix une interface web. Comme la plupart des gens ne savent pas utiliser autre chose, il faut du web, du web, du web.
Donc, vous avez un serveur web. Et ce serveur web, généralement, est privilégié. Pourquoi ? Parce que, comme vous aimez la sécurité, vous lui avez laissé le droit de flasher le firmware de l’appareil. Et pour faire ça, il faut être root.
Mais il n’y a qu’un serveur web possible, donc il est privilégié, et il contient du code applicatif souvent écrit avec les pieds, sous la pression. Résultat : des désastres comme ceux qu’on connaît.
L’IoT, c’est une pile d’erreurs les unes sur les autres. Il suffit d’en compromettre une pour qu’un botnet pénètre et transforme votre device en zombie.
4. Back to 9P
4.1. Three core tenets

Pour vous faire comprendre comment 9P fonctionne, il faut retenir trois choses.
La première, c’est que tout est fichier. Et quand je dis tout, c’est vraiment tout. Je vous montrerai ça dans quelques instants pendant la démo, mais je vais d’abord essayer de vous l’expliquer avec les mains.
La deuxième chose, c’est que 9P est le protocole qui permet de transférer des actions sur des fichiers. Que ce soit:
- en local — sur un vrai fichier sur un disque —,
- en IPC — entre deux processus, avec des « fichiers » qui sont en réalité des interfaces —,
- ou en remote — sur une autre machine —, tout passe par 9P.
Quand vous faites un fopen
, un fread
, ou un fwrite
, ça génère du 9P, qui est envoyé au processus qui écoute, ou interprété par le noyau, pour manipuler les fichiers.
La troisième chose, c’est l’isolation parfaite de chaque processus. L’image que chaque processus a du système de fichiers est unique. Si vous lancez un autre processus, il aura sa propre image du système de fichiers.
Et ça, c’est hyper important. Parce que par défaut, vous avez ce qu’on appelle maintenant la containerisation. Mais vous l’avez dès le début des années 90, sur des machines à très faibles ressources.
Aujourd’hui, on déploie ça sur des serveurs avec Kubernetes, Docker et compagnie. Mais Docker, ça ne tourne pas sur un objet connecté ! C’est pour les gros serveurs.
Alors que là, ça tourne sur des machines avec quelques kilo-octets de RAM, et ça isole proprement les processus. C’est vraiment bien foutu.
4.2. The protocol

Ça, c’est le protocole 9P.
La slide est moche parce qu’elle est illisible, mais mon point c’est qu’on peut faire tenir tout le protocole sur une seule diapositive. Vous avez quoi… une douzaine de messages. Et chacun de ces messages correspond exactement à un appel système lié aux fichiers.
Vous voulez ouvrir un fichier ? Ça génère un Topen, et le retour c’est Ropen. Vous voulez lire ? Ça génère un Tread, le retour c’est Rread. Et c’est tout. Une fois que vous savez manipuler des fichiers, le protocole est relativement simple.
C’est ça la référence. Si vous avez cette doc sous les yeux et que vous avez déjà utilisé des appels système pour des fichiers, vous pouvez implémenter 9P en une demi-journée. Ce n’est vraiment pas difficile.
Et il y a des implémentations partout. Dans tous les langages que vous pouvez imaginer.
- Il y en a en bare metal.
- Il y en a dans les navigateurs web.
- Il y en a sur toute la pile.
Ce n’est pas un protocole obscur ou sorti de nulle part. Il est même bien intégré dans le noyau Linux.
Par exemple, vous avez v9fs, un driver 9P. Avec un Linux standard de base, vous pouvez monter des serveurs 9P. Quand je dis "monter", c’est comme une clé USB. Un serveur 9P, comme c’est des fichiers, vous faites un mount, et vos fichiers apparaissent comme si vous veniez de brancher une clé USB.
Mais en réalité, vous êtes en train de parler à un serveur à l’autre bout du monde.
Le Windows Subsystem for Linux ? Il utilise 9P pour afficher les fichiers Windows dans le Linux. QEMU, le virtualiseur ? Il utilise 9P aussi pour faire passer les fichiers entre l’hôte et l’invité.
Il y a du 9P partout. Mais on ne le voit pas, parce que c’est un truc de systèmes.
Mais il est utilisable dans l’IoT.
4.3. Per process namespace

L’idée, ce n’est pas d’avoir une grande maison qui s’écroule dès qu’on enlève une brique.
C’est d’avoir un champ de ménhirs : chaque processus est dans son propre namespace. Si jamais un pirate arrive à s’introduire dans un processus à cause d’une faille — par exemple, une exécution de code à distance — eh bien il n’arrivera pas à faire grand-chose. Parce qu’il est complètement isolé.
Peut-être qu’il n’aura même pas accès au réseau — ça, c’est une astuce que je vous montrerai tout à l’heure. Il n’aura pas accès aux fichiers. Et surtout, il n’aura pas accès aux autres processus.
Donc l’impact d’une compromission est très limité, contrairement à un serveur web privilégié où, dès qu’on a une exécution de code distante, c’est la machine entière qui est perdue.
Et encore une fois, ce système a été développé en 1987. C’est l’année où je suis né. Donc oui, on est très en avance. Mais bon… ça, c’est Bell Labs.
4.4. Everything is a file, Linux version

Ça, c’est la version Linux d’il y a 20 ans. À l’époque, on pouvait encore cat
un fichier .wav
sur /dev/dsp
, et ça sortait sur les haut-parleurs. C’était pas mal.
Les entrées-sorties, c’était du texte : stdin, stdout. Ça marchait pas trop mal.
Les joysticks ? Pour être honnête, sur Linux, ça marche vraiment pas mal. Vous pouvez littéralement lire un fichier, et vous voyez quels boutons sont pressés. Si vous voulez faire un petit jeu, c’est une super interface.
Vous avez /proc, qui a été importé directement de Plan 9, et qui vous permet de voir les processus, de les débugger, etc. Vous avez accès à la mémoire, aux block devices…
Certains trucs marchent pas trop mal.
4.5. And then Linux started drinking

Pardon. Je veux dire : il a commencé à boire.
Il y a un truc qui est apparu, qui s’appelle ioctl. Je ne sais pas si ça vous parle… mais en gros, on peut lire des fichiers — ok. Mais avant de les lire, il faut les configurer. Et ioctl, c’est l’appel système poubelle dans lequel on met tout.
Vous voulez lire une vidéo ? D’accord. Mais d’abord, faut faire un ioctl pour dire la résolution, le framerate, etc.
Vous voulez accéder au son ?
Bon, /dev/dsp
marchait avec OSS il y a 20 ans, mais maintenant c’est ALSA, PulseAudio, je sais pas quoi… et c’est ioctl partout, parce que plus personne ne veut faire des fichiers simples.
La souris ? C’était facile… sauf qu’il y en a 27. Faites un ls /dev/input sur votre Linux, vous verrez la tête du truc. On ne sait pas laquelle est laquelle.
Donc, pour "régler" le problème : → on lit toutes les souris en même temps, → mais en fait aucune à la fois.
C’est n’importe quoi.
4.6. It gets worse

Et ça ne s’arrête pas là.
Maintenant, on met même du iouring, parce que lire/écrire des fichiers, c’était trop simple. Donc on crée des buffers circulaires comme dans les années 70. Et on fait du mmap, parce que read, c’est trop rustique. Et on se retrouve à devoir mapper des fichiers en mémoire, et faire du code illisible.
Bref, c’est le bazar.
Il faut lire des pages de man pendant cinq ans. Il faut aller voir le code source pour comprendre. Développer sous Linux avec "tout est fichier", c’est devenu une vaste blague.
4.7. Inferno gets it right

Tout est fichier. Absolument tout. Et c’est vraiment fichier dans le sens où on peut lire et écrire.
Je donne quelques exemples :
- /dev/pointer
- vous le lisez, vous avez la position de la souris. Vous écrivez dedans ? La souris bouge.
- /dev/draw
- vous lisez, vous avez les pixels. Vous écrivez, vous dessinez les pixels.
- /dev/audio
- vous y mettez un fichier .wav, ça joue le son. Vous voulez enregistrer ? Vous lisez dedans.
- /dev/audioctl
- ça remplace ioctl. Il y a parfois un ctl à côté, pour les métadonnées (framerate, etc.), mais c’est du texte, documenté pour chaque device.
Pas un appel système ioctl obscur, avec des flags binaires incompréhensibles.
C’est clean, simple, documenté.
Et parmi ces fichiers, si vous voulez faire de l’IoT, il y en a qui vont vous plaire :
- Les ports séries
- vous pouvez envoyer directement des bits sur du câble.
- Si vous avez un FPGA
- vous pouvez lui parler en live.
- Vous avez les GPIO
- donc sur un Raspberry Pi, par exemple, vous pouvez commander des LED, des relais, etc.
- L’USB
- est supporté.
- Les écrans tactiles aussi
- vous pouvez savoir si c’est un appui long, court, un stylet, plusieurs doigts…
Vous avez tout là-dedans. Ça, c’est l’équivalent de stdin / stdout. Si vous voulez savoir quel utilisateur vous êtes, vous lisez /dev/user. Si vous voulez en changer (et que vous avez les privilèges), vous écrivez dedans.
Bref, ça marche vraiment bien. C’est clean, beau, propre.
5. Demo time:
5.1. VPN

(This demo is on my Inferno is Cool page) Alors, la démo.
Je vais tenter un truc, ne quittez pas. Je vais faire une démo SSH.
Je me connecte à mon serveur pour vous montrer.
Bon, j’utilise mon téléphone, donc c’est pas sûr que ça marche. Donnez-moi juste deux minutes de patience — merci.
Je tente une démo sur un talk de 20 minutes, c’est un peu ambitieux…
Ce qui se passe ici : Ça, c’est le client. Ça, c’est le serveur.
Le serveur tourne chez OVH. Il fait tourner Linux, qui fait tourner Inferno.
Ce que je ne vous ai pas encore dit, c’est qu’Inferno, ce n’est pas juste un système d’exploitation. C’est aussi une application.
Donc vous pouvez le faire tourner comme une app. En fait, ça émule un OS. C’est hyper léger.
Donc là, j’ai un petit serveur pas cher chez OVH, qui fait tourner Inferno.
Sur l’écran, vous voyez un truc du genre :
listen -v 'tcp!*!5546' { export /net& }
Qu’est-ce que ça veut dire ?
Ça veut dire : → on écoute sur le port 5546, → toute connexion qui arrive est authentifiée, → une fois authentifiée, on exécute la commande export /net.
Ce qui vient du réseau va sur l’entrée standard de cette commande. Et ce qui sort de la sortie standard de cette commande retourne sur le réseau.
Donc c’est super simple de faire du scripting en réseau avec ça.
Et export, ça sert à quoi ?
Ça sert à exporter via 9P une partie du système de fichiers.
Là, on exporte /net, qui est l’interface réseau.
Quand je vous dis que tout est fichier, c’est vraiment tout : → Il n’y a pas de sockets sur Inferno. → Vous voulez ouvrir une connexion vers un site ? → Vous écrivez dans /net/tcp/clone, et voilà.
Donc ici, je suis sur Inferno qui tourne sur ma machine locale.
Si je lance un script que j’ai écrit, my-ip
, j’obtiens l’adresse IP de mon téléphone (via la 4G), un truc du genre 92.xxx.xxx.xxx.
Si je fais la même chose sur le serveur, j’obtiens 51.178.xxx.xxx, l’IP d’OVH.
Et maintenant, le truc cool : je monte le /net
du serveur localement.
Donc j’ai pris le système de fichiers réseau du serveur, et je l’ai monté dans /n/rdklein.fr
sur ma machine.
Là, dans ce répertoire, j’ai accès au /net
du serveur distant.
Je fais :
sh -c { bind /n/rdklein.fr/net /net; myip }
Et là, bam, j’obtiens l’adresse IP du serveur : 51.178.xxx.xxx.
Mais si je relance myip sans cette bidouille, je reviens à 92.xxx.xxx.xxx — mon IP locale.
Pourquoi ? Parce que chaque processus a sa propre vision du système de fichiers. Avec sh -c, j’ai lancé un nouveau processus. Dans ce processus, j’ai bindé /net sur celui du serveur. Résultat : mon script voit l’IP distante.
Donc là, en deux lignes de code, j’ai fait un VPN par processus.
Juste pour comparer : WireGuard dans le noyau Linux, c’est 100 000 lignes de code. Là, avec Inferno, on a une solution simple, élégante, puissante.
5.2. Omegle

[Je n'ai pas eu le temps de faire la deuxième démo] Le point que je voulais faire avec Omegle :
Le modèle du Web, c’est un gros serveur central, très puissant, avec des clients stupides qui s’y connectent.
Le modèle proposé par 9P est complètement différent.
Vous pouvez avoir un point de rendez-vous (genre un DNS pour se retrouver), mais ensuite, Alice et Bob se connectent directement entre eux.
Et dans Inferno, la notion de "serveur" et "client" devient floue. Tout le monde peut être serveur, tout le monde peut être client. Vous pouvez composer un univers distribué, en assemblant des bouts de fichiers entre machines.
Et vous pouvez exporter une partie de votre monde à quelqu’un d’autre, avec à chaque fois :
- authentification,
- chiffrement,
- contrôle d’accès.
6. 9P + IoT
6.1. 9P vs HTTP

Alors, pourquoi je vous parle de tout ça dans le cadre de l’IoT ?
Parce que souvent, dans l’IoT, on fait du HTTP.
On fait soit une API REST, soit une interface web… mais tout passe par HTTP. Et du coup, le chiffrement devient un problème de transport, pas un problème d’application. On fait du TLS (ou SSL si on est en retard) au niveau de TCP.
Mais l’authentification, elle, devient un problème d’application. HTTP ne sait pas gérer ça proprement.
Il y a eu des gens qui ont dit qu’on allait faire de l’authentification TLS avec des certificats clients… → En théorie, ça marche. → En pratique, ça ne s’est jamais déployé.
Donc on a reporté l’authentification dans l’appli. Et les problèmes de sécurité que ça pose sont énormes.
À l’inverse, dans 9P, l’authentification est intégrée dès le départ.
Quand un client se connecte, il est déjà authentifié. Du coup, le serveur lancé pour ce client n’a pas besoin de vérifier quoi que ce soit. Il n’est lancé que si l’authentification a réussi.
Donc toute la partie cryptographie, gestion de login, mot de passe… elle dégage de la couche applicative. Et ça, ça renforce la sécurité.
Et pour le reste, les verbes HTTP (GET, POST, PUT, DELETE, etc.), ce sont juste des appels systèmes fichiers.
- Lire un fichier = GET.
- Écrire dans un fichier = POST.
- Supprimer = DELETE.
- Chercher à un offset (
seek
), ce qui est PATCH, galère en HTTP mais trivial en système de fichiers.
6.2. Less is More

Ça ne sert à rien d’avoir des machines hyper puissantes, toutes connectées à Internet, que des pirates peuvent prendre.
Au contraire : Faites des machines toutes petites, qui tournent Inferno, qui parlent 9P, sur port série. Si quelqu’un peut les pirater, c’est qu’il est dans la pièce.
Et à ce moment-là, s’il veut ouvrir la fenêtre, il peut juste le faire à la main. S’il veut allumer le robinet, il peut le tourner. L’accès physique, c’est fini.
Utilisez donc des petits protocoles, courte distance : → Bluetooth Low Energy, Zigbee, → série, infrarouge…
Le série, ça marche super bien, et il n’y a aucune raison de faire autre chose dans 90 % des cas.
Petit exemple marrant : Il y a une expérience où ils ont pris Plan 9, et ils l’ont fait tourner sur un LEGO Mindstorms. Littéralement, une brique en plastique.
Ils ont réussi à parler 9P en infrarouge entre un ordi et le LEGO. Ils ont mis ça en place en une après-midi. Et ensuite, en écrivant des fichiers, on pouvait contrôler les moteurs du robot LEGO.
6.3. Smart appliances

Et dans une cuisine, ça donnerait quoi ?
Vous avez des capteurs de température et des thermostats. Vous créez un fichier /dev/temp. Vous le lisez → vous obtenez la température. Vous écrivez dedans → vous définissez la température cible.
Vous faites ça pour chaque appareil.
Ensuite, vous prenez un petit Raspberry Pi, vous montez ces fichiers : /mnt/frigo/temp
,
/mnt/four/temp
.
Et vous construisez une interface graphique qui parle à ça.
Le noyau Linux du Raspberry Pi se charge du contrôle d’accès. Une fois que c’est blindé, les machines sont bêtes. Elles n’ont aucun contrôle d’accès local. Mais comme elles sont reliées physiquement ou par un réseau radio très court, c’est suffisant. → Si quelqu’un est là physiquement, il peut déjà tourner le bouton du four à la main. Ce n’est pas un problème de sécurité.
Donc, on peut composer l’univers qu’on veut, avec 9P. C’est vraiment pas difficile.
7. Conclusion

Il ne me reste qu’une demi-minute.
Merci beaucoup de votre attention.
Si vous voulez me joindre, mon adresse email est ici.
Si vous voulez jouer avec 9P et toutes ces technologies, il y a un site qui s’appelle the-dam.org
.
J’essaie d’y construire une communauté. On se connecte tous au même serveur, il y a du 9P dessus, venez !
Pour éviter le spam, j’ai mis une entrée à 10 €. Mais si vous me dites que vous étiez là, c’est gratuit. Je veux juste éviter les robots.
Et dernière chose : du 22 au 24 mai, il y a la conférence internationale Plan 9, et cette année, elle a lieu en France, au CNAM.
Ça fait 20 ans qu’elle n’était pas venue en Europe. C’est une conférence scientifique, avec plein de gens qui ont vécu ça à l’époque, et qui prêchent maintenant la bonne parole.
Venez !
Merci beaucoup, et venez me parler à la fin.