#!⌨

LXC et connection au réseau par pont

Lorsqu'on crée des machines virtuelles avec libvirt ou VirtualBox, ces applications s'occupent de gérer les connections au réseau. Mais on n'utilise pas toujours libvirt ou VirtualBox. Dans mon cas, je voulais tester LXC (le site n'a pas l'air très frais...) afin de pouvoir bénéficier d'une machine virtuelle tout en économisant la mémoire vive. En effet, une fois que j'ai lancé gnome-shell, firefox et thunderbird, il ne reste plus beaucoup de mes 2 Go de mémoire vive ! LXC permet de cloisonner des processus et donc de lancer tout un système d'exploitation sans avoir à émuler du matériel.

Créer un environnement avec LXC est simple. Après avoir installé les outils (pacman -S lxc), il suffit de lancer lxc-create -n nom_de_la_machine -t debian pour créer une machine virtuelle nommée nom_de_la_machine en se basant sur le template debian. L'utilisation du template debian nécessite toutefois d'installer d'autres outils (comme dpkg et debootstrap).

Maintenant, on peut manipuler notre environnement Debian avec les commandes :
  • lxc-start -n nom_de_la_machine : démarre l'environnement. On pourra rajouter l'option -d pour lancer l'environnement en mode démon (enfin, simplement en arrière plan).
  • lxc-console -n nom_de_la_machine  : se connecte à l'environnement virtualisé.
  • lxc-stop -n nom_de_la_machine  : éteint l'environnement.
  • lxc-ls  : affiche les environnements disponibles.

De base, la machine créée n'est pas connetée au réseau. Nous allons donc voir comment configurer l'hôte et l'environnement virtualisé.

Plusieurs scénarios sont possibles. Ici, nous allons créer un réseau entre l'hôte et l'environnement virtualisé, puis configurer l'hôte pour servir de passerelle NAT. Le principe du réseau interne consiste à créer un pont réseau virtuel auquel la machine virtuelle et l'hôte vont se connecter. Voici les commandes pour créer le pont :

# sur l'hôte
brctl addbr lxcbr0
ifconfig lxcbr0 192.168.222.1 netmask 255.255.255.0 up

Maintenant, nous devons configurer notre environnement pour qu'au lancement, il crée une interface virtuelle qui fasse partie du pont. Il faut s'assurer que les lignes suivantes soient présentes dans /var/lib/lxc/nom_de_la_machine/config  :

lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = lxcbr0

Maintenant, on peut redémarrer l'environnement, puis configurer le réseau :

# sur l'environnement cloisonné
ifconfig eth0 192.168.222.2 netmask 255.255.255.0 up
route add default gw 192.168.222.1 dev eth0

À ce niveau, on peut constater que l'environnement a une interface :

[nom_de_la_machine]$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 6e:b2:2a:ef:1b:d6
          inet addr:192.168.222.2  Bcast:192.168.222.255  Mask:255.255.255.0
          inet6 addr: fe80::6cb2:2aff:feef:1bd6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:5469 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3135 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:7573740 (7.2 MiB)  TX bytes:245057 (239.3 KiB)

Et sur l'hôte, on constate qu'une interface a été créée et s'est enregistrée au pont :

[host]$ brctl show
bridge name   bridge id       STP enabled interfaces
lxcbr0        8000.fe4df3f631c5   no      vethFcOTZN
[host]$ ifconfig vethFcOTZN
vethFcOTZN: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::fc4d:f3ff:fef6:31c5  prefixlen 64  scopeid 0x20<link>
        ether fe:4d:f3:f6:31:c5  txqueuelen 1000  (Ethernet)
        RX packets 3135  bytes 245057 (239.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5469  bytes 7573740 (7.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Et les deux machines devraient se pinguer (ping 192.168.222.2 sur l'hôte et ping 192.168.222.1 sur l'environnement virtuel).

Maintenant, il suffit d'activer le NAT, et configurer le DNS sur l'environnement cloisonné :

# sur l'hôte
echo 1 > /proc/sys/net/ipv4/ip_forward
# wlp11s0 est mon interface relié à internet
iptables -t nat -A POSTROUTING -o wlp11s0 -j MASQUERADE

# configurer le DNS
cp /etc/resolv.conf /var/lib/lxc/nom_de_la_machine/rootfs/etc/

Et vous pourrez accèder au monde entier depuis l'environnement virtualisé !

Dans les autres options possibles, on pourrait relier directement l'interface virtuelle de notre environnement cloisonné vers l'interface reliée au réseau (mais je suis connecté au réseau par le wifi, et ce n'est apparemment pas supporté). On pourrait également configurer l'environnement par DHCP, utiliser un serveur DNS local... il y a beaucoup de scénarios possibles... À explorer !

Si LXC vous intéresse, un article assez complet a été publié dans GNU/Linux Magazine 159.