Choisir la configuration réseau au démarrage
Lorsque l'on dispose d'un portable que l'on promène par monts et par vaux, il peut être bien pratique de choisir son environnement réseau au démarrage de la machine. On n'a alors plus besoin d'activer/désactiver certaines interfaces réseau ni de les configurer une fois l'initialisation de la machine terminée. Ce document propose une méthode simple permettant d'atteindre cet objectif, basée sur le choix d'un réseau dans me menu de démarrage, une configuration du fichier /etc/network/interfaces
et un script de «mapping».
Configuration
Utilisation d'un paramètre au lancement du noyau
Depuis longtemps déjà, il est possible de spécifier des arguments à transmettre au noyau au démarrage de celui-ci. Parmi les plus connus citons root=/dev/XXXX
pour spécifier la partition racine du système, ou vga=XYZ
pour déterminer le mode graphique lors de la phase de démarrage.
Sur le système en fonctionnement, l'ensemble des paramètres transmis au noyau en fonctionnement est consigné dans le fichier /proc/cmdline
. Nous allons utiliser ce moyen pour préciser quel est l'environnement réseau que nous souhaitons activer. On ajoutera par exemple une directive du type :
net=home-wifi ou net=work-wired
à la liste des paramètres déjà présents.
Configuration des réseaux logiques
Au démarrage de la machine, le contenu du fichier /etc/network/interfaces
détermine quelles sont les interfaces physiques qui vont être activées, et de quelle manière (automatique, manuelle avec spécification de l'adresse IP…).
À chaque choix de réseau logique accessible dans le menu de démarrage nous allons faire correspondre une configuration particulière d'interface physique grâce à ce fichier /etc/network/interfaces
.
Récupération du paramètre lors de la configuration des interfaces réseau
Il ne nous reste plus qu'à récupérer, grâce à un script qui sera exécuté à l'intérieur de /etc/network/interfaces
, la valeur de paramètre définissant le réseau logique choisi. Sachant que l'ensemble des paramètres passés au noyau est disponible dans le fichier /proc/cmdline
; le script en question se contentera d'aller extraire la valeur de la chaîne de caractères qui suit la directive net=
et de remonter cette information aux instructions suivantes dans /etc/network/interfaces
.
Mise en œuvre
Modification du menu de démarrage
ce qui suit n'est plus d'actualité sur les version récentes d'Ubuntu qui utilisent grub-pc.
Le menu de démarrage est décrit dans le fichier /boot/grub/menu.lst
(le fonctionnement détaillé de grub est spécifié dans ce tutoriel). Chacune des entrées est représentée par un bloc dont la première ligne commence par le mot-clé title et dont la dernière comporte le mot-clé boot. En règle générale, on choisit toujours la même entrée (ou l'entrée par défaut) pour démarrer la machine. Sur mon système p. ex. le bloc correspondant est :
title Ubuntu, kernel 2.6.12-10-386 root (hd0,4) kernel /boot/vmlinuz-2.6.12-10-386 root=/dev/sda5 ro vga=771 quiet splash initrd /boot/initrd.img-2.6.12-10-386 savedefault boot
Afin de pouvoir choisir son réseau au démarrage, on va dupliquer ce bloc autant de fois qu'il y a de configurations réseau souhaitées. Dans mon cas, il y en a quatre : un mode «non-connecté» où aucune interface ne doit être activée que j'appellerai Standalone, un deuxième mode adapté à mon réseau domestique sans fil (Home Wifi) où seule l'interface WiFi doit être configurée, un troisième mode (Work WiFi) où je suis connecté au réseau d'entreprise par une borne WiFi, et enfin un dernier mode (Work Wired) utilisant un bon vieux câble Ethernet au cas où la borne WiFi de mon entreprise serait défaillante .
Seules les lignes title
et kernel
doivent être modifiées :
title
pour adapter le label qui sera proposé au démarrage,kernel
pour ajouter le paramètre noyau spécifique au réseau.
En remplacement du bloc précédent, mon /boot/grub/menu.lst
contiendra donc les quatre blocs ci-dessous :
title Ubuntu, kernel 2.6.12-10-386 Standalone root (hd0,4) kernel /boot/vmlinuz-2.6.12-10-386 root=/dev/sda5 ro vga=771 quiet splash initrd /boot/initrd.img-2.6.12-10-386 savedefault boot
title Ubuntu, kernel 2.6.12-10-386 Home WiFi root (hd0,4) kernel /boot/vmlinuz-2.6.12-10-386 root=/dev/sda5 ro vga=771 quiet splash net=home-wifi initrd /boot/initrd.img-2.6.12-10-386 savedefault boot
title Ubuntu, kernel 2.6.12-10-386 Work WiFi root (hd0,4) kernel /boot/vmlinuz-2.6.12-10-386 root=/dev/sda5 ro vga=771 quiet splash net=work-wifi initrd /boot/initrd.img-2.6.12-10-386 savedefault boot
title Ubuntu, kernel 2.6.12-10-386 Work Wired root (hd0,4) kernel /boot/vmlinuz-2.6.12-10-386 root=/dev/sda5 ro vga=771 quiet splash net=work-wired initrd /boot/initrd.img-2.6.12-10-386 savedefault boot
Configuration de ''/etc/network/interfaces''
Le fichier /etc/network/interfaces
décrit l'ensemble des opérations à effectuer pour activer les différentes interfaces réseau physiques dont dispose la machine. Sa structure et son mode de fonctionnement pouvant être assez élaborés, je me contenterai ici d'aller à l'essentiel.
En premier lieu, on va demander à ce que toutes nos interfaces physiques subissent les opérations de configuration, quitte à que certaines restent inactives au bout du compte. Ceci s'obtient à l'aide d'un ligne de type :
auto lo eth0 wlan0
(lo
est obligatoire, c'est la «boucle locale» ; eth0
et wlan0
sont les interfaces correspondant respectivement à ma carte Ethernet, et à ma carte WiFi).
Comme il faut obligatoirement initialiser la boucle locale, la ligne suivante s'écrit :
iface lo inet loopback
Ensuite, des directives de «mapping» vont faire correspondre à chaque interface physique le nom du réseau tel qu'il a été spécifié en tant que paramètre au démarrage du noyau.
En l'espèce, pour déterminer quelle configuration adopter pour le réseau sans fil, les lignes suivantes sont nécessaires :
mapping wlan0 script /etc/network/get_net_kernel_param.sh map home-wifi wifihome map work-wifi wifiwork
Cette déclaration signifie que pour configurer wlan0
il faut appeller le script /etc/network/get_net_kernel_param.sh
(auquel nous reviendrons dans la section suivante) qui recevra comme argument le nom de l'adresse physique, ici wlan0
, et en entrée standard les autres lignes du bloc mapping
desquelles sont enlevées les mots-clés map
.
En clair, c'est comme si en ligne de commande, on faisait :
echo -e "home-wifi wifihome\nwork-wifi wifiwork" | /etc/network/get_kernel_param.sh wlan0
Ce script est alors censé afficher sur sa sortie standard un identifiant de configuration figurant dans /etc/network/interfaces
. Dans notre cas, si l'on a choisi au démarrage l'entrée correspondant à Home WiFi (et donc le paramètre net=home-wifi
, le script devra afficher :
wifihome
Si l'on a choisi l'entrée Work WiFi la sortie du script sera :
wifiwork
J'ajoute donc à /etc/network/interfaces
les instructions de configuration effectives pour wifihome
et pour wifiwork
:
iface wifihome inet static pre-up modprobe ndiswrapper address 192.168.0.2 netmask 255.255.255.0 gateway 192.168.0.1 wireless-essid homesweethome wireless-key 1234ABCDEF post-up echo -e "nameserver 213.228.0.168\nameserver 212.27.63.113" > /etc/resolv.conf iface wifiwork inet dhcp pre-up modprobe ndiswrapper wireless-essid workessid wireless-key ABCDEF1234
La configuration de wifihome
est purement statique. Outre sa propre adresse, j'y spécifie le masque de sous-réseau et la passerelle. Et en fin de configuration, à l'aide de la ligne comportant la commande post-up
je crée le fichier /etc/resolv.conf
avec les deux serveurs de nom de mon FAI pour avoir un DNS fonctionnel.
La configuration de wifiwork
est, quant à elle, entièrement automatique (par dhcp
)
Ces deux configurations nécessitent néanmoins que l'on charge préalablement le module ndiswrapper
(bah oui, ma carte n'est pas supportée en natif ), d'o la ligne contenant la commande pre-up
. Dans les deux cas, les identifiants des réseaux sans fil sont également inclus dans la configuration.
Ce qui vaut pour l'interface physique wlan0
est aisément transposable à eth0
dont la configuration se fait donc à l'aide des lignes ci-dessous :
mapping eth0 script /etc/network/get_kernel_param.sh map work-wired wiredwork iface wiredwork inet dhcp
Ouf ! Voilà pour le fichier /etc/network/interfaces
. Ne reste plus que la dernière étape…
En fait, le comportement erratique de ce module lorsque mon portable fonctionne sur batterie a été l'une des motivations pour mettre au point cette méthode de configuration dynamique du réseau.
Installation du script de «mapping»
Voici script de mapping dont le fonctionnement est décrit dans la section précédente :
#!/bin/bash # First argument of script is physical interface. IFACE="$1" # Fetch kernel net= argument given at boot time. BOOTNETNAME=$(sed 's/^.*net=\([a-z_A-Z0-9-]*\).*$/\1/' /proc/cmdline) # Resulting interface to bring up RESULTIFACENAME="" # Read map lines given on stdin. while read NETNAME IFACENAME ; do if [ "$RESULTIFACENAME" ] ; then continue fi if [ "$NETNAME" = "$BOOTNETNAME" ] ; then RESULTIFACENAME=$IFACENAME fi done # Output resulting interface name if [ "$RESULTIFACENAME" ] ; then echo $RESULTIFACENAME exit 0 fi exit1
Même si les commentaires sont en anglais, sont déroulement ne devrait pas poser de problème de compréhension majeur :
- le nom de l'interface passé en premier argument est récupéré dans la variable
IFACE
- le nom de la configuration réseau (paramètre noyau) est récupéré dans
BOOTNETNAME
- le nom de l'interface logique à configurer sera stocké dans
RESULTIFACENAME
- une boucle
while
traite toutes les lignes reçues en entrée et issues des lignesmap
de/etc/network/interfaces
- ces lignes contiennent deux mots : le nom d'une configuration réseau (
NETNAME
) et le nom logique de l'interface correspondante à configurer (IFACENAME
) - s'il y a correspondance entre le nom de la configuration et celle passée au noyau, on affecte l'interface logique à configurer avec la valeur de
IFACENAME
- enfin, un test final vérifie qu'il y a bien une configuration correspondant à celle demandée (
RESULTIFACENAME
n'est pas vide) et l'affiche - dans le cas contraire un code de retour non-nul est retourné signifiant qu'il ne faut pas configurer l'interface physique donnée en argument du script.
Ce scipt se trouve donc dans le fichier /etc/network/get_net_kernel_param.sh
comme indiqué dans /etc/network/interfaces
.
Nous sommes donc arrivés au bout de nos peines, et disposons d'un système dont nous pouvons personnaliser à souhait les différents environnements réseau.
Extensions
Pour ceux qui ne se seraient pas encore endormis, il peut être utile d'ajouter d'autres éléments à la configuration dynamique. Par exemple, ma propre configuration ajoute quelques lignes supplémentaire à chaque interface logique dans /etc/network/interfaces
de façon à configurer correctement le serveur SMTP sortant. L'astuce est de déclarer ce serveur dans /etc/hosts comme mailhost
et de configurer l'ensemble de ses clients de messagerie en indiquant mailhost
comme serveur de messagerie sortant.
Voici un exemple de ce que j'ai ajouté au bloc qui configure wifihome
:
post-up grep -v mailhost /etc/hosts >> /tmp/hosts post-up mv /tmp/hosts/ /etc/hosts post-up echo "212.27.48.4 smtp.free.fr mailhost" >> /etc/hosts
Les deux premières lignes nettoyent /etc/hosts
pour en éliminer un éventuel mailhost
résiduel, et la dernière y a joute l'adresse du serveur SMTP de mon FAI.
Problème ouvert : Proxy ?
Que faire pour basculer entre :
- une connexion maison par wifi
- une connexion travail derrière un PROXY ?
Contributeurs : verrader