Le meilleur moyen d'empêcher un UML de tourner

Solution rapide: déployez des vservers, et vous serez certains que les administrateurs des sous-domaines vserver seront incapables, ou fortement gênés dans le démarrage d’un noyau User-Mode Linux.

Ceci, pour plusieurs raisons qui ont trait à la conception des vservers.

Pour ceux qui ne savent pas, je résume. Vserver est une solution de virtualisation de machine, permettant en gros de découper une machine physique en N machines virtuelles, chacune ayant son administrateur, ses logiciels, son IP, sa présence sur le net. La virtualisation peut intervenir à divers niveaux.

Certaines solutions, comme Xen, virtualisent intégralement la machine, ce qui permet de booter un noyau par machine virtuelle, et d’avoir une ségrégation qui est aussi totale que possible, et aussi un maximum de flexibilité au sein de la machine virtuelle, puisqu’on a un noyau entièrement fonctionnel.

D’autres, comme User Mode Linux, ne virtualisent pas totalement la machine, et utilisent à la place les capacités du noyau hote pour créer une machine dans la machine. C’est une solution assez amusante, qui n’en reste pas moins assez élégante, et qui permet de déployer un environnement fortement cloisonné un peu partout.

Enfin, d’autres, comme vserver, font une virtualisation de l’environnement d’exécution, et non de la machine. Ainsi, on a un seul noyau qui tourne sur la machine. Ce noyau, fortement patché, permet de créer plusieurs domaines cloisonnés, qui tournent comme des machines virtuelles. La séparation est rendue effective par le noyau, et par la modification de quelques librairies userspace. C’est une solution qui a l’avantage (theorique) d’avoir de meilleures performances, au prix d’une lourde perte en flexibilité dans les domaines virtualisés.

Ces pertes de flexibilité sont souvent dues à des capacités que les administrateurs du vserver retirent aux utilisateurs des domaines restreints, parce que ces capacités outrepassent le rideau de fumée que le noyau vserver établit pour faire croire à une séparation. Ainsi, passer l’interface réseau en mode promiscuous est proscrit, parce que le faire permettrait à un domaine de recevoir les paquets réseau de tous les domaines de la machine. De même, exit la fantaisie d’avoir un firewall configuré aux petits oignons: netfilter n’a pas été virtualisé par vserver, donc tous les domaines virtualisés tournent à nu, dans l’impossibilité de se firewaller.

Ces restrictions se ressentent peu quand on veut monter un serveur web de base. Par contre, on le sent bien passer quand on essaye, comme moi, de faire démarrer un noyau UML dans son domaine virtualisé vserver. Là, énormément des limitations dues à la conception (à mon avis foireuse pour la plupart des utilisations) de vserver viennent faire trébucher le noyau virtualisé.

La première embuche, c’est la mise en réseau. Une machine virtuelle UML peut se faire donner accès au réseau de multiples manières. De loin la plus simple, c’est tun/tap, le pilote linux qui permet à un logiciel de s’approprier une interface réseau virtuelle pour injecter des paquets IP dans la pile réseau du noyau. UML permet d’utiliser ca: le noyau virtualisé crée une interface tunX dans le noyau hote, et la transpose en eth0 dans la machine virtuelle. Tout ce qui transite sur eth0 dans la machine virtuelle finira sur tunX sur la machine hote, qu’on peut ensuite configurer pour router tout ca joyeusement.

Aha, mais oui mais non. Déjà, si tu croyais que dans ton vserver t’aurais le droit de créer une interface tun, ben t’as de bien beaux rêves. La virtualisation réseau de vserver est un fragile chateau de cartes, et tun la dedans est comme un ventilateur. Donc, exit le driver tun/tap dans le noyau vserver. Et puis bon, même si on l’avait, sans netfilter et avec le routage désactivé dans le domaine vserver (ben ouais, routage == possibilité de faire des trucs intéressants en réseau == le ventilateur d’avant, en version turboréacteur Rolls Royce), donc meme avec un tunX, impossible d’avoir le net.

