393 lines
12 KiB
Markdown
393 lines
12 KiB
Markdown
\newpage
|
||
|
||
Mise en place
|
||
=============
|
||
|
||
Pour réaliser ce TP, vous allez avoir besoin de créer une machine virtuelle,
|
||
possédant les caractéristiques suivantes :
|
||
|
||
- 1 disque de quelques Gio ;
|
||
- 1 lecteur de CD-ROM ;
|
||
- 1 interface réseau `virtio`, sur laquelle il sera possible d'obtenir une IP
|
||
permettant d'aller sur Internet.
|
||
|
||
Le choix de la technologie de virtualisation est laissé à votre
|
||
appréciation. L'ISO est réputée supportée par *Hyper-V* (Windows), *qemu*/*KVM*
|
||
(macOS, Linux, Windows) et VMware (macOS, Windows).\
|
||
|
||
L'hyperviseur qui vous laissera le plus de liberté (et avec lequel vous pourrez
|
||
apprendre le plus de choses !) est sans doute *qemu*, sous Linux ; vous pouvez
|
||
le lancer avec la commande :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
qemu-system-x86_64
|
||
```
|
||
</div>
|
||
|
||
Cette commande se trouve dans le paquet `qemu` (ArchLinux/Gentoo/Fedora),
|
||
`qemu-system-x86` (Debian/Ubuntu), `qemu-system-x86_64` (alpine).
|
||
|
||
|
||
L'image d'installation
|
||
----------------------
|
||
|
||
Vous pouvez télécharger l'ISO du TP depuis
|
||
<https://adlin.nemunai.re/resources/tuto2.iso>.
|
||
|
||
Cette image contient un système Debian minimaliste, en partie préinstallé afin
|
||
de vous permettre de commencer à travailler sans plus attendre !
|
||
|
||
|
||
Gérer le réseau de son hyperviseur
|
||
----------------------------------
|
||
|
||
::::: {.more}
|
||
|
||
Cette section est là pour vous donner un aperçu du fonctionnement de votre
|
||
installation, pour que plus jamais, vous ne puissiez vous demander « On la met
|
||
en NAT ou en Bridge la VM ? », sans vraiment savoir de quoi vous parler.
|
||
|
||
On vous encourage évidemment à comprendre les éléments présentés et à tester
|
||
par vous-même avec `qemu`, mais tous les hyperviseurs fonctionnent de la même
|
||
manière et vous pouvez donc tester avec votre hyperviseur habituel.
|
||
|
||
:::::
|
||
|
||
Rares sont les machines qui, aujourd'hui, ne sont pas connectées à Internet (ou
|
||
au moins à un réseau local, pour permettre d'y apporter les mises à jour).
|
||
|
||
La première chose qu'il va falloir faire avec notre hyperviseur, est donc de
|
||
lui indiquer comment notre machine virtuelle accédera au réseau.\
|
||
|
||
::::: {.question}
|
||
|
||
Nous ne présenterons ici que les méthodes qui permettent d'obtenir un
|
||
réseau ayant toutes les caractéristiques d'utilisation et de contrôle que l'on
|
||
pourrait en attendre. Nous ne verrons donc pas le mode `user` de *qemu* par
|
||
exemple.
|
||
|
||
:::::
|
||
|
||
### Interface physique
|
||
|
||
Tout d'abord, il faut savoir qu'il n'est pas possible, avec du matériel
|
||
habituel, de partager une interface réseau entre plusieurs machines (qu'elles
|
||
soient virtuelles ou qu'il s'agisse de la machine hôte).
|
||
|
||
Ainsi, si notre machine possède une seule carte réseau et que le système hôte
|
||
l'utilise pour accéder au réseau, il ne sera pas possible de l'assigner à une
|
||
machine virtuelle.
|
||
|
||
En revanche, si notre machine possède 2 interfaces ou plus, il sera alors
|
||
possible d'assigner à chaque machine sa propre interface, dans la limite du
|
||
nombre d'interfaces physiques existantes.
|
||
|
||
Concrètement, l'opération est assez fastidieuse à réaliser à la main, car cela
|
||
demande de détacher le périphérique (via
|
||
<span lang="en-US">`/sys/bus/pci/devices/0000:03:00.0/driver/unbind`</span>,
|
||
par exemple pour une carte `enp0s3`) ; avant de l'assigner à notre machine
|
||
virtuelle :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
qemu-system-x86_64 [...] -device pci-assign,host=03:00.0
|
||
```
|
||
</div>
|
||
|
||
|
||
### Interface virtuelle
|
||
|
||
On se rend compte que la solution d'avoir une interface physique par machine
|
||
virtuelle n'est pas bien pérenne et devient vite très onéreuse.
|
||
|
||
La solution qui s'offre à nous est donc de virtualiser la carte ethernet :
|
||
notre hyperviseur va alors **émuler** le comportement d'une carte (*qemu* émule
|
||
des cartes PCI `e1000` ou `rtl8139` pour les plus connues) : côté machine
|
||
virtuelle, l'hyperviseur va communiquer sur le bus PCI virtualisé, tandis que
|
||
côté hôte, il va créer une nouvelle interface virtuelle (de type `tap`), se
|
||
comportant comme un tunnel vers la machine virtuelle.
|
||
|
||
Pour attacher une carte réseau à notre machine virtuelle et créer l'interface
|
||
correspondante sur l'hôte, ce sera grâce à la commande :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
qemu-system-x86_64 [...] -net nic,model=e1000 -net tap,ifname=tap0,script=no,downscript=no
|
||
```
|
||
</div>
|
||
|
||
Avec cette solution, la machine hôte est capable de communiquer avec ses
|
||
machines virtuelles, après avoir assigné des IP aux interfaces correspondantes.
|
||
Il faut alors assigner une IP à l'interface de la machine hôte, et à la machine
|
||
virtuelle.
|
||
|
||
Par exemple : nous assignerons `172.23.69.1/31` à l'interface dans notre
|
||
machine virtuelle et `172.23.69.0/31` à l'interface correspondante de
|
||
l'hôte. Ainsi, l'hôte pourra contacter cette machine virtuelle à
|
||
`172.23.69.1/31`, et inversement.
|
||
|
||
#### Virtio
|
||
|
||
Parmi les périphériques que peut émuler *qemu*, il y a le contrôleur un peu
|
||
particulier `virtio`. Ce pilote va, conjointement avec un support adapté côté
|
||
système d'exploitation invité, permettre de se passer de la couche
|
||
d'émulation : les paquets seront directement envoyés par le système hôte dans un
|
||
format compréhensible sans effort, par le système invité.
|
||
|
||
Ce principe a été introduit par la paravirtualisation (utilisé notamment par
|
||
Xen) : au moyen d'un noyau spécialement conçu (soit pour être hôte, soit pour
|
||
être invité), l'hôte et l'invité peuvent communiquer entre-eux directement,
|
||
sans passer par une couche d'émulation du matériel.
|
||
|
||
`virtio` peut également être utilisé pour se passer de l'émulation des
|
||
contrôleurs de disques.
|
||
|
||
|
||
### Pont réseau // switch virtuel
|
||
|
||
Un pont réseau va nous permettre de faire communiquer entre-elles plusieurs
|
||
interfaces (qu'elles soient physiques ou virtuelles).
|
||
|
||
Pour créer un nouveau pont, on utilise la commande `ip` comme suit :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
ip link add name br0 type bridge
|
||
```
|
||
</div>
|
||
|
||
où `br0` est le nom que l'on souhaite attribuer à l'interface.
|
||
|
||
|
||
Pour assigner à un pont une interface, on utilise la commande suivante :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
ip link set veth0 master br0
|
||
```
|
||
</div>
|
||
|
||
où `veth0` est le nom de l'interface que l'on souhaite inclure dans le pont
|
||
`br0`.
|
||
|
||
|
||
Pour consulter la liste des interfaces concentrées par le pont `br0` :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
ip link show master br0
|
||
```
|
||
</div>
|
||
|
||
La création d'un pont entre plusieurs interfaces va donc créer un réseau de
|
||
machines, celles-ci pourront donc se parler, à condition que leurs IP fassent
|
||
partie du même sous-réseau. Généralement, il convient préalablement de retirer
|
||
toute IP que l'on aurait précédemment assignée à une interface, avant de lui
|
||
faire rejoindre le pont. En effet, c'est le pont qui va porter l'IP de la
|
||
machine hôte sur ce réseau virtuel.
|
||
|
||
Il est tout à fait possible d'ajouter une interface réseau physique à un pont,
|
||
et c'est sans doute la méthode la plus simple pour que les machines virtuelles
|
||
puissent accéder à internet : si le réseau local de la machine hôte fourni des
|
||
adresses IP par DHCP à toute machine rejoignant le réseau.
|
||
|
||
|
||
Lorsque le pont existe, `qemu` peut créer l'interface virtuelle et l'assigner à
|
||
un pont directement, avec la commande :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
qemu-system-x86_64 [...] -net bridge,br=br0
|
||
```
|
||
</div>
|
||
|
||
|
||
### NAT
|
||
|
||
Dans certaines situations, il n'est pas aussi simple d'avoir une IP ou de
|
||
communiquer avec le réseau utilisé par la machine hôte : par exemple, si le
|
||
nombre d'IP disponibles n'est pas suffisant par rapport au nombre de machines
|
||
que l'on a besoin de créer, ou bien parce que le réseau nécessite d'être
|
||
authentifié (netsoul, portail captif, ...) et qu'il est difficile ou inadapté
|
||
de réaliser cette authentification dans chaque machine virtuelle.
|
||
|
||
Il convient alors ici d'avoir un pont *host-only networking*. Dans cette
|
||
configuration, les machines virtuelles obtiendront une IP via un serveur DHCP
|
||
lancé sur l'hôte et pourront donc communiquer entre-elles et avec l'hôte, sur
|
||
un réseau privé.
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
dnsmasq --interface=br0 --bind-interfaces --dhcp-range=172.20.0.2,172.20.255.254
|
||
```
|
||
</div>
|
||
|
||
Afin que les machines virtuelles puissent accéder à Internet, il est nécessaire
|
||
de faire du NAT.
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
sysctl -w net.ipv4.ip_forward=1
|
||
iptables -t nat -A POSTROUTING -o wlp3s0 -j MASQUERADE
|
||
```
|
||
</div>
|
||
|
||
où `wlp3s0` correspond à l'interface de notre route par défaut.
|
||
|
||
|
||
Démarrer la machine virtuelle
|
||
-----------------------------
|
||
|
||
::::: {.more}
|
||
|
||
Comme pour la section précédentes, les exemples sont donnés pour `qemu`. Ils
|
||
sont à adapter en fonction de votre hyperviseur. Avec `qemu`, les exemples sont
|
||
à combiner avec la ligne de commande établie précédemment, il faut accumuler
|
||
les arguments avant de lancer la machine virtuelle.
|
||
|
||
:::::
|
||
|
||
### Ajouter un disque vierge
|
||
|
||
Pour réaliser ce TP, nous aurons besoin d'un disque vierge :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
qemu-img create -f qcow2 /tmp/disk.qcow2 4G
|
||
```
|
||
</div>
|
||
|
||
Ce disque sera à attacher à notre machine virtuelle de cette manière :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
qemu-system-x86_64 [...] -drive file=/tmp/disk.qcow2
|
||
```
|
||
</div>
|
||
|
||
|
||
### Démarrer sur l'ISO
|
||
|
||
Tout comme le disque, nous utilisons ici le paramètre `-drive` pour donner un
|
||
ISO de CD :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
qemu-system-x86_64 [...] -boot d -drive format=raw,media=cdrom,readonly,file=tuto2.iso
|
||
```
|
||
</div>
|
||
|
||
Notez également l'option `-boot d` qui change l'ordre de démarrage de la
|
||
machine, afin qu'elle ne teste que le lecteur de CD virtuel.
|
||
|
||
|
||
Connexion
|
||
---------
|
||
|
||
Si la machine ne se connecte pas au réseau toute seule, vous allez devoir
|
||
l'aider en reproduisant les étapes que nous avons apprises au TP précédent.
|
||
|
||
### Requête DHCP
|
||
|
||
Sur un réseau IPv4, un serveur héberge généralement un serveur DHCP. Le but
|
||
d'un tel serveur est de distribuer des adresses IP, dans la plage qui aura été
|
||
déterminée, ainsi que tous les paramètres du réseau, afin de faciliter son
|
||
utilisation.
|
||
|
||
Sur un réseau IPv6, le protocole DHCP n'est plus nécessaire car plusieurs
|
||
mécanismes de découverte automatique permettent à la pile IPv6 de se configurer
|
||
seule.
|
||
|
||
Pour dialoguer avec un serveur DHCP, il convient de lancer un client DHCP sur
|
||
la machine que l'on souhaite configurer : `udhcpc`, `dhcpcd`, `isc-dhcp-client`
|
||
(`dhclient`), etc. Généralement, ces clients prennent en argument l'interface
|
||
réseau à configurer.
|
||
|
||
|
||
### Vérification des paramètres IP
|
||
|
||
Parmi les configurations généralement effectuées automatiquement par le serveur
|
||
DHCP, on trouve les éléments suivants :
|
||
|
||
#### Lien
|
||
|
||
L'activation du lien est la première étape qu'effectue le client DHCP, afin de
|
||
pouvoir émettre un paquet sur le réseau.
|
||
|
||
<div lang="en-US">
|
||
```
|
||
42sh$ ip link
|
||
1: enp3s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT
|
||
^^^^^^^^^^
|
||
```
|
||
</div>
|
||
|
||
Manuellement, l'état d'un lien se change avec la commande :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
ip link set enp3s0 up
|
||
```
|
||
</div>
|
||
|
||
|
||
#### Adresses
|
||
|
||
Après avoir reçu la validation (paquet `DHCPACK`) du serveur DHCP, l'IP est
|
||
définie sur l'interface, via une méthode similaire à la commande :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
ip address add 192.168.0.42/24 dev enp3s0
|
||
```
|
||
</div>
|
||
|
||
|
||
#### Routes
|
||
|
||
Parmi toutes les informations embarquées dans un paquet DHCP, figure
|
||
généralement la route par défaut, permettant de localiser la passerelle du
|
||
réseau : le routeur conduisant généralement à Internet.
|
||
|
||
<div lang="en-US">
|
||
```
|
||
42sh$ ip route
|
||
default via 192.168.0.254 dev enp3s0
|
||
192.168.0.0/24 dev enp3s0 proto kernel scope link src 192.168.0.42
|
||
```
|
||
</div>
|
||
|
||
Sur un réseau IPv6, les routes sont obtenues grâce au *Neighbor Discovery
|
||
Protocol* : chaque routeur émet à intervalle régulier ou sur sollicitation un
|
||
paquet détaillant ses routes.
|
||
|
||
|
||
Manuellement, on ajoute une route par défaut avec la commande :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
ip route add default via 192.168.0.254
|
||
```
|
||
</div>
|
||
|
||
La route directe d'accès au réseau local (ici `192.168.0.0/24`) est
|
||
automatiquement créée lors de l'assignation de l'IP à l'interface en question.
|
||
|
||
|
||
#### Résolveur de noms de domaine
|
||
|
||
La dernière chose que l'on a généralement besoin de configurer pour pouvoir
|
||
accéder pleinement à Internet, c'est un serveur de noms de domaine.
|
||
|
||
Les informations relatives à la résolution de noms sont inscrites dans le
|
||
fichier `/etc/resolv.conf` :
|
||
|
||
<div lang="en-US">
|
||
```
|
||
nameserver 9.9.9.9
|
||
```
|
||
</div>
|
||
|
||
Pour plus d'informations à ce sujet, consultez le `man 5 nsswitch.conf`.
|