Installer Marionnet

Traduction française de INSTALL.md. L'original anglais fait foi : en cas de divergence, c'est lui qu'il faut corriger, et cette page à sa suite.

Quelle méthode utiliser, ce que chacune installe sur le système de fichiers, et ce que vous devez ou pouvez faire ensuite.

Marionnet est publié sous trois formes prêtes à l'emploi, toutes alimentées par le même répertoire de release sur www.marionnet.org et portant toutes le même binaire. Celle qu'il faut prendre dépend du gestionnaire de paquets de votre machine, pas de ce que vous comptez faire de Marionnet :

Votre machine Prenez §
Debian, Ubuntu et dérivées le dépôt apt § 2
Fedora, famille RHEL (Rocky, AlmaLinux), openSUSE le dépôt dnf/zypper § 3
tout le reste — ou vous ne voulez aucun gestionnaire de paquets le tarball précompilé § 4
vous comptez modifier Marionnet depuis les sources § 6

Les systèmes sur lesquels cette release a réellement été installée, et les chiffres qui le disent, sont juste en dessous.

Quelle que soit la méthode, les images invitées et les noyaux UML se récupèrent séparément (§ 5) : ils pèsent des gibioctets et changent à leur propre rythme. Marionnet démarre sans eux et le dit.

Marionnet est un programme graphique : il lui faut un affichage X (DISPLAY), et il en ouvre l'accès aux invités avec xhost (§ 7.2).

Tout chemin relatif de cette page est relatif au répertoire où se trouve ce fichier : doc-src/ dans les sources, <prefix>/share/doc/marionnet/ sur une machine où Marionnet est installé.

Sur quels systèmes l'installation a été testée

Le tableau ci-dessous n'est pas une déclaration d'intention : chacune de ses lignes a été mesurée, sur la release que décrit cette page, par les quatre bancs de Makefile.d/*.bench/ et bin/scripts/marionnet-install.sh.bench/ — chacun installant Marionnet dans un conteneur nu de la distribution concernée, puis demandant à la machine ce qu'elle a obtenu. Les chiffres sont les cas que ces bancs ont joués, et les échecs qu'ils ont trouvés.

Système glibc tarball (§ 4) apt (§ 2) dnf/zypper (§ 3)
Ubuntu 20.04 LTS (focal) 2.31 49 / 0 41 / 0
Ubuntu 22.04 LTS (jammy) 2.35 49 / 0 41 / 0
Ubuntu 24.04 LTS (noble) 2.39 49 / 0 41 / 0
Ubuntu 26.04 LTS 2.41 49 / 0 41 / 0
Debian 11 (bullseye) 2.31 49 / 0 41 / 0
Debian 12 (bookworm) 2.36 49 / 0 41 / 0
Debian 13 (trixie) 2.41 49 / 0 41 / 0
Rocky Linux 9 2.34 58 / 0
AlmaLinux 9 2.34 56 / 0
Rocky Linux 10 2.39 59 / 0
AlmaLinux 10 2.39 57 / 0
Fedora 42 2.41 58 / 0
openSUSE Leap 16.0 2.40 56 / 0
openSUSE Leap 15.6 2.38 non servie, voir plus bas

Lire réussis / échoués. L'installeur lui-même est mesuré à part, sur les sept boîtes Debian et Ubuntu à la fois : 504 cas, aucun échec.

Ce que le tableau veut dire pour votre machine. Marionnet est un programme lié dynamiquement, et les noyaux UML qu'il exécute le sont aussi : ce qu'ils exigent du système où ils atterrissent est une glibc au moins aussi récente que celle contre laquelle ils ont été compilés, et cette exigence ne voyage que vers l'avant. Cette release est construite sur Debian 11 (glibc 2.31) pour le versant Debian et sur Rocky Linux 9 (glibc 2.34) pour le versant RPM — les plus anciennes boîtes de chaque famille que nous servons. Toute distribution au-dessus de ces planchers est servie par les mêmes artefacts ; vous n'avez pas de build à choisir pour votre version.

Le tarball précompilé (§ 4) porte ce plancher dans son propre nom de fichier (marionnet_<version>-r<rév>_<arch>_glibc<x.y>.tar.xz), et marionnet-install.sh l'y lit : sur une machine dont la glibc est plus ancienne, l'installeur le dit et refuse, plutôt que de déplier quelque chose qui ne pourrait pas démarrer. Le .deb et le .rpm disent la même chose dans les mots de leur propre gestionnaire de paquets — libc6 (>= ...), libc.so.6(GLIBC_...) — de sorte qu'apt et dnf les refusent d'eux-mêmes.

openSUSE Leap 15.6, et ce qui lui barrait la route. Sa glibc (2.38) n'a jamais été l'obstacle. uml-utilities, qu'aucune distribution RPM n'empaquette et que ce projet compilait donc lui-même, est lié à libreadline.so.8, or Leap 15.x livre readline 7 ; le refus était celui de zypper, et il nommait cette bibliothèque. Depuis le 2026-09-12, Marionnet ne dépend plus du tout de ce paquet : les deux programmes qu'il lui fallait — le client mconsole et le port-helper qu'exécute le noyau UML — sont construits depuis ce dépôt, sans readline, et installés sous les noms marionnet_uml_mconsole et marionnet_uml_port_helper. La release publiée avant cette date porte encore l'ancienne dépendance ; la première release publiée après elle sert Leap 15.6. Leap 16.0, elle, était déjà servie.

Plus ancien que le tableau. Ubuntu 18.04 et Debian 10 sont sous les deux planchers et ne sont pas servies. Rien n'empêche de construire Marionnet depuis les sources (§ 6) sur un système que les canaux binaires n'atteignent pas, pourvu que ses paquets satisfassent le § 6.

1. Avant toute chose, sur une Debian ou une Ubuntu minimale

Les trois méthodes atteignent le site en https, et un système Debian ou Ubuntu minimal — notamment une image de conteneur nue — ne porte aucun magasin de certificats (mesuré sur Debian 12 et 13 et sur Ubuntu 24.04 et 26.04 ; les images de la famille RPM, elles, en ont un). Sans lui, apt ne lira pas notre dépôt et l'installeur ne lira pas le catalogue, alors même que le serveur est parfaitement debout :

sudo apt update && sudo apt install ca-certificates curl

curl est dans cette ligne pour la même raison : une image slim n'a pas non plus de téléchargeur, et le § 2 récupère la clef de l'archive avec (wget -O à la place de curl -o fait tout aussi bien).

marionnet-install.sh nomme cette cause plutôt que d'accuser le réseau, mais il ne peut pas la réparer : installer ce paquet demande le gestionnaire de paquets en état de marche qui est précisément en jeu.

2. Debian et Ubuntu — le dépôt apt

Mesuré sur Debian 12, Debian 13, Ubuntu 24.04 et Ubuntu 26.04.

sudo install -d /etc/apt/keyrings
sudo curl -o /etc/apt/keyrings/marionnet.asc \
     https://git.launchpad.net/marionnet/plain/marionnet-archive-keyring.asc
echo 'deb [signed-by=/etc/apt/keyrings/marionnet.asc] https://www.marionnet.org/download/apt/ ./' \
  | sudo tee /etc/apt/sources.list.d/marionnet.list
sudo apt update
sudo apt install marionnet

download/apt est un point d'entrée stable : il suit la série de publication courante, si bien que la ligne ci-dessus n'a pas à être modifiée quand la série change.

La clef

Le fichier Release du dépôt est signé, et c'est signed-by= qui fait qu'apt le vérifie. La clef est :

Marionnet Archive Signing Key <loddo@lipn.univ-paris13.fr>
4A65 3434 0BF9 7733 E74C  9DFC 12E4 6000 225F 0E56

Elle vient de git.launchpad.net, et non de www.marionnet.org : c'est tout l'intérêt. https ne prouve que ceci, que le serveur n'a pas été usurpé ; qui contrôle ce serveur réécrit les paquets et les empreintes qui en répondent. Une signature déplace le point de confiance vers une clef privée qui n'y vit pas.

Ce qu'elle protège : les machines déjà installées. Elles ne relisent jamais cette page — à chaque apt upgrade elles contrôlent contre la clef présente sur leur propre disque, si bien que personne qui prendrait le serveur demain ne peut leur pousser une mise à jour piégée, sur des machines où Marionnet installe une règle sudoers. Ce qu'elle ne protège pas : votre toute première installation, si vous apprenez tout d'une page compromise, qui nommerait une autre clef et vérifierait parfaitement. La sortie est de comparer l'empreinte ci-dessus avec une source qui n'est pas cette page : le dépôt git (§ Où aller ensuite), un polycopié imprimé, une machine où Marionnet tourne déjà. Dans une salle de TP, l'empreinte lue à voix haute une fois en début de semestre règle la question pour tout le monde.

Contrôlez ce que vous avez récupéré — cette étape n'est pas facultative. Mesuré : git.launchpad.net répond 200 la plupart du temps et, environ une requête sur six, un 302 vers sa page de connexion OpenID, et curl écrit dans le fichier ce qui lui est revenu. N'ajoutez pas -L : cela suit la redirection et écrit la page de connexion — un échec qui ressemble à une réussite.

sudo apt install gnupg
gpg --show-keys /etc/apt/keyrings/marionnet.asc     # doit afficher l'empreinte ci-dessus

Si autre chose s'affiche — ou rien — récupérez-la de nouveau. apt n'a pas besoin de gnupg pour vérifier le dépôt (il a son propre vérificateur) ; vous en avez besoin, vous, pour lire ce que vous avez récupéré.

Les paquets

apt install marionnet installe l'application et le noyau 64 bits : marionnet-kernels est un Recommends:, qu'apt installe par défaut — sans noyau, rien ne démarre du tout. (--no-install-recommends est là pour qui n'en veut pas.) Les images, elles, restent des Suggests: : des gibioctets sont un choix, pas une implication. Au § 3, dnf install marionnet n'apporte que l'application, et c'est mesuré, pas négligé : dnf saute en silence la dépendance faible sur le noyau (qui tire glibc.i686), donc ce canal la laisse en Suggests: et le dit après l'installation. Dans les deux cas, le message d'après-installation mesure ce qui manque encore et le nomme.

Ce ne sont pas des accessoires : sans image, l'application ne démarre rien. Un invité a besoin d'un système de fichiers et d'un noyau que ce système de fichiers déclare supporter, et Marionnet ne propose pas un système de fichiers dont aucun noyau supporté n'est installé. Rien n'échoue et rien n'est dit : le composant est simplement absent de la liste.

Paquet Ce qu'il porte — et ce qui manque sans lui
marionnet-kernels le noyau UML 64 bits linux-6.12.95. Sans lui, les images récentes (Debian trixie) ne sont pas proposées
marionnet-fs-guignol la petite image invitée, machine et routeur — le seul système de fichiers de routeur publié. Sans lui, aucun routeur ne peut être construit
marionnet-kernels-i386 le noyau UML 32 bits linux-6.12.95-i386. Sans lui, guignol et wheezy ne sont pas proposés, et avec eux tout projet .mar antérieur à 2026

Un routeur coûte deux paquets, pas un. Mesuré dans le .conf publié : guignol déclare SUPPORTED_KERNELS='/3.2.[6-9]/ /-i386$/', que linux-6.12.95 ne satisfait pas. Donc marionnet-fs-guignol exige marionnet-kernels-i386 — le noyau 64 bits ne le fera pas tourner — et l'architecture étrangère ci-dessous n'est pas affaire de vieux projets seulement : c'est ce que coûte un routeur aujourd'hui.

marionnet-kernels-i386 exige une architecture étrangère activée sur votre machine, parce que l'interpréteur du noyau 32 bits est /lib/ld-linux.so.2 et que seul libc6:i386 possède ce chemin :

sudo dpkg --add-architecture i386 && sudo apt update
sudo apt install marionnet-kernels-i386

Sans cela, apt refuse le paquet en nommant libc6:i386. Activer une architecture étrangère est une décision : c'est pourquoi le noyau 32 bits est un paquet à part.

Si un tarball Marionnet (§ 4) a d'abord été installé sur cette machine, /etc/marionnet/marionnet.conf existe déjà et dpkg demandera quoi en faire — et un apt install non interactif échoue là, parce que DEBIAN_FRONTEND=noninteractive gouverne debconf, et non l'invite de conffile de dpkg. Pour garder la configuration que vous avez déjà :

sudo apt install -o Dpkg::Options::=--force-confold marionnet

La version du fichier livrée par le paquet est alors laissée à côté, sous le nom marionnet.conf.dpkg-dist. Les deux divergent sur un point qui compte : un paquet installe sous /usr, un tarball sous /usr/local.

3. Fedora, famille RHEL et openSUSE — le dépôt dnf/zypper

Mesuré sur Fedora 42, Rocky Linux 10, AlmaLinux 10 et openSUSE Leap 16.

# 1. la clef — récupérée, REGARDÉE, et alors seulement importée
sudo install -d /etc/pki/rpm-gpg
sudo curl -o /etc/pki/rpm-gpg/RPM-GPG-KEY-marionnet \
     https://git.launchpad.net/marionnet/plain/marionnet-archive-keyring.asc
gpg --show-keys /etc/pki/rpm-gpg/RPM-GPG-KEY-marionnet   # doit afficher l'empreinte du § 2
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-marionnet

# 2. le dépôt, puis l'application
sudo curl -o /etc/yum.repos.d/marionnet.repo \
     https://www.marionnet.org/download/rpm/marionnet.repo
sudo dnf install marionnet          # zypper install marionnet, sur openSUSE

download/rpm est le point d'entrée stable, comme download/apt l'est pour le § 2.

La clef, de ce côté-ci

Même clef, même endroit, mêmes réserves qu'au § 2 — y compris la redirection une requête sur six. La ligne du milieu du bloc ci-dessus vient avant rpm --import à dessein : importer est l'acte de faire confiance, donc regarder ensuite serait regarder trop tard. Si gpg manque : sudo dnf install gnupg2 (zypper install gpg2 sur openSUSE) ; ni dnf ni rpm n'en ont besoin.

Ce qui diffère, c'est la forme de la vérification, pas sa force. Là où apt a une signature sur Release qui couvre tous les paquets par leur empreinte, rpm a deux mécanismes, et la strophe demande les deux :

Réglage Ce qu'il vérifie
gpgcheck=1 chaque paquet, par une signature que rpmsign a logée dans le fichier lui-même
repo_gpgcheck=1 l'index, par le repodata/repomd.xml.asc posé à côté

La strophe nomme la clef par un fichier local (gpgkey=file:///etc/pki/rpm-gpg/…) et non par une URL — d'où le fait que vous la récupériez vous-même ci-dessus : dnf récupère gpgkey= lui-même et suit les redirections, sans qu'on puisse l'en empêcher, si bien qu'une URL pointant sur git.launchpad.net télécharge la page de connexion une fois sur six et fait mourir l'installation sur Failed to import OpenPGP keys, après avoir téléchargé tous les paquets.

dnf peut encore vous montrer une empreinte et vous demander s'il faut accepter la clef : il tient un trousseau à lui pour repo_gpgcheck, que le rpm --import n'alimente pas. Comparez ce qu'il affiche avec l'empreinte du § 2 avant de répondre oui.

Sur la famille RHEL, activez d'abord EPEL : gtksourceview3, l'une des dépendances d'exécution de Marionnet, y vit et non dans les dépôts de base.

sudo dnf install epel-release

Le dépôt porte aussi vde2, sans lequel Marionnet ne peut pas tourner et qu'aucune distribution RPM n'empaquette (mesuré sur Rocky 9 avec EPEL, CRB et epel-next, et sur Fedora 42 et 44) ; il est construit ici à partir du paquet source Debian. dnf le résout depuis le même répertoire, si bien que vous n'avez pas à savoir qu'il existe — sauf sur openSUSE, qui livre vde2 et dont c'est le paquet qui est utilisé. Un second paquet, uml-utilities, était porté de la même façon jusqu'au 2026-09-12 ; un répertoire publié avant cette date le contient encore, et plus rien ne l'installe.

Les trois paquets de données sont les mêmes qu'au § 2, sous les mêmes noms, et nécessaires aux mêmes choses. Le multilib étant natif ici, le noyau 32 bits n'a pas besoin d'un équivalent du dpkg --add-architecture ; mais RHEL 10 a supprimé tout le multilib 32 bits, si bien que sur cette famille marionnet-kernels-i386 n'est tout simplement pas installable — c'est pourquoi il est un paquet séparé : que son refus n'emporte pas celui de 64 bits. Il faut en prendre la conséquence : pas de noyau 32 bits, donc pas de guignol ni de wheezy, donc pas de routeur sur RHEL 10 (§ 2) — état temporaire, la publication d'une image de routeur 64 bits étant prévue.

4. N'importe quelle distribution — le tarball précompilé

L'application est aussi publiée sous la forme d'un tarball relocatable, nommé marionnet_<version>-r<rev>_<arch>_glibc<x.y>.tar.xz. Les deux derniers champs sont ceux qui décident : l'artefact tourne sur une machine dont l'architecture est <arch> et dont la glibc est au moins <x.y>, le versionnement des symboles de la glibc ne garantissant la compatibilité que dans ce sens-là. L'artefact publié est construit sur le plus ancien système que nous servons (actuellement Debian 12, glibc 2.36) : il tourne donc sur toutes les distributions listées aux § 2 et § 3, et sur aucune plus ancienne — Rocky 9 et openSUSE Leap 15.6 le refusent en nommant la glibc.

Cette forme n'est pas signée : SHA256SUMS, que l'installeur contrôle pendant le téléchargement, prouve que le fichier est arrivé entier, pas qui l'a écrit — le catalogue voyage par la même route que les tarballs. Si cette distinction compte pour vous, prenez le § 2 ou le § 3.

Le plus simple est de laisser l'installeur choisir et déplier pour vous :

wget https://www.marionnet.org/download/marionnet-install.sh/marionnet-install.sh
bash marionnet-install.sh --binary --with-deps

--binary exige root (il appelle sudo si vous n'êtes pas root). Pour voir ce qui est publié avant d'installer quoi que ce soit, demandez le catalogue — y compris ce qu'il refuse, et pourquoi :

bash marionnet-install.sh --binary --fetch-only --list

--list se donne avec un mode : c'est le mode qui dit si l'application, les données, ou les deux vous intéressent, et le script refuse de le deviner (sous son autre nom, marionnet-get-images, le mode est implicite — § 5). À la main, si vous préférez :

xz -dc -T0 marionnet_<...>.tar.xz | tar xf -
cd marionnet_<...>/ && sudo ./install.sh --prefix /usr/local

install.sh est le même script dans les deux cas — l'installeur ne fait que lancer celui qui voyage dans le tarball. Il copie bin/ et share/ sous le préfixe, écrit /etc/marionnet/marionnet.conf (c'est ce qui permet au tarball de vivre n'importe où) et installe la règle sudoers (§ 7). Par défaut il nomme les paquets apt manquants sans rien installer ; --with-deps les installe, --no-deps ne regarde même pas. Son --help liste le reste.

Les paquets dont Marionnet a besoin à l'exécution voyagent dans le tarball comme donnée, un nom par ligne, dans REQUIRED-PACKAGES-RUNTIME. Sur un système de la famille Debian, à la main :

sudo apt install $(tr '\n' ' ' < REQUIRED-PACKAGES-RUNTIME)

5. Les images invitées et les noyaux UML

Quelle que soit la méthode qui a installé l'application, voici la commande qui propose les images et les noyaux publiés sous forme de liste à cocher, et récupère ce que vous avez coché :

marionnet-get-images

Elle montre comme déjà installée — cochée, et non modifiable — toute image dont la date de modification correspond au MTIME que son .conf enregistre, lequel est le champ que user-mode-linux lui-même contrôle sur un backing file.

Ne passez pas --prefix après une installation par paquet. Sans --prefix, les images vont là où le Marionnet installé ici les cherche — demandé à marionnet --paths, seul lecteur de la cascade de configuration — soit /usr/share/marionnet/... pour un paquet et /usr/local/share/marionnet/... pour un tarball. Un --prefix écrit à la main, c'est ainsi que des images finissent dans un répertoire que l'application ne lit jamais : rien n'échoue, et les images n'apparaissent simplement pas.

Deux des images (Debian wheezy, Debian trixie) sont délibérément hors d'apt et de dnf : elles pèsent des gibioctets. La petite image guignol et les noyaux sont aussi disponibles en paquets (§ 2, § 3), si vous préférez que votre gestionnaire de paquets en soit propriétaire.

Pour une salle de TP sans accès à Internet, faites une fois un miroir du répertoire de release et pointez toutes les machines sur la copie — un répertoire local et une URL sont le même argument :

marionnet-install.sh --fetch-only --from /srv/marionnet-mirror

6. Depuis les sources

Pour qui compte modifier Marionnet. La chaîne d'outils est OCaml 5.4.1 par opam, plus camlp4 ; les images invitées et les noyaux viennent toujours du § 5.

git clone https://git.launchpad.net/marionnet && cd marionnet
make dependencies          # paquets apt (build + exécution), switch opam, paquets opam
dune build                 # un clone frais n'a besoin de rien d'autre : préprocesseurs camlp4,
                           # stubs C, version.ml et meta.ml sont tous construits par dune
make install-final-as-root # elle appelle sudo elle-même, pour la seule étape qui l'exige

Lancez les parties de make dependencies séparément (make apt-dependencies, make opam-switch, make opam-dependencies) si vous voulez les voir une à une. Deux choses à savoir :

7. Ce qui reste dû après n'importe quelle méthode : la règle sudoers

Marionnet construit ses taps réseau avec iproute2, ce qui exige une règle sudoers cadrée. Aucune méthode d'installation ne l'accorde automatiquement, et les paquets s'en abstiennent délibérément : une installation de paquet ne peut pas savoir à quel humain une machine appartient. Lancez, en tant qu'administrateur :

sudo marionnet-sudoers.sh install <user>...

Cela accorde le socle — bloc (a) — sans lequel rien ne marche. L'install.sh du tarball l'installe pour vous (sauf --no-sudoers). Pour tout retirer : sudo marionnet-sudoers.sh uninstall.

Ce qui est accordé est une porte, pas une commande. Aucun des trois blocs ne nomme plus ip, iptables ni sysctl. Chacun nomme un petit script — une porte — que l'on franchit par un verbe littéral, lequel valide ses arguments en root et refuse tout le reste. Le bloc (a) accorde quatre de ces verbes de marionnet-tap.sh — plus une ligne pour marionnet-tun-device.sh, la porte qui rend /dev/net/tun utilisable sur un hôte où il ne l'est pas —, le bloc (b) vingt-quatre verbes de marionnet-natbridge.sh priv, et le bloc (c) douze de marionnet-lanbridge.sh priv. La raison n'est pas une affaire de style : un tap et un pont sont nommés d'après un identifiant de processus, si bien que les anciennes règles devaient se cadrer par un * à l'intérieur d'un argument, et sudo-rs — le sudo d'Ubuntu 26.04 — rejette le fichier entier dès qu'il en rencontre un. Mesuré sur ubuntu:26.04 : chacune de ces règles refusée, rien d'installé.

Une porte doit appartenir à root, et tout répertoire au-dessus d'elle aussi. Une règle NOPASSWD qui nomme un script que son propriétaire peut remplacer est un shell root pour ce propriétaire : install refuse donc — en nommant le chemin fautif et le chown/chmod qui le réparerait — plutôt que d'accorder. Deux conséquences à connaître avant de taper la commande :

7.1 Accorder : un compte, plusieurs, ou une salle entière

La commande est additive : accorder le droit à une deuxième personne ne retire jamais celui de la première, et sudo marionnet-sudoers.sh uninstall <utilisateur> retire une autorisation en laissant les autres en place. Un compte qui n'existe pas est refusé — sudoers le nommerait volontiers, et le droit tomberait dans les mains du premier à qui l'on créerait ce login.

Un principal est un compte, ou un groupe dans l'orthographe de sudoers. La salle de TP en est la raison : celui qui prépare une salle ne connaît pas les logins des étudiants qui s'y assiéront.

sudo groupadd marionnet                      # si le site n'a pas de groupe à lui
sudo gpasswd -a <login> marionnet            # (ou utilisez le groupe LDAP/AD existant)
sudo marionnet-sudoers.sh install %marionnet

Tout membre du groupe est alors autorisé, y compris celui qui s'inscrira la semaine prochaine. Une chose à savoir sur une autorisation de groupe : ALL est refusé — ce qu'un fichier accorde doit avoir été décidé par quelqu'un, et cela engloberait les comptes système. (Jusqu'à la version 1.0.423 il y en avait une seconde : un groupe ne pouvait pas lier le tap à un login, si bien qu'un membre pouvait créer un tap appartenant à quelqu'un d'autre. C'est fini : le propriétaire du tap n'est plus écrit dans la règle du tout, c'est le compte que sudo désigne comme appelant.)

sudo -l -U <login> est la question sur les droits effectifs ; marionnet-sudoers.sh check répond sur les principaux que le fichier nomme, si bien qu'un membre d'un groupe autorisé n'en est pas un. Nu, check est une question sur le fichier : est-il à jour pour les comptes qu'il nomme (0), accordé mais écrit par une version antérieure de Marionnet (4), ou pas accordé du tout (1) ? Sur un 4, check --explain nomme ce qu'un rafraîchissement changerait, en commandes gagnées et perdues — et rafraîchir, c'est marionnet-sudoers.sh install, qui est additif et ne retire le droit de personne.

Et une quatrième réponse, 5, qui ne parle pas du fichier du tout. Un fichier peut être parfait et sudo le refuser quand même, car dans sudoers la dernière règle qui matche gagne : une entrée plus large analysée après la nôtre — un simple student ALL=(ALL:ALL) ALL déposé dans /etc/sudoers.d/student, qui trie après marionnet — annule chaque ligne NOPASSWD sans changer un octet de notre fichier. Réinstaller ne changerait rien ; renommer le fichier large pour qu'il soit analysé en premier est le remède :

sudo -ll ; ls /etc/sudoers.d/          # trouver l'entrée large
sudo mv /etc/sudoers.d/student /etc/sudoers.d/00-student

check interroge sudo lui-même, une question par bloc — le verdict est par fichier, si bien qu'un voisin trié après marionnet-lanbridge annule le LAN bridge et rien d'autre. Il interroge en lançant un no-op inoffensif de la porte propre à ce bloc, seule question qui ait un sens ici : sudo -l répond « ce compte a-t-il le droit de le lancer », pas « sans mot de passe ».

7.2 Les trois blocs, et ce que chacun fait à cette machine

À lire avant d'accorder quoi que ce soit au-delà du socle. Les trois blocs sont trois fichiers de /etc/sudoers.d/, accordés à trois moments différents, et ils ne sont pas également dangereux.

Bloc Accordé Ce qu'il permet de faire à l'hôte
(a) taps fantômes à l'installation, par l'administrateur Créer et détruire des interfaces mtap*, leur donner l'adresse fixe 172.23.0.254/32 et y router 172.23.*. Confiné aux mtap* — et le cadrage est désormais fait en root, par la porte : les quatre verbes de marionnet-tap.sh vérifient le nom qu'on leur donne, et le propriétaire du tap est le compte que sudo désigne comme appelant, pas un argument que n'importe qui peut écrire. Ce tap est aussi la route par laquelle les clients X11 d'un invité atteignent l'affichage de l'hôte — xterm sur une machine ou un routeur, et surtout wireshark lancé dans un routeur ou une machine pour capturer son propre trafic ; Marionnet en ouvre la porte par xhost +172.23.0.254. Sans ce bloc, Marionnet tourne en mode dégradé : pas de graphique depuis les invités, pas de terminaux de routeur.
(b) NAT bridge à l'exécution, depuis l'interface Construire le pont privé mnbr* et faire du NAT pour les invités derrière lui.
(c) LAN bridge à l'exécution, depuis l'interface Mettre la carte réseau de l'hôte dans un pont, pour que les invités soient sur le vrai réseau local.

(b), en détail. Il crée un pont mnbr* portant l'adresse .1/24 d'un réseau privé ; il met net.ipv4.ip_forward à 1, ce qui vaut pour toute la machine et non par interface (Marionnet ne le remet à 0 au démontage que s'il l'a lui-même mis à 1) ; il ajoute une règle MASQUERADE et deux règles FORWARD avec iptables, toutes porteuses du commentaire marionnet-natbridge:mnbr* — ce marqueur est construit par la porte, à partir d'un nom de pont qu'elle vient de valider, si bien qu'aucune règle préexistante de votre pare-feu ne peut être ajoutée, modifiée ni supprimée par cette autorisation. Ce qui est accordé ici, ce sont les vingt-quatre verbes de marionnet-natbridge.sh priv, qui valident leurs arguments en root — la porte, encore, et le marqueur ci-dessus fait partie de ce qu'elle calcule au lieu de l'accepter. Facultativement, il démarre un dnsmasq lié à ce seul pont (DHCP en .100-.200, plus le DNS pour les invités) — c'est pourquoi dnsmasq-base est une dépendance d'exécution. Facultativement encore, l'IPv6 : une ULA /64, des Router Advertisements émis par ce même dnsmasq, et du NAT66 sur ip6tables — et comme le forwarding IPv6 n'est pas par interface, l'activer fait de tout l'hôte un routeur, or un routeur ignore les annonces qu'il reçoit ; une porte minuscule et sans argument (marionnet-ipv6.sh) mémorise donc et restitue accept_ra. La carte de l'hôte, ses adresses et ses routes ne sont jamais nommées dans ce bloc : elles ne peuvent pas être touchées par lui.

(c), en détail — c'est le réseau de l'hôte, et cela ne peut pas être cadré. Un LAN bridge est la carte de l'hôte asservie à mnlan0, avec l'adresse IPv4 et la route par défaut de l'hôte déplacées sur le pont et l'adresse MAC de la carte clonée dessus. Il y en a exactement un par machine (une carte n'a qu'un maître), donc deux sessions Marionnet le partagent. À peser avant de l'accorder :

Le Wi-Fi est refusé (un point d'accès ne répond pas à plusieurs adresses MAC derrière une seule association), de même qu'une carte déjà asservie au pont de quelqu'un d'autre, ou une route par défaut ambiguë.

7.3 Accorder (b) sans (c)

C'est le défaut, et il n'y a rien à faire pour l'obtenir : un install nu n'accorde que (a), et aucun des deux blocs de pont n'est jamais accordé à l'installation. Quand un utilisateur démarre un composant bridge, Marionnet demande son propre mot de passe sudo et installe ce bloc — (c) est donc déjà réservé aux comptes qui peuvent faire du sudo à l'exécution, bien après l'installation faite par l'administrateur.

Pour donner d'avance le NAT bridge à une salle, sans qu'aucun mot de passe soit demandé et sans que (c) entre jamais en jeu :

sudo marionnet-sudoers.sh install --enable-natbridge %marionnet

et, symétriquement, pour retirer un bloc en laissant le socle tranquille :

sudo marionnet-sudoers.sh uninstall --disable-lanbridge      # tous les comptes
sudo marionnet-sudoers.sh uninstall --disable-lanbridge <user>

7.4 Interdire un bloc pour de bon

Retirer une autorisation n'empêche pas l'utilisateur suivant de la redemander, depuis l'interface, avec son propre mot de passe. Un administrateur qui ne veut pas qu'un LAN bridge soit construit sur cette machine — jamais, par personne — le dit une fois :

sudo marionnet-sudoers.sh deny --lanbridge     # ou --natbridge, ou --bridges

Tant que ce veto est en place : le bloc est refusé à tout le monde, l'autorisation déjà en place est reprise (la laisser ferait du veto un mensonge), et Marionnet le dit dans son interface au lieu de demander un mot de passe. On le lève par sudo marionnet-sudoers.sh allow --lanbridge — ce qui n'accorde rien : un utilisateur doit toujours demander. N'importe qui peut consulter l'état, sans aucun privilège :

marionnet-sudoers.sh policy          # rc 0 si autorisé, 3 si interdit ; il dit lequel

Le veto est un fichier de /etc/marionnet/, lisible par tous à dessein : Marionnet doit connaître la réponse avant de demander un mot de passe, et un fichier de /etc/sudoers.d/ est en 0440 root, comme il se doit.

Le socle — bloc (a) — n'a pas de veto : c'est l'administrateur qui l'accorde à la main, donc l'interdire reviendrait à ne pas taper la commande. Et un veto arrête une erreur, pas un administrateur déterminé, qui édite /etc/sudoers.d/ directement. Là où il mord, c'est la configuration ordinaire d'une salle — un enseignant qui peut faire du sudo, des étudiants qui ne peuvent pas — et c'est exactement là qu'un LAN bridge se construit par accident.

7.5 Le lancer, et contrôler l'installation

marionnet                    # ou : marionnet -r lab.mar, marionnet --exam, marionnet --help

marionnet est le nom que tape chaque page de cette documentation — le guide de l'enseignant, le mode examen, les exemples du canal de contrôle, les scripts de TP. C'est un lien symbolique vers marionnet.native, le nom que dune install donne à l'exécutable : le même programme, sous le nom qu'emploie un humain.

Deux commandes répondent à « cette installation est-elle bien celle que je crois ? », quelle que soit la méthode qui l'a posée :

marionnet -v                 # version et révision
marionnet --paths            # où cette installation cherche images, noyaux et scripts

--paths est la réponse à « les images n'apparaissent pas » : il affiche les répertoires que la cascade de configuration a effectivement résolus (§ 5).

Et une commande répond à « reste-t-il quelque chose à faire ? » — la même que les canaux apt et dnf lancent après l'installation, ce qui explique que vous en ayez peut-être déjà lu la sortie :

marionnet-setup-check.sh          # en root, pour que le fichier sudoers soit examiné aussi

Elle mesure au lieu de réciter : elle ne dit rien quand rien ne manque, et quand quelque chose manque, elle nomme quoi — l'état de la règle sudoers (§ 7.1), les images et les noyaux absents, la commande qui les rapatrierait. Sur une autorisation périmée, elle affiche les commandes exactes qu'un rafraîchissement gagnerait et perdrait, sur cette machine, au lieu de citer un exemple qui pourrait n'être vrai qu'ailleurs.

8. Désinstaller Marionnet

Dans les trois cas, la règle sudoers n'ayant jamais été accordée par l'installation, elle n'est pas retirée par la désinstallation : sudo marionnet-sudoers.sh uninstall.

9. Quand quelque chose ne marche pas

Symptôme Ce que c'est
server down, no route, wrong URL? alors que le site est debout pas de magasin de certificats — § 1
apt dit que le dépôt est ignoré, et apt-get update sort quand même avec 0 même cause, ou la ligne du sources.list a été modifiée ; apt rapporte cela comme un avertissement
Missing key <empreinte>, ou signature verification failed le fichier de /etc/apt/keyrings/ n'est pas la clef de l'archive — récupérez-la de nouveau (§ 2) et comparez l'empreinte
apt continue de proposer le paquet alors qu'il vient de refuser le dépôt il réutilise l'index qu'il avait déjà : sudo rm -rf /var/lib/apt/lists/* puis apt update
Failed to import OpenPGP keys, ou dnf annonce que le dépôt n'a aucun paquet le fichier de clef du § 3 est absent, n'a pas été accepté, ou n'est pas une clef du tout — récupérez-le de nouveau et contrôlez l'empreinte avant d'importer
le tarball est refusé, en nommant une glibc votre distribution est plus ancienne que le plancher de compilation — § 4
marionnet-kernels-i386 est refusé, en nommant libc6:i386 dpkg --add-architecture i386 — § 2
Marionnet démarre mais les images invitées n'apparaissent pas elles ont été déposées sous un préfixe que l'application ne lit pas — § 5, puis marionnet --paths
Unsatisfied dependency au démarrage vde2 ou graphviz manque ; l'install.sh du tarball nomme ce qui manque, --with-deps l'installe
une machine virtuelle refuse de démarrer, les taps ne peuvent pas être construits la règle sudoers — § 7
rien ne s'ouvre quand un invité lance wireshark ou xterm le bloc (a) n'est pas accordé (§ 7.2), ou l'hôte n'a pas d'affichage X
marionnet-sudoers.sh install refuse, en nommant un chemin et un propriétaire une porte doit appartenir à root de bout en bout — § 7. Typique d'une installation sous un préfixe qui vous appartient
la règle est installée, et sudo demande quand même un mot de passe une entrée plus large de /etc/sudoers.d/ est analysée après la nôtre et gagne — § 7.1, état 5
visudo ou sudo rejette le fichier entier sur Ubuntu 26.04 des règles écrites par un Marionnet antérieur aux portes : sudo marionnet-sudoers.sh install <utilisateur> les réécrit — § 7
le contrôle répète que l'autorisation est périmée, quoi que vous fassiez un Marionnet plus ancien que celui livré avec cette page, sur une distribution RPM : son contrôle avait besoin de diff, que ces images ne portent pas, et lisait l'outil manquant comme un périmé — la mise à jour est le remède

Où aller ensuite

Ces pages sont installées à côté de celle-ci ; sauf mention contraire, elles sont en anglais. Elles vivent dans doc-src/ du dépôt des sources, qui est aussi là où est publiée la clef d'archive des § 2 et § 3 :

git clone https://git.launchpad.net/marionnet
Page À lire pour
INSTALL.md cette même page en anglais — c'est elle qui fait foi
teacher-guide.md préparer un TP, conduire la séance, la noter
scripting/README.md piloter Marionnet depuis un script, par le canal de contrôle
exam-mode.md ce qu'une session d'examen enregistre
project-format-v3.md le format de projet .mar