Le fait de ne pas avoir de tunX élimine pour ainsi dire trois quarts des possibilités de mise en réseau qu’a UML. Heureusement, des hackers qui ont du un jour être dans la même situation que moi lui ont ajouté le support SLiRP. SLiRP, c’est un petit logiciel tout à fait bourrin, qui transforme tout shell que vous ouvririez en petit modem. SLiRP recoit des paquets sur son entrée standard, et s’occupe de les envoyer sur le vrai internet, en faisant croire que c’est des paquets à lui. Au retour, il rebalance ca sur la sortie standard. Connectez-y un pppd, et vous transformez n’importe quel compte ssh en un truc qui vous donne accès au net.

Ca parait inutile comme ca, puisque pour faire le ssh faut avoir le net. Ben non, justement! UML permet de configurer une interface réseau SLiRP. C’est à dire que c’est le noyau virtualisé qui lance SLiRP, et s’en sert pour avoir un accès au réseau de la machine hote (habituellement, internet). C’est un immonde hack, ca ne peut que vehiculer du TCP, ca ne permet pas (sauf configuration) de pouvoir se connecter à la machine virtuelle depuis l’extérieur, mais c’est tout ce qu’on peut avoir sur un vserver.

Mais, juste quand on pensait que c’était tout, non! Il y a mieux encore! Si si!

UML gère la mémoire physique de sa machine virtuelle assez simplement: il balance un gros fichier dans /tmp, qui contient l’image de la mémoire physique de la machine virtuelle. Comme dans nos machines modernes, /tmp est un mount tmpfs, ce qui correspond à un ramdisk, on se retrouve avec la mémoire physique de la machine virtuelle… En mémoire physique de la machine hote!

C’est élégant, c’est beau… Et vserver nous fout des batons dans les roues. En effet, de base, un domaine vserver virtualisé a effectivement un /tmp en mount tmpfs, nickel et tout. Sauf que la taille du mount est limitée à 16Mo. Ca fait 16Mo grand max pour la ram d’une machine virtuelle, soit pas beaucoup. Surtout qu’il faut aussi caser les fichiers temporaires de la machine hote dans ces 16Mo.

Bon, pas grave on se dit, puisque c’est comme ca, suffit de mounter un autre tmpfs ailleurs, et de dire a UML d’utiliser ca, non?

Ben non, parce que mount est un autre de ces chateaux de cartes dans le noyau vserver, et c’est pour ca que, étant root dans le domaine vserver, on se bouffe un “permission denied” quand on tente de mounter quoi que ce soit, ou que ce soit. C’est soit vserver qui mounte quelque chose, depuis le domaine de controle, soit c’est personne. Supaire.

Heureusement, UML est flexible, lui, et permet pour les gros bourrins de stocker son fichier de mémoire physique sur n’importe quel support, pas seulement un tmpfs. Ce qui fait que là, je boote une machine virtuelle sur un disque dur, plutot que de la ram. Si vous n’avez jamais vu ce que ca fait d’avoir une machine qui a 100% de swap et 0% de RAM, ben c’est à peu près ca. 2 minutes à démarrer alors que la machine est assez brutale, et qu’il n’y a rien comme services. Et une fois démarré, le load sur la machine hote est allègrement dans les 3.5, vu que le noyau virtualisé lui fait faire des I/O comme un barbare, pour écrire dans sa “ram”.

Bref, bravo vserver, tu as réussi a m’empêcher de faire un truc pourtant simple: ne pas donner d’accès en trop au vserver, en virtualisant l’un de ses services. Donc, cette machine virtuelle s’arrête maintenant pour de bon, puisqu’elle est dans l’impossibilité de faire ce qu’elle devrait faire correctement dans l’environnement de merde que vserver lui impose.

Et après, on se demande pourquoi je suis un partisan de la paravirtualisation totale de Xen. Elle oblige peut-être à booter N noyaux, mais non seulement l’hyperviseur Xen est plus flexible et robuste, mais il fait une séparation réelle des domaines virtualisés, si bien qu’on peut monter un firewall par domaine, qu’on peut monter des interfaces tun, qu’on peut router comme il nous plait, et qu’on peut administrer notre machine, bordel de tyrol!