La magie du chroot...

Le changement de racine est un aspect des Unix offrant une alternative très intéressante à la virtualisation. Éminemment plus léger, mais surtout plus simple à mettre en oeuvre, qu'un VirtualBox, KVM, ou même docker, le petit utilitaire chroot peut vous rendre bien des services pour emprisonner un accès FTP, pour créer une machine de développement avec des versions de librairies différentes de celle de votre système principal ou encore simplement pour tester les derniers joujous dans une version instable de debian.

Qu'est-ce qu'un chroot?

Comme vous le savez sûrement déjà, le système fichier d'un *NIX est construit autour d'une racine (le /) sur laquelle les partitions sont ensuite "montées" formant ainsi l'espace de fichier accessible. Cette racine est la référence pour tous les chemins absolus utilisés par un processus lui permettant d'accéder aux fichiers (librairies, configurations, etc.) qui lui sont nécessaires.

Ce que l'on sait moins c'est que cette racine est un paramètre du processus qu'il est parfaitement possible de modifier grace à l'utilitaire chroot. Pour quoi faire me direz-vous ? Tout simplement pour faire croire à ce processus que le dossier que nous lui avons arbitrairement fixé comme racine, est l'origine de tous ses chemins absolus.

Le cadre d'usage de cette technique est vaste. Elle permet par exemple de lancer des processus critiques dans un dossier isolé du reste du système de sorte à rendre plus difficile (mais pas impossible !) la compromission du reste du système de fichier en cas d'exploitation d'une faille de sécurité. C'est ce que l'on appelle mettre en prison le processus (jail).

Elle permet aussi de créer des environnements qui fonctionnent sur des règles différentes du reste du système. Il est ainsi possible de faire tourner une debian au sein d'une mandriva, ou encore un linux en 32bits au sein d'un linux 64 bits. La seule limitation est que le kernel doit être compatible entre les deux distributions.

Mais même si cela sonne terriblement comme de la virtualisation il est important de ne pas confondre les deux principes. Le changement de racine n'émule absolument rien. Ce n'est que l'exploitation d'une propriété des processus unix. Chaque processus chrooté accède donc au même matériel que les processus "normaux". De même ils tournent au sein du même kernel et partagent le même espace mémoire. Plus flagrant, les processus lancés dans le cadre d'un changement de racine sont parfaitement visible si l'on exécute une commande ps à partir d'un shell "normal".

Et c'est là finalement la grande force du changement de racine. C'est un principe limité mais simple, et qui ne souffre d'aucun problème de performance accompagnant généralement la virtualisation.

Construction d'un dossier chrootable

Il y a d'innombrables manière de créer un dossier utilisable pour un changement de racine. Tout dépend au fond du besoin derrière la manipulation. Si l'on désire chrooter un service FTP par exemple, on va s'attacher à ne mettre dans le dossier que les fichiers strictement nécessaires au processus : l'exécutable, ses librairies et ses fichiers de configurations, placé avec soin dans une arborescence qui mime parfaitement ce que l'on trouverait sur une racine réelle. Il existe des utilitaires qui aident à effectuer ce genre de tâche mais ce n'est pas forcement l'approche la plus didactique.

Pour notre exemple, voyons plutôt comment créer une debian complète dans notre racine de sorte à y placer une pile Apache, PostgreSql et PHP.

La première chose à faire est d'installer dans un dossier de votre choix une installation de la distribution Debian. Il est possible de faire bêtement une copie de la racine principale, cela marcherait très bien, mais ce serait sûrement très volumineux.

Heureusement, il existe un outil debian qui fait des miracles debootstrap. Notez que cet outil n'est pas spécifique à Debian et fonctionne aussi très bien sous Mandriva. Nous allons donc installer la commande et la lancer pour installer une wheezy tout neuve

gastonsudo aptitude install debootstrap
gastonsudo debootstrap --include=locales-all wheezy ma_racine http://ftp.fr.debian.org/debian
installation de la racine

Le paramètre --include indique à debootstrap des paquets supplémentaires à installer, ici les locales. Suit la version de debian à installer et le dossier dans lequel effectuer les opérations. Si ce dossier n'existe pas il sera créé. Enfin nous avons l'url des paquets debian en france.

Une fois lancée, la commande va jaquasser un petit moment pour installer tout cela. Lorsque c'est terminé, vous avez une mini debian d'environ 356Mo.

La debian est installée et déjà totalement fonctionnelle. Vous pouvez donc lancer votre premier changement de racine

on met un petit fichier témoin dans la racine
gastonsudo echo "Je suis dans ma racine..." | sudo tee ma_racine/ça_marche.txt > /dev/null

lancement d'un bash en chroot
gastonsudo chroot ma_racine /bin/bash

On vérifie que ça a bien marche...
rootcat /ça_marche.txt
Je suis dans ma racine...
premier chroot

Et voilà, nous sommes dans notre bash chrooté. Mais que c'est il passé exactement ?

  1. La commande chroot engendre un processus qui a pour racine la même que celle de son processus parent, généralement le / (mais rien n'empêche de se la jouer matryoshka ;-).

  2. En interne, chroot appel de la fonction kernel chroot("/ma_racine"). Le kernel va donc modifier la valeur de la racine pour ce processus et lui associer la valeur /ma_racine.

  3. Le processus de chroot, exécute la commande passée en 2nd paramètre, /bin/bash. Comme la racine de chroot a été changée, c'est bien le /bin/bash de la nouvelle racine /ma_racine qui va être exécuté.

  4. Cette exécution débouche sur la création d'un processus fils de celui du chroot qui hérite logiquement de cette nouvelle racine.

  5. Tout ce que /bin/bash lancera par la suite héritera de cette nouvelle racine jusqu'à ce que l'on tape exit qui mettra fin au processus /bin/bash, et par domino à celui du chroot qui a permis son lancement.

Ok, le bash c'est bien mignon mais voyons comment aller un peu plus loin.

Dossiers spéciaux

Notre debian a besoin d'un plus que les fichiers installés pour fonctionner. En effet pour accéder au matériel il lui faudra les fameux dossier /proc et /sys. Dans un premier temps, nous allons faire cela à la main.

rootmount proc /proc -t proc
rootmount sysfs /sys -t sysfs
Montage des dossiers spéciaux

Ok, là on lance cela à la main. Mais rien n'empêche de créer dans la nouvelle racine un fichier /etc/fstab pour automatiser tout cela et de lancer carrément init q pour lancer un système complet. Personnellement, je préfère coller bien sagement les deux montages dans un script de ce genre

cd /chemin/vers/ma_racine
sudo mount --bind /proc proc
sudo mount --bind /sys sys
sudo chroot . /bin/bash
sudo umount sys
sudo umount proc

Techniquement cela revient au même, sauf qu'au lieu de monter les dossiers spéciaux au sein de la racine, on les monte de l'extérieur en les liant aux dossiers principaux. L'avantage c'est que lorsque vous sortirez de la racine, les deux dossiers seront automatiquement démontés. Il est aussi possible de lancer autre chose que bash, comme par exemple un script qui va lancer apache... Le truc s'est qu'il faudra tuer apache pour arrêter le chroot :-)

Installation d'apache

Maintenant le système est complet, nous pouvons commencer à installer des choses comme nous en avons l'habitude.

rootaptitude install libapache2-mod-php5
installation de l'apache et PHP

Si, lors de l'installation, dpkg a essayé de lancer apache et a échoué lamentablement, c'est sans doute parce que vous avez déjà un apache qui tourne sur votre machine. Et comme il squate l'interface réseau, notre apache parent pauvre se voit signifier une fin de non recevoir.

La solution la plus efficace est simplement d'ajouter une adresse IP à votre interface réseau physique. Imaginons que cette interface s'appelle eth0 et que votre IP est 10.0.0.1, nous allons lui ajouter 10.0.0.2 :

ifconfig eth0:0 192.168.154.110
Ajoutd d'une adresse IP

Ceci fait, il ne reste plus qu'à modifier, tant sur l'apache principal que celui de la racine, le fichier /etc/apache2/ports.conf de sorte à préciser l'adresse à utiliser pour la directive Listen. Ce sera Listen 10.0.0.1:80 pour le principal et 10.0.0.2 pour le secondaire. Il ne reste maintenant plus qu'à redémarrer d'abord le principal, puis le secondaire.

Maintenant il ne reste plus qu'à tester, en tapant dans votre navigateur http://10.0.0.2, et normalement, It Works!.

Conclusion

Le chrooting est une base fondamentale. C'est cette même base qui a été fortement améliorée pour donner naissance au principe de conteneurs avec par exemple LXC. Et c'est LXC qui à son tour a servi de base au très célèbre Docker. Mais ça, c'est une autre histoire...

Vus : 4010
Publié par Artisan Numérique : 100