Debian logo [inetdoc.LINUX]

12. Fonction TUN/TAP du noyau Linux

La solution retenue pour les communications réseau entre système hôte et machine virtuelle utilise la fonction TUN/TAP du noyau Linux. Cette solution est utilisée dans toutes les sections suivantes de ce document.

Indépendamment du contexte de la virtualistion, TUN/TAP est une fonction de réception et de transmission de paquets entre le noyau et les programmes de l'espace utilisateur. Cette fonction peut être vue comme une simple interface point à point ou Ethernet qui, au lieu de recevoir les paquets d'un média physique, les reçoit du programme de l'espace utilisateur. De même, cette interface au lieu d'envoyer les paquets vers un média physique, les transmet au programme de l'espace utilisateur.

Dans le contexte de ce document, le programme de l'espace mémoire utilisateur est l'instance virtuelle de système d'exploitation. L'interface réseau TUN/TAP devient un canal de communication réseau entre le système hôte et un système émulé via KVM (et|ou) QEMU.

Cette section se décompose en trois parties consacrées à la mise en œuvre d'une interface TAP. La première propose une configuration d'interface à partir de la session utilisateur alors que la deuxième et la troisième proposent une configuration permanente au niveau système. Seule la troisième partie est spécifique à la distribution Debian GNU/Linux. À l'usage et compte tenu de la faible empreinte mémoire du module tun, la deuxième ou la troisième solution sont à privilégier.

12.1. Configuration manuelle d'une interface TAP

La création d'une interface TAP doit se faire par l'intermédiaire d'un programme de l'espace mémoire utilisateur. Il existe deux méthodes classiques de création d'interface à partir des outils fournis avec les paquets de la distribution Debian GNU/Linux.

User-Mode Linux, uml-utilities

Ce paquet contient les programmes utilitaires liés à la solution User-Mode Linux qui permet «d'imbriquer» l'exécution de plusieurs noyaux Linux. L'utilitaire de manipulation des interfaces TUN/TAP est baptisé tunctl. Voici un exemple de séquence de configuration d'une interface TAP.

# tunctl -d tap0
Set 'tap0' nonpersistent
# tunctl -u etu -t tap0
Set 'tap0' persistent and owned by uid 1000
# ifconfig tap0
tap0      Link encap:Ethernet  HWaddr 00:ff:3b:71:37:bb
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:500
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

Comme la solution User-Mode Linux ne fait pas partie des outils utilisés dans le contexte de ce document, ce mode de configuration ne sera pas utilisé par la suite.

OpenVPN, openvpn

OpenVPN est une solution très populaire de mise en œuvre de réseaux privés virtuels (VPN) ou tunnels IP utilisant les fonctions de chiffrement, de certification et d'authentification de la bibliothèque OpenSSL.

La commande # openvpn --mktun --dev tap0 suffit à la création de l'interface TAP.

Comme OpenVPN est utilisé par ailleurs dans l'infrastructure des travaux pratiques de la filière STRI, c'est cette solution qui est retenue pour la création des interfaces TAP. Les informations de la version utilisée pour les manipulations sont les suivantes :

# dpkg -l openvpn |grep ^ii
ii  openvpn          2.1~rc15-1                virtual private network daemon

# openvpn --mktun --dev tap0
Wed May 14 21:22:52 2008 TUN/TAP device tap0 opened
Wed May 14 21:22:52 2008 Persist state set to: ON
# ifconfig tap0
tap0      Link encap:Ethernet  HWaddr 00:ff:11:82:55:fe
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:100
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

Si on retient l'utilisation d'openvpn pour créer l'interface tap0, il est préférable d'utiliser un script qui permet aussi de configurer cette interface sur le système hôte.

#!/bin/bash

# $Id: tap-up.sh 1305 2008-06-08 20:59:09Z latu $
# Run this tap interface setup script before KVM/QEMU launch
# Sudo should be configured with the two following tools allowed from user level
# user    ALL = NOPASSWD: /sbin/ifconfig, /usr/sbin/openvpn
# These scripts should be located in ~/bin as they are run at normal user level

if [ -z $1 ] || [ -z $2 ]; then
	echo "Usage: tap-up.sh {tap interface} {IP address}"
	exit 1
fi

TAP=`/sbin/ifconfig 2>/dev/null|grep $1|cut -d " " -f 1`

if [ "$TAP" != "$1" ];
then
	sudo /usr/sbin/openvpn --mktun --dev $1 >/dev/null 2>&1
fi
sudo /sbin/ifconfig $1 $2

Dans cet exemple, l'exécution du script est indépendante du lancement de l'instance de machine virtuelle. Cette configuration autonome de l'interface TAP correspond au cas le plus général.

Comme ce script est utilisé au niveau utilisateur normal, on suppose qu'il est stocké dans le répertoire ~/bin/. C'est habituellement dans ce répertoire que l'on retrouve l'ensemble des (programmes|scripts) exécutables propres au compte utilisateur.

12.2. Configuration système d'une interface TAP

Pour généraliser l'utilisation d'une interface TAP, il est possible de la paramétrer directement au niveau système dans le fichier de configuration des interfaces réseau. Voici un extrait de fichier /etc/network/interfaces.

# The tap network interface
auto tap0
iface tap0 inet static 1
        address 192.200.0.1
        netmask 255.255.255.224
        network 192.200.0.0
        broadcast 192.200.0.31
        pre-up /usr/sbin/openvpn --mktun --dev tap0 2
        post-up su phil -c "vde_switch -d -F --tap tap0 -s /tmp/vde.ctl -M /tmp/vde.mgmt" 3
        post-up iptables-restore </var/lib/iptables/active 4
        pre-down kill `ps -o pid -C vde_switch --no-headers` 5
        post-down /usr/sbin/openvpn --rmtun --dev tap0 6

1

La configuration de l'interface se présente avec les éléments classiques communs à n'importe quelle interface réseau IP statique configurée sur un système Debian GNU/Linux ou apparenté. On y trouve, l'adresse IP, le masque réseau, l'adresse du réseau ainsi que l'adresse de diffusion.

2

La directive pre-up permet de lancer la commande de création de l'interface au niveau système avant l'application des paramètres de configuration IP.

À ce niveau, l'appel à OpenVPN ne fait qu'installer le périphérique (device) tap0. On retrouve les traces de cette opération dans le journal de l'initialisation du système.

$ egrep  ' tap| tun' /var/log/kern.log
 tun: Universal TUN/TAP device driver, 1.6
 tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
 tap0: no IPv6 routers present
 tun0: Disabled Privacy Extensions

3

La directive post-up permet de lancer la commande d'initialisation du commutateur virtuel VDE après la configuration de l'interface tap0.

Comme pour l'interface réseau, l'empreinte mémoire du commutateur virtuel est suffisamment légère pour que l'on puisse rendre son chargement systématique sans pénaliser les performances du système hôte. De plus, cette interface tap0 constitue l'unique «lien montant» (uplink) du commutateur virtuel vers les autres réseaux. Il est donc logique d'associer le démarrage du commutateur à la configuration de l'interface.

L'utilisation du commutateur virtuel VDE est détaillée dans la Section 15, « Communications réseau en mode commutation virtuelle ».

Dans la configuration présentée ici, l'utilisateur phil est propriétaire du processus vde_switch et des sockets de communication.

4

La seconde directive post-up permet d'installer les règles de filtrage réseau consécutives à l'activation de l'interface.

L'objectif de ces règles de filtrage est de rendre l'utilisation du ou des réseau(x) virtuel(s) transparente vis-à-vis des réseaux réels situé «à l'extérieur» du système hôte. Il s'agit donc d'un cas classique de traduction d'adresse source sur les interfaces physiques de ce système hôte. Dans le cas de l'ordinateur «transportable» de l'enseignant, on peut trouver les règles suivantes.

# cat /var/lib/iptables/active
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -p tcp -m tcp --syn -m tcpmss --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu
-A POSTROUTING -o wlan0 -j MASQUERADE
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT

Même si l'opération n'est pas effectuée à ce niveau, on suppose que la fonction routage du noyau est activée pour les paquets IP puissent transiter entre l'interface tap0 et les autres interfaces réseau du système hôte.

# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

5

Avec la directive pre-down, on aborde les opérations d'arrêt de l'interface tap0.

Dans le cas présent, il s'agit d'arrêter le commutateur virtuel VDE en tuant le processus correspondant.

6

Enfin, la commande appelée par la directive post-down efface le canal de communication entre l'interface réseau virtuelle dans l'espace mémoire utilisateur et le sous-système réseau du noyau. Cette opération est effectuée une fois que les paramètres de configuration IP ont été supprimés et que l'interface est inactive.

12.3. Configuration Debian d'une interface TAP

Sur un système Debian GNU/Linux, il est possible configurer directement une interface TAP tout en initialisant le commutateur Virtual Distributed Ethernet. Cette méthode de configuration est très voisine de celle présentée dans la section ci-dessus. Elle ne se différencie que par l'utilisation des scripts fournis avec le paquet vde2. Si on reprend un extrait du fichier /etc/network/interfaces, on obtient la syntaxe suivante.

auto tap0
iface tap0 inet static
        address 192.200.0.1
        netmask 255.255.255.224
        network 192.200.0.0
        broadcast 192.200.0.31
        vde2-switch -

La dernière instruction : vde2-switch - déclenche l'initialisation du commutateur virtuel avec les attributs définis dans les scripts du paquet vde2.

$ ps aux | grep vde
/usr/bin/vde_switch -s /var/run/vde2/tap0.ctl \ 1
                    -m 660 -g vde2-net \ 2
                    -p /var/run/vde2/tap0.pid \
                    -t tap0 \
                    -M /var/run/vde2/tap0.mgmt --mgmtmode 660 \ 3
                    -d

L'ensemble des options de configuration du commutateur est présenté à la Section 15, « Communications réseau en mode commutation virtuelle ».

On relève cependant les éléments relatifs au groupe propriétaire du processus et à son masque de permissions.

1

Les canaux de communication avec le commutateur sont définis dans le répertoire /var/run/ comme pour n'importe quel autre service d'un système Debian GNU/Linux. Ici, le répertoire /var/run/vde2/ contient toutes les références de communication avec le processus vde_switch.

$ ll /var/run/ | grep vde
drwxrws--- 3 vde2-net   vde2-net   4,0K jun 27 14:12 vde2

L'utilisteur système vde2-net et les membres du groupe du même nom ont accès au contenu de ce répertoire qui contient le répertoire des sockets de communication, l'identifiant de processus et le socket de gestion de la configuration du commutateur.

2 3

Les valeurs numériques 660 correspondent au masque des permissions sur les objets du système de fichiers. Ces objets sont des sockets de type UNIX. La valeur numérique 660 correspond au masque rw-rw---- qui donne les droits de lecture et d'écriture exclusivement au propriétaire et au groupe.

D'après les éléments identifiés ci-dessus, il est nécessaire que le compte utilisateur «normal» appartienne au groupe vde2-net pour utiliser le commutateur et l'interface tap0. Si on reprend l'exemple de la section précédente, c'est le compte utilisateur phil qui est concerné.

$ cat /etc/group | grep vde
vde2-net:x:120:phil

Les scripts proposés avec le paquet vde2 assurent la configuration de l'interface tap0 mais non son activation. De plus, il manque la partie filtrage relativement à la section précédente. On implante donc un script supplémentaire dans le répertoire /etc/network/if-up.d/ qui se charge de ces opérations.

# cat /etc/network/if-up.d/tap0
#!/bin/sh

if [ -d "/proc/sys/net/ipv4/conf/tap0" ]
then
        /sbin/ifup tap0
fi

if [ -f "/var/lib/iptables/active" ]
then
        /sbin/iptables-restore </var/lib/iptables/active
fi

Une fois ce dernier script en place, on dispose d'une interface de communication fonctionnelle entre le système hôte et les instances de machines virtuelles.