Comment commencer Ă  utiliser le mode utilisateur sous Linux

Introduction par le traducteur : Avec l'entrĂ©e massive de divers types de conteneurs dans nos vies, il peut ĂȘtre intĂ©ressant et utile de se rappeler d'oĂč tout cela a commencĂ©. Certaines de ces technologies peuvent encore ĂȘtre mises Ă  profit aujourd'hui, mais peu de gens se souviennent de ces mĂ©thodes (ou ne les connaissent pas, s'ils n'Ă©taient pas lĂ  pendant leur dĂ©veloppement intense). L'une de ces technologies est le User Mode Linux. L'auteur de l'original a creusĂ© en profondeur pour dĂ©terminer quelles anciennes rĂ©alisations fonctionnent encore et lesquelles ne sont plus d'actualitĂ©, et elle a rassemblĂ© une sorte de guide Ă©tape par Ă©tape sur comment configurer son propre UML en 2019. Et oui, nous avons invitĂ© sur Habr l'auteur de l'article original. Cadey, donc si vous avez des questions, posez-les en anglais dans les commentaires.

Comment commencer Ă  utiliser le mode utilisateur sous Linux

Le User Mode sous Linux est, en fait, un port du noyau Linux sur lui-mĂȘme. Ce mode permet de lancer un noyau Linux complet en tant que processus utilisateur et est gĂ©nĂ©ralement utilisĂ© par les dĂ©veloppeurs pour tester des pilotes. Mais ce mode est Ă©galement utile comme outil d'isolation gĂ©nĂ©rale, dont le principe est similaire Ă  celui des machines virtuelles. Ce mode offre une plus grande isolation que Docker, mais moins qu'une machine virtuelle complĂšte comme KVM ou Virtual Box.

Dans l'ensemble, le User Mode peut sembler ĂȘtre un outil Ă©trange et complexe Ă  utiliser, mais il a nĂ©anmoins ses domaines d'application. C'est un noyau Linux complet, fonctionnant sous un utilisateur non privilĂ©giĂ©. Cette caractĂ©ristique permet d'exĂ©cuter un code potentiellement peu fiable sans aucune menace pour la machine hĂŽte. Et comme il s'agit d'un noyau complet, ses processus sont isolĂ©s de la machine hĂŽte, c'est-Ă -dire que les processus fonctionnant Ă  l'intĂ©rieur du User Mode ne seront pas visibles pour l'hĂŽte. Cela ne ressemble pas Ă  un conteneur Docker traditionnel, dans lequel la machine hĂŽte voit toujours les processus Ă  l'intĂ©rieur du conteneur. Regardez ce morceau de pstree d'un de mes serveurs :

containerd─┬─containerd-shim─┬─tini─┬─dnsd───19*[{dnsd}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─aerial───21*[{aerial}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─s6-svscan───s6-supervise
           │                 │      └─surl
           │                 └─9*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─h───13*[{h}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─goproxy───14*[{goproxy}]
           │                 └─9*[{containerd-shim}]
           └─32*[{containerd}]

Et comparez cela avec pstree du noyau Linux en mode utilisateur :

linux─┬─5*[linux]
      └─slirp

Lorsque je travaille avec des conteneurs Docker, je peux voir depuis l'hÎte les noms des processus qui s'exécutent dans le systÚme invité. Cela n'est pas possible avec le mode utilisateur Linux. Que signifie cela ? Cela signifie que les outils de surveillance fonctionnant via le sous-systÚme d'audit Linux (le sous-systÚme d'audit de Linux) ne voient pas les processus s'exécutant dans le systÚme invité. Mais dans certaines situations, cette caractéristique peut devenir une arme à double tranchant.

En fait, tout le post ci-dessous est une sĂ©rie de recherches et de tentatives brutales pour obtenir le rĂ©sultat dĂ©sirĂ©. Pour cela, j'ai dĂ» utiliser divers anciens outils, lire le code source du noyau, faire de l'intense dĂ©bogage de code Ă©crit Ă  une Ă©poque oĂč j'Ă©tais encore Ă  l'Ă©cole primaire, ainsi que fouiller dans les builds de Heroku Ă  l'aide d'un binaire spĂ©cial Ă  la recherche des outils dont j'avais besoin. Tout ce travail a conduit Ă  ce que les gars dans mon IRC commencent Ă  m'appeler magicienne (magic). J'espĂšre que ce post servira de documentation fiable Ă  quelqu'un pour rĂ©aliser exactement la mĂȘme chose, mais avec des kernels et des versions de systĂšmes d'exploitation plus rĂ©cents.

Configuration

La configuration du mode utilisateur Linux se fait en plusieurs étapes :

  • installation des dĂ©pendances sur l'hĂŽte ;
  • tĂ©lĂ©chargement du noyau Linux ;
  • configuration de la compilation du noyau ;
  • compilation du noyau ;
  • installation du binaire ;
  • configuration du systĂšme de fichiers invitĂ© ;
  • choix des paramĂštres de lancement du noyau ;
  • configuration du rĂ©seau invitĂ© ;
  • lancement du noyau invitĂ©.

Je suppose que si vous dĂ©cidez de faire tout cela par vous-mĂȘme, vous allez probablement le faire sur un systĂšme basĂ© sur Ubuntu ou Debian. J'ai essayĂ© de mettre en Ɠuvre tout ce qui prĂ©cĂšde sur ma distribution prĂ©fĂ©rĂ©e - Alpine, mais cela n'a pas fonctionnĂ©, apparemment Ă  cause du fait que le noyau Linux a une liaison stricte avec les glibc-isms pour les pilotes en mode utilisateur. Je prĂ©vois d'en faire part en amont aprĂšs avoir complĂštement compris le problĂšme.

Installation des dépendances sur l'hÎte

Ubuntu nécessite au minimum les paquets suivants pour compiler le noyau Linux (en cas d'installation propre) :

- 'build-essential'
- 'flex'
- 'bison'
- 'xz-utils'
- 'wget'
- 'ca-certificates'
- 'bc'
- 'linux-headers'

Vous pouvez les installer avec la commande suivante (avec les droits root ou avec sudo) :

apt-get -y install build-essential flex bison xz-utils wget ca-certificates bc 
                   linux-headers-$(uname -r)

Veuillez noter que l'exécution du programme de configuration de menu pour le noyau Linux nécessitera l'installation de libncurses-dev. Veuillez vous assurer qu'il est installé avec la commande suivante (avec les droits root ou avec sudo) :

apt-get -y install libncurses-dev

Téléchargement du noyau

Déterminez l'emplacement pour télécharger et ensuite compiler le noyau. Pour cette opération, vous aurez besoin de libérer environ 1,3 Go d'espace disque, alors assurez-vous de l'avoir.

Ensuite, allez sur kernel.org et obtenez l'URL pour télécharger la derniÚre version stable du noyau. Au moment de la rédaction du post, c'est : https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Téléchargez ce fichier en utilisant 'wget':

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Et décompressez-le avec 'tar':

tar xJf linux-5.1.16.tar.xz

Maintenant, entrez dans le répertoire créé lors de l'extraction du tarball :

cd linux-5.1.16

Configuration de la compilation du noyau

Le systÚme de compilation du noyau est un ensemble de fichiers Make avec avec de nombreux outils personnalisés et scripts pour automatiser le processus. Pour commencer, ouvrez le programme de configuration interactif :

make ARCH=um menuconfig

Il guidera partiellement la compilation et vous affichera une fenĂȘtre de dialogue. Lorsque ‘[Select]‘ apparaĂźt en bas de la fenĂȘtre, vous pouvez vous occuper de la configuration avec les touches Espace ou EntrĂ©e. La navigation dans la fenĂȘtre se fait normalement avec les flĂšches de direction « haut » et « bas », et la sĂ©lection des Ă©lĂ©ments se fait « Ă  gauche » ou « Ă  droite ».

Un indicateur de type -> signifie que vous ĂȘtes dans un sous-menu, auquel vous accĂ©dez par la touche EntrĂ©e. Pour sortir de celui-ci, Ă©videmment, appuyez sur ‘[Exit]‘.

Activez les paramĂštres suivants dans ‘[Select]‘ et assurez-vous qu'un symbole ‘[*]’ soit Ă  cĂŽtĂ© d'eux :

Options spécifiques à UML :
  - SystĂšme de fichiers hĂŽte
Support réseau (activez cela pour afficher le sous-menu) :
  - Options réseau :
    - Réseau TCP/IP
Dispositifs réseau UML :
  - Dispositif réseau virtuel
  - Transport SLiRP

Vous pouvez quitter cette fenĂȘtre, en sĂ©lectionnant successivement ‘[Exit]‘. Assurez-vous simplement qu'Ă  la fin, il vous sera demandĂ© de sauvegarder la configuration et que vous sĂ©lectionnez ‘[Oui]‘.

Je vous recommande de jouer avec les paramÚtres de compilation du noyau aprÚs avoir lu ce post. Grùce à ces expériences, vous pourrez beaucoup apprendre sur le fonctionnement des mécanismes de bas niveau du noyau et l'impact de divers drapeaux sur sa compilation.

Compilation du noyau

Le noyau Linux est un grand programme qui s'occupe de nombreuses choses. MĂȘme avec une configuration minimale sur du matĂ©riel ancien, sa compilation peut prendre un certain temps. Donc, compilez le noyau avec la commande suivante :

make ARCH=um -j$(nproc)

Pourquoi ? Cette commande dira à notre compilateur d'utiliser tous les cƓurs et threads de processeur disponibles pendant le processus de compilation. La commande $(nproc) à la fin de Build remplace la sortie de la commande nproc, qui fait partie de coreutils dans la compilation standard d'Ubuntu.

AprÚs un certain temps, notre noyau sera compilé dans un fichier exécutable ./linux.

Installation du binaire

Étant donnĂ© que le Mode Utilisateur dans Linux crĂ©e un binaire normal, vous pouvez l'installer comme n'importe quel autre utilitaire. Voici comment je l'ai fait :

mkdir -p ~/bin
cp linux ~/bin/linux

Il est également utile de s'assurer que ~/bin est présent dans votre $PATH:

export PATH=$PATH:$HOME/bin

Configuration du systÚme de fichiers invité

Créez un répertoire pour le systÚme de fichiers invité :

mkdir -p $HOME/prefix/uml-demo
cd $HOME/prefix

Ouvrez alpinelinux.org et dans la section des téléchargements trouvez le lien de téléchargement actuel pour MINI ROOT FILESYSTEM. Au moment de la rédaction de cette publication, c'était :

http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gz

Téléchargez ce tarball en utilisant wget :

wget -O alpine-rootfs.tgz http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gz

Maintenant, accédez au répertoire du systÚme de fichiers invité et décompressez l'archive :

cd uml-demo
tar xf ../alpine-rootfs.tgz

Ces actions créeront un petit modÚle de systÚme de fichiers. En raison des spécificités du systÚme, il sera trÚs difficile d'installer des paquets via le gestionnaire apk d'Alpine. Mais ce systÚme de fichiers suffira pour évaluer l'idée générale.

Nous aurons Ă©galement besoin d'un outil tini pour empĂȘcher la consommation de mĂ©moire par les processus zombies de notre noyau invitĂ©.

wget -O tini https://github.com/krallin/tini/releases/download/v0.18.0/tini-static
chmod +x tini

Création de l'invite de commande du noyau

Dans le noyau Linux, comme dans la plupart des autres programmes, il existe des arguments de ligne de commande que vous pouvez consulter en utilisant la clé --help.

self —help

linux --help
User Mode Linux v5.1.16
        disponible sur http://user-mode-linux.sourceforge.net/

--showconfig
    Affiche le fichier de configuration à partir duquel ce binaire UML a été généré.

iomem=,
    Configure  comme une région de mémoire IO nommée .

mem=
    Cela contrÎle combien de "mémoire physique" le noyau alloue
    pour le systÚme. La taille est spécifiée comme un nombre suivi de
    l'une des lettres 'k', 'K', 'm', 'M', qui ont les significations évidentes.
    Cela n'est pas lié à la quantité de mémoire dans l'hÎte. Elle peut
    ĂȘtre plus grande, et l'excĂ©dent, s'il est jamais utilisĂ©, sera simplement Ă©changĂ©.
        Exemple : mem=64M

--help
    Affiche ce message.

debug
    ce flag n'est pas nécessaire pour exécuter gdb sur UML en mode skas

root=
    Cela est en fait utilisĂ© par le noyau gĂ©nĂ©rique de la mĂȘme
    maniĂšre que dans n'importe quel autre noyau. Si vous configurez un certain nombre de dispositifs de bloc
    et souhaitez démarrer autre chose que ubd0, vous
    utiliseriez quelque chose comme :
        root=/dev/ubd5

--version
    Affiche le numéro de version du noyau.

umid=
    Cela est utilisé pour assigner une identité unique à cette machine UML et
    est utilisé pour nommer le fichier pid et le socket de la console de gestion.

con[0-9]*=
    Attache une console ou une ligne série à un canal hÎte. Voir
    http://user-mode-linux.sourceforge.net/old/input.html pour une description complĂšte de ce commutateur.

eth[0-9]+=,
    Configure un dispositif réseau.
    
aio=2.4
    Cela est utilisĂ© pour forcer UML Ă  utiliser le style AIO de 2.4 mĂȘme lorsque l'AIO de 2.6 est
    disponible. L'AIO de 2.4 est un seul thread qui gĂšre une requĂȘte Ă  la
    fois, de maniĂšre synchrone. L'AIO de 2.6 est un thread qui utilise l'interface AIO de 2.6
    pour gĂ©rer un nombre arbitraire de requĂȘtes en attente. L'AIO de 2.6
    n'est pas disponible en mode tt, sur des hĂŽtes 2.4, ou lorsque UML est construit avec
    /usr/include/linux/aio_abi.h non disponible. De nombreuses distributions n'incluent pas
    aio_abi.h, donc vous devrez le copier d'un arbre de noyau vers
    votre /usr/include/linux afin de construire un UML compatible AIO

nosysemu
    Désactive le patch d'émulation de syscall pour ptrace (SYSEMU).
    SYSEMU est un patch de performance introduit par Laurent Vivier. Il change
    le comportement de ptrace() et aide à réduire les taux de changement de contexte de l'hÎte.
    Pour le faire fonctionner, vous avez également besoin d'un patch de noyau pour votre hÎte.
    Voir http://perso.wanadoo.fr/laurent.vivier/UML/ pour plus d'informations.

uml_dir=
    L'emplacement pour placer les fichiers pid et umid.

quiet
    Désactive les messages d'information pendant le démarrage.

hostfs=,,...
    Cela est utilisé pour définir les paramÚtres hostfs. L'argument du répertoire racine
    est utilisé pour confiner tous les montages hostfs dans l'arborescence de répertoire spécifiée
    sur l'hÎte. Si cela n'est pas spécifié, alors un utilisateur à l'intérieur d'UML peut
    monter tout ce qui est accessible à l'utilisateur qui l'exécute sur l'hÎte.
    Le seul flag actuellement supporté est 'append', qui spécifie que tous
    les fichiers ouverts par hostfs seront ouverts en mode ajout.

Ce drapeau met en lumiÚre les principaux paramÚtres de démarrage. Exécutons le noyau avec le minimum d'options nécessaires :

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  init=/bin/sh

Les lignes ci-dessus indiquent Ă  notre noyau ce qui suit :

  • Supposons que le systĂšme de fichiers racine soit un pseudo-dispositif /dev/root.
  • Choisissez hostfs comme pilote du systĂšme de fichiers racine.
  • Montez le systĂšme de fichiers invitĂ© que nous avons créé sur le dispositif root.
  • Et oui, en mode lecture-Ă©criture.
  • Utilisez seulement 64 mĂ©gaoctets de mĂ©moire vive (vous pouvez utiliser beaucoup moins, selon ce que vous prĂ©voyez de faire, mais 64 Mo semblent ĂȘtre une quantitĂ© optimale).
  • Le noyau dĂ©marre automatiquement /bin/sh comment init-processus.

Exécutez cette commande, et vous devriez obtenir quelque chose comme ce qui suit :

Une autre feuille

Limites de vidage de mémoire :
        doux - 0
        dur - AUCUN
Vérification que ptrace peut changer les numéros d'appel systÚme...OK
Vérification du patch d'émulation d'appel systÚme pour ptrace...OK
Vérification du patch d'émulation d'appel systÚme avancé pour ptrace...OK
Vérification des variables d'environnement pour un répertoire temporaire...aucun trouvé
Vérification si /dev/shm est sur tmpfs...OK
Vérification de PROT_EXEC mmap dans /dev/shm...OK
Ajout de 32137216 octets à la mémoire physique pour tenir compte de l'écart d'exécution
Version de Linux 5.1.16 (cadey@kahless) (version gcc 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #30 Dim Jul 7 18:57:19 UTC 2019
1 zonelists construit, regroupement de mobilité activé. Total des pages : 23898
Ligne de commande du noyau : root=/dev/root rootflags=/home/cadey/dl/uml/alpine rootfstype=hostfs rw mem=64M init=/bin/sh
Entrées de la table de hachage du cache Dentry : 16384 (order : 5, 131072 octets)
Entrées de la table de hachage du cache Inode : 8192 (order : 4, 65536 octets)
Mémoire : 59584K/96920K disponible (2692K code noyau, 708K rwdata, 588K rodata, 104K init, 244K bss, 37336K réservé, 0K cma-réservé)
SLUB : HWalign=64, Ordre=0-3, MinObjects=0, CPUs=1, NƓuds=1
NR_IRQS : 15
source d'horloge : minuteur : masque : 0xffffffffffffffff max_cycles : 0x1cd42e205, max_idle_ns : 881590404426 ns
Calibrage de la boucle de délai... 7479.29 BogoMIPS (lpj=37396480)
pid_max : défaut : 32768 minimum : 301
Entrées de la table de hachage du cache de montage : 512 (order : 0, 4096 octets)
Entrées de la table de hachage du cache de point de montage : 512 (order : 0, 4096 octets)
Vérification que les ptys hÎtes supportent la sortie SIGIO...Oui
Vérification que les ptys hÎtes supportent SIGIO à la fermeture...Non, activation du contournement
devtmpfs : initialisé
aléatoire : get_random_bytes appelé depuis setup_net+0x48/0x1e0 avec crng_init=0
Utilisation de 2.6 hĂŽte AIO
source d'horloge : jiffies : masque : 0xffffffff max_cycles : 0xffffffff, max_idle_ns : 19112604462750000 ns
Entrées de la table de hachage futex : 256 (order : 0, 6144 octets)
RÉSEAU : Protocole enregistrĂ© famille 16
source d'horloge : Changement vers la source d'horloge minuteur
RÉSEAU : Protocole enregistrĂ© famille 2
tcp_listen_portaddr_hash entrées de la table de hachage : 256 (order : 0, 4096 octets)
Entrées de la table de hachage TCP établies : 1024 (order : 1, 8192 octets)
Entrées de la table de hachage TCP de liaison : 1024 (order : 1, 8192 octets)
TCP : Tables de hachage configurées (établi 1024 liaison 1024)
Entrées de la table de hachage UDP : 256 (order : 1, 8192 octets)
Entrées de la table de hachage UDP-Lite : 256 (order : 1, 8192 octets)
RÉSEAU : Protocole enregistrĂ© famille 1
console [stderr0] désactivée
mconsole (version 2) initialisée sur /home/cadey/.uml/tEwIjm/mconsole
Vérification du support de MADV_REMOVE par l'hÎte...OK
workingset : timestamp_bits=62 max_order=14 bucket_order=0
Pilote du générique SCSI de la couche bloc (bsg) version 0.4 chargé (maj 254)
scheduler d'E/S noop enregistré (par défaut)
scheduler d'E/S bfq enregistré
loop : module chargé
RÉSEAU : Protocole enregistrĂ© famille 17
Pilote de console stdio initialisé
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 1 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 2 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 3 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 4 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 5 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 6 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 7 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 8 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 9 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 10 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 11 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 12 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 13 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 14 : Échec de la configuration
Utilisation d'un type de canal configuré hors de UML
setup_one_line a Ă©chouĂ© pour le dispositif 15 : Échec de la configuration
Console initialisée sur /dev/tty0
console [tty0] activée
console [mc-1] activée
Échec de l'initialisation du dispositif ubd 0 : Impossible de dĂ©terminer la taille du fichier du dispositif
VFS : SystÚme de fichiers racine monté (systÚme de fichiers hostfs) sur le dispositif 0:11.
devtmpfs : monté
Cette architecture n'a pas de protection de la mémoire du noyau.
Exécutez /bin/sh en tant que processus init
/bin/sh : impossible d'accéder à tty ; le contrÎle des tùches est désactivé
aléatoire : initialisation rapide terminée
/ # 

Les manipulations ci-dessus nous donneront un systÚme invité minimaliste, sans des éléments tels que /proc ou un nom d'hÎte attribué. Par exemple, essayez d'exécuter les commandes suivantes :

- uname -av
- cat /proc/self/pid
- hostname

Pour quitter le systÚme invité, tapez exit ou appuyez sur control-d. Cela va provoquer un crash shell avec un kernel panic suivant :

/ # exit
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
fish: “./linux root=/dev/root rootflag
” terminated by signal SIGABRT (Abort)

Nous avons rencontrĂ© ce kernel panic parce que le noyau Linux considĂšre que le processus d'initialisation est toujours en cours. Sans lui, le systĂšme ne peut plus fonctionner et s'arrĂȘte. Mais comme il s'agit d'un processus du mode utilisateur, le rĂ©sultat obtenu s'envoie lui-mĂȘme Ă  SIGABRT, ce qui entraĂźne la sortie.

Configuration du réseau invité

C'est ici que les choses commencent Ă  ne pas se dĂ©rouler comme prĂ©vu. Le rĂ©seau dans User Mode Linux est l'endroit oĂč toute la notion de "mode utilisateur" limitĂ© commence Ă  s'effondrer. En effet, gĂ©nĂ©ralement, au niveau systĂšme, le rĂ©seau est limitĂ© Ă  des niveaux d'exĂ©cution privilĂ©giĂ©s pour des raisons qui nous sont comprĂ©hensibles.

Note de l'éditeur : vous pouvez en savoir plus sur les différentes options de travail avec le réseau dans UML ici.

Voyage dans slirp

Cependant, il existe un ancien outil presque obsolĂšte appelĂ© Slirp, qui permet Ă  User Mode Linux d'interagir avec le rĂ©seau. Il fonctionne un peu comme une pile TCP/IP au niveau utilisateur et ne nĂ©cessite aucune autorisation systĂšme pour fonctionner. Cet outil a Ă©tĂ© lancĂ© en 1995, et la derniĂšre mise Ă  jour date de 2006.Slirp est trĂšs ancien. Pendant le temps sans support et mises Ă  jour, les compilateurs ont Ă©voluĂ© au point qu'il ne peut maintenant ĂȘtre qualifiĂ© que de «dĂ©gradation du code».

Alors, installons Slirp depuis les dépÎts Ubuntu et essayons de le faire fonctionner :

sudo apt-get install slirp
/usr/bin/slirp
Slirp v1.0.17 (BETA)

Copyright (c) 1995,1996 Danny Gasparovski et autres.
Tous droits réservés.
Ce programme est protégé par le droit d'auteur, logiciel libre.
Veuillez lire le fichier COPYRIGHT qui accompagne le paquet Slirp
pour les termes et conditions du droit d'auteur.

Adresse IP de l'hĂŽte Slirp : 127.0.0.1
Adresse IP de vos DNS : 1.1.1.1, 10.77.0.7
Votre adresse est 10.0.2.15
(or tout autre que vous souhaitez)

Tapez cinq zéros (0) pour quitter.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]

SLiRP prĂȘt ...
fish : “/usr/bin/slirp” terminĂ© par signal SIGSEGV (Erreur de limites d'adresse)

Oh mon Dieu. Installons un débogueur pour Slirp et voyons si nous pouvons comprendre ce qui se passe ici :

sudo apt-get install gdb slirp-dbgsym
gdb /usr/bin/slirp
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/slirp...Reading symbols from /usr/lib/debug/.build-id/c6/2e75b69581a1ad85f72ac32c0d7af913d4861f.debug...done.
done.
(gdb) run
Starting program: /usr/bin/slirp
Slirp v1.0.17 (BETA)

Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.

IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)

Type five zeroes (0) to exit.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]

SLiRP Ready ...

Program received signal SIGSEGV, Segmentation fault.
                                                    ip_slowtimo () at ip_input.c:457
457     ip_input.c: No such file or directory.

Une erreur s'est produite dans cette ligne. Regardons la trace de la pile, peut-ĂȘtre que cela pourra nous aider :

(gdb) bt full
#0  ip_slowtimo () at ip_input.c:457
        fp = 0x55784a40
#1  0x000055555556a57c in main_loop () at ./main.c:980
        so = 
        so_next = 
        timeout = {tv_sec = 0, tv_usec = 0}
        ret = 0
        nfds = 0
        ttyp = 
        ttyp2 = 
        best_time = 
        tmp_time = 
#2  0x000055555555b116 in main (argc=1, argv=0x7fffffffdc58) at ./main.c:95
No locals.

Ici, nous voyons que le plantage se produit pendant le lancement de la boucle principale, lorsque slirp essaie de vĂ©rifier les dĂ©lais d'attente. À ce moment, j'ai dĂ» abandonner mes tentatives de dĂ©bogage. Mais voyons si Slirp, compilĂ© Ă  partir des sources, fonctionne. J'ai tĂ©lĂ©chargĂ© Ă  nouveau l'archive directement depuis le site Sourceforge, car tirer des fichiers Ă  partir de lĂ  via la ligne de commande est pĂ©nible :

cd ~/dl
wget https://xena.greedo.xeserv.us/files/slirp-1.0.16.tar.gz
tar xf slirp-1.0.16.tar.gz
cd slirp-1.0.16/src
./configure --prefix=$HOME/prefix/slirp
make

Ici, nous voyons des alertes concernant des fonctions intégrées non définies, c'est-à-dire l'impossibilité de lier le fichier binaire résultant. Il semble qu'entre 2006 et ce moment, gcc a cessé de créer des symboles utilisés dans les fonctions intégrées des fichiers intermédiaires compilés. Essayons de remplacer le mot-clé inline par un commentaire vide et voyons le résultat :

vi slirp.h
:6
a

#define inline /**/

:wq
make

Non, cela ne fonctionne pas non plus. Il n'est toujours pas possible de trouver les caractĂšres de ces fonctions.

À ce stade, j'ai abandonnĂ© et commencĂ© Ă  chercher sur Github les paquets de compilation de Heroku. Ma thĂ©orie Ă©tait que dans l'un des paquets de compilation de Heroku, il y aurait les fichiers binaires nĂ©cessaires. En fin de compte, mes recherches m'ont menĂ© ici. J'ai tĂ©lĂ©chargĂ© et extrait uml.tar.gz et j'ai trouvĂ© ce qui suit :

total 6136
-rwxr-xr-x 1 cadey cadey   79744 10 déc.  2017 ifconfig*
-rwxr-xr-x 1 cadey cadey     373 13 déc.  2017 init*
-rwxr-xr-x 1 cadey cadey  149688 10 déc.  2017 insmod*
-rwxr-xr-x 1 cadey cadey   66600 10 déc.  2017 route*
-rwxr-xr-x 1 cadey cadey  181056 26 juin  2015 slirp*
-rwxr-xr-x 1 cadey cadey 5786592 15 déc.  2017 uml*
-rwxr-xr-x 1 cadey cadey     211 13 déc.  2017 uml_run*

C'est un fichier binaire slirp ! Et il fonctionne ?

./slirp
Slirp v1.0.17 (BETA) FULL_BOLT

Copyright (c) 1995,1996 Danny Gasparovski et autres.
Tous droits réservés.
Ce programme est protégé par le droit d'auteur, logiciel libre.
Veuillez lire le fichier COPYRIGHT qui vient avec le paquet Slirp
pour les termes et conditions du copyright.

Adresse IP de l'hĂŽte Slirp : 127.0.0.1
Adresse IP de votre(s) DNS : 1.1.1.1, 10.77.0.7
Votre adresse est 10.0.2.15
(ou tout ce que vous voulez)

Tapez cinq zéros (0) pour sortir.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500]

SLiRP PrĂȘt ...

Il ne plante pas — donc cela devrait fonctionner ! Mettons ce binaire dans ~/bin/slirp:

cp slirp ~/bin/slirp

Au cas oĂč le crĂ©ateur du paquet le supprimerait, j'ai fait un miroir.

Configuration du réseau

Maintenant, configurons le réseau sur notre noyau invité. Mettons à jour les paramÚtres de démarrage:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/bin/sh

Maintenant, activons le réseau :

mount -t proc proc proc/
mount -t sysfs sys sys/

ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
route add default gw 10.0.2.2

Les deux premiĂšres commandes de configuration /proc et /sys sont nĂ©cessaires au fonctionnement ifconfig, qui Ă©tablit l'interface rĂ©seau pour communiquer avec Slirp. La commande route Ă©tablit la table de routage du noyau pour forcer tout le trafic Ă  passer par le tunnel Slirp. VĂ©rifions cela avec une requĂȘte DNS :

nslookup google.com 8.8.8.8
Serveur :    8.8.8.8
Adresse 1 : 8.8.8.8 dns.google

Nom :      google.com
Adresse 1 : 172.217.12.206 lga25s63-in-f14.1e100.net
Adresse 2 : 2607:f8b0:4006:81b::200e lga25s63-in-x0e.1e100.net

Ça marche!

Note : Il semblerait que le post original ait été écrit sur un ordinateur de bureau avec une carte réseau filaire, ou dans une autre configuration ne nécessitant pas de pilotes supplémentaires. Sur un ordinateur portable avec un Wi-Fi 8265 d'Intel, l'activation du réseau entraßne une erreur

/ # ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
slirp_tramp failed - errno = 2
ifconfig: ioctl 0x8914 failed: No such file or directory
/ #

Apparemment, le noyau ne parvient pas à communiquer avec le pilote de la carte réseau. La tentative de compiler le firmware dans le noyau n'a malheureusement pas corrigé la situation. Au moment de la publication, aucune solution n'avait encore été trouvée dans cette configuration. Dans des configurations plus simples (par exemple, dans Virtualbox), l'interface se lÚve correctement.

Automatisons la redirection avec le script shell suivant :

#!/bin/sh
# init.sh

mount -t proc proc proc/
mount -t sysfs sys sys/
ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
route add default gw 10.0.2.2

echo "networking set up"

exec /tini /bin/sh

Et rendons-le exécutable :

chmod +x init.sh

Ensuite, modifions la ligne de commande du noyau :

linux 
  root=\/dev\/root 
  rootfstype=hostfs 
  rootflags=$HOME\/prefix\/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME\/bin\/slirp 
  init=\/init.sh

Et répétons :

SLiRP prĂȘt ...
réseau configuré
\/bin\/sh : impossible d'accéder au tty ; le contrÎle des travaux est désactivé

nslookup google.com 8.8.8.8
Serveur :    8.8.8.8
Adresse 1 : 8.8.8.8 dns.google

Nom :      google.com
Adresse 1 : 172.217.12.206 lga25s63-in-f14.1e100.net
Adresse 2 : 2607:f8b0:4004:800::200e iad30s09-in-x0e.1e100.net

Le réseau fonctionne de maniÚre stable !

Fichier Docker

Pour vous aider Ă  vĂ©rifier tout cela, j'ai rassemblĂ© Dockerfile, qui automatise la plupart des Ă©tapes dĂ©crites et doit vous fournir une configuration fonctionnelle. J'ai aussi une configuration du noyau prĂȘte, qui inclut tout ce qui est dĂ©crit dans le post. Mais il est important de comprendre que je n'ai exposĂ© ici que la configuration minimale.

J'espĂšre que ce post vous aidera Ă  comprendre comment dĂ©marrer un noyau invitĂ©. Cela s'est transformĂ© en un monstre, mais je voulais que cette publication soit un guide complet sur la construction, l'installation et la configuration de User Mode sous Linux pour les versions modernes de ce systĂšme d'exploitation. Les prochaines Ă©tapes devraient inclure l'installation de services et d'autres logiciels Ă  l'intĂ©rieur du systĂšme invitĂ©. Comme les images de conteneurs Docker sont simplement des archives tar dĂ©compressĂ©es, vous devriez ĂȘtre en mesure d'extraire l'image via docker export, puis de dĂ©finir le chemin de son installation Ă  la racine du systĂšme de fichiers du noyau invitĂ©. Ensuite, exĂ©cutez le script shell.

Un grand merci à Rkeene de #lobsters sur Freenode. Sans son aide pour déboguer Slirp, je ne serais pas allée aussi loin. Je n'ai aucune idée de comment son systÚme Slackware fonctionne correctement avec slirp, mais mes systÚmes Ubuntu et Alpine n'ont pas accepté slirp ni le binaire proposé par Rkeene. Mais je me contente et de ce que j'ai qui fonctionne au moins.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster