5.7. Routage

Le routage est un vaste sujet. On peut écrire de grandes quantités de textes sur ce sujet. La plupart d'entre vous ont besoin d'un simple routage, et certains même de rien du tout. Je ne parlerai que des principes du routage. Si vous voulez plus d'informations je vous suggère de vous reporter aux références fournies en début du document.

Commençons par une définition. Qu'est-ce que le routage IP ? Voici celle que j'utilise :

"Le routage IP est le processus par lequel un hôte, ayant des connexions réseau multiples, décide du chemin par lequel délivrer les datagrammes IP qu'il a reçus."

Il peut être utile d'illustrer cela par un exemple. Imaginez un routeur dans un bureau : il peut avoir un lien PPP sur l'Internet, un certain nombre de segments Ethernet alimentant les stations de travail et un second lien PPP vers un autre bureau. Lorsque le routeur reçoit un datagramme de l'une de ses connexions, le routage est le mécanisme utilisé pour déterminer vers quelle interface il doit renvoyer ce datagramme. De simples hôtes ont besoin aussi de routage, tous les hôtes Internet ayant deux périphériques réseau, l'un étant l'interface loopback décrite auparavant et l'autre est celui qui est utilisé pour parler avec le reste du monde, soit un lien Ethernet, soit une interface série PPP ou SLIP.

Ok, alors comment fonctionne le routage ? Chaque hôte possède une liste spéciale de règles de routage, appelée une table de routage. Cette table contient des colonnes qui contiennent au moins trois champs, le premier étant une adresse de destination, le deuxième étant le nom de l'interface vers lequel le datagramme doit être routé et le troisième, qui est optionnel, l'adresse IP d'une autre machine qui transportera le datagramme vers sa prochaine destination sur le réseau passerelle. Sur Linux vous pouvez voir cette table en utilisant la commande suivante :

user% cat /proc/net/route

ou bien en utilisant l'une des commandes suivantes :

user% /sbin/route -n
user% /sbin/netstat -r

Le processus de routage est plutôt simple : un datagramme entrant est reçu, l'adresse de destination est examinée et comparée avec chaque entrée de la table. L'entrée qui correspond le mieux à cette adresse est choisie, et le datagramme est renvoyé vers l'interface spécifiée. Si le champ passerelle est rempli, alors le datagramme est renvoyé vers cet hôte via l'interface spécifiée, sinon l'adresse de destination est supposée comme étant sur le réseau supporté par l'interface.

Pour manipuler ce tableau, une commande spéciale est utilisée. Cette commande prend des arguments et les convertit en appels système pour demander au noyau d'ajouter, supprimer ou modifier des entrées dans la table de routage. Cette commande s'appelle `route'.

Un exemple simple. Imaginez que vous ayez un réseau Ethernet. On vous a dit que c'est un réseau classe C avec une adresse de 192.168.1.0. On vous fournit une adresse IP 192.168.1.10 pour votre usage et on vous a dit que 192.168.1.1 est un routeur connecté à l'Internet.

La première étape est de configurer l'interface comme indiqué plus haut. Vous utiliserez la commande :

root# ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up

Maintenant vous avez besoin d'ajouter une entrée dans la table de routage pour indiquer au noyau que les datagrammes destinés aux hôtes dont les adresses correspondent à 192.168.1.* doivent être dirigés vers le périphérique Ethernet. Vous utiliserez une commande comme ceci :

root# route add -net 192.168.1.0 netmask 255.255.255.0 eth0

Notez l'utilisation de l'argument `-net' pour indiquer au programme route que cette entrée est une route réseau. Un autre choix peut être `-host' qui est une route spécifique d'une adresse IP.

Cette route vous permettra d'établir des connexions IP avec tous les hôtes sur votre segment Ethernet. Mais qu'en est-il des hôtes IP qui n'y sont pas ?

Il serait compliqué d'ajouter des routes pour chaque réseau destinataire, aussi il y a une astuce utilisée pour simplifier la tâche. L'astuce est appelée route par `defaut'. La route par defaut s'adapte à toutes les destinations possibles, mais pas très bien, de telle sorte que si il y a une entrée qui correspond à l'adresse requise elle sera utilisée à la place de la route par defaut. L'idée de la route par defaut est simplement de pouvoir dire `et tout le reste va ici'. Dans l'exemple que j'ai inventé, on utilisera une entrée telle que :

root# route add default gw 192.168.1.1 eth0

L'argument `gw' indique à la commande route que le prochain argument est l'adresse IP, ou le nom, d'une passerelle (gateway) ou d'une machine routeur vers qui tous les datagrammes correspondant à cette entrée seront dirigés pour routage ultérieur.

Ainsi votre configuration complète sera :

root# ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up
root# route add -net 192.168.1.0 netmask 255.255.255.0 eth0
root# route add default gw 192.168.1.1 eth0

Si vous regardez bien vos fichiers `rc' qui concernent le réseau vous en trouverez au moins un très semblable à celui-ci. C'est une configuration courante.

Examinons maintenant une configuration un peu plus compliquée. Imaginons que nous configurions le routeur examiné auparavant, celui qui avait un lien PPP vers l'Internet et des segments LAN alimentant des stations de travail dans le bureau. Supposons que ce routeur ait 3 segments Ethernet et un lien PPP. Notre configuration de routage ressemblerait à ceci :

root# route add -net 192.168.1.0 netmask 255.255.255.0 eth0
root# route add -net 192.168.2.0 netmask 255.255.255.0 eth1
root# route add -net 192.168.3.0 netmask 255.255.255.0 eth2
root# route add default ppp0

Chacune des stations de travail utilisera le format plus simple décrit ci-dessus, seul le routeur aura besoin d'indiquer les routes réseau séparément car pour les stations de travail le mécanisme de routage par defaut les capturera toutes, laissant au routeur le soin de les séparer de manière appropriée. Vous pouvez vous demander pourquoi la route par défaut n'utilise pas `gw'. La raison en est très simple : les protocoles de lien série comme PPP et SLIP ont seulement deux hôtes sur leur réseau, un à chaque bout. Spécifier à l'hôte que l'autre bout de la liaison est une passerelle est sans objet et redondant, car il n'a pas d'autre choix, aussi vous n'avez pas à indiquer de passerelle pour ce type de connexions réseau. Les autres types comme Ethernet, arcnet ou token ring ont besoin que l'on indique une passerelle car ces réseaux supportent un grand nombre d'hôtes.

5.7.1. Alors, que fait le programme routed ?

La configuration de routage décrite ci-dessus est bien adaptée aux réseaux simples où il n'y a que des chemins uniques entre les destinations. Lorsque vous avez un réseau plus complexe les choses deviennent plus compliquées. Heureusement pour la plupart d'entre vous, ce ne sera pas le cas.

Le gros problème est qu'avec le `routage manuel' ou `routage statique' comme décrit ci-dessus, si une machine ou un lien tombe en panne dans le réseau, alors la seule façon de diriger vos datagrammes vers un autre chemin, s'il existe, est d'intervenir manuellement et d'exécuter les commandes adéquates. Naturellement c'est lourd, lent, peu pratique et source de risques. Des techniques variées ont été développées pour régler automatiquement les tables de routage dans le cas d'incidents sur un réseau où il y a plusieurs routes possibles, toutes ces techniques étant regroupées sous le nom de `protocoles de routage dynamique'.

Vous avez peut-être entendu parler des plus courants. Ce sont RIP (Routing Information Protocol) et OSPF (Open Shortest Path First Protocol). RIP est très souvent utilisé sur les petits ou moyens réseaux d'entreprise. L'OPSF est plus moderne et plus apte à gérer de grands réseaux et mieux adapté dans le cas où il y a un grand nombre de chemins possibles à travers le réseau. Les implémentations usuelles de ces protocoles sont : `routed' - RIP, et `gated' - RIP, OSPF et autres. Le programme `routed' est normalement fourni avec votre distribution Linux ou est inclus dans la paquetage `NetKit' décrit auparavant.

Un exemple pour vous montrer comment et où vous pouvez utiliser un protocole de routage dynamique ressemblerait à ceci :


 192.168.1.0 /                         192.168.2.0 /
 255.255.255.0                         255.255.255.0
 -                                     -
 |                                     |
 |   /- - -\                 /- - -\   |
 |   |     |ppp0   //    ppp0|     |   |
eth0 |- -|  A  |- - - //- - - - -|  B  |- -| eth0
 |   |     |     //          |     |   |
 |   \- - -/                 \- - -/   |
 |      \ ppp1             ppp1 /      |
 -       \                     /       -
 \                   /
 \                 /
 \               /
 \             /
 \           /
 \         /
 \       /
 \     /
 ppp0\   /ppp1
 /- - -\
 |     |
 |  C  |
 |     |
 \- - -/
 |eth0
 |
 |- - - - -|
 192.168.3.0 /
 255.255.255.0

Nous avons trois routeurs A, B et C. Chacun supporte un segment Ethernet avec un réseau IP de classe C (masque de réseau 255.255.255.0). Chaque routeur a également une liaison PPP vers chacun des autres routeurs. Ce réseau forme un triangle.

Il est évident que la table de routage sur le routeur A ressemble à ceci :

root# route add -net 192.168.1.0 netmask 255.255.255.0 eth0
root# route add -net 192.168.2.0 netmask 255.255.255.0 ppp0
root# route add -net 192.168.3.0 netmask 255.255.255.0 ppp1

Cela fonctionnera bien jusqu'à ce que le lien entre A et B tombe en panne. Les hôtes sur le segment A (voir le diagramme ci-dessus) ne peuvent pas atteindre les hôtes sur le segment B : leurs datagrammes seront dirigés sur le lien ppp0 du routeur A qui est rompu. Ils pourront encore continuer à parler aux hôtes du segment C, et les hôtes du segment C pourront toujours parler à ceux du segment B car la liaison reste intacte.

Si A peut parler à C et si C peut toujours parler à B, pourquoi A ne routerait-il pas ses datagrammes pour B via C, et laisser ensuite C les envoyer à B ? C'est exactement le type de problèmes que les protocoles de routage dynamique comme RIP sont en mesure de résoudre. Si chacun des routeurs A, B et C utilisent un démon de routage (NdT: démon est une francisation familière du vocable informatique anglais daemon, qui signifie Disk And Extension MONitor, c'est à dire qui n'est pas invoqué manuellement mais attend en tâche de fond que quelque chose se passe, que quelque condition se produise. Ce terme fut introduit au départ sous CTSS (Compatible Time Sharing System), un ancêtre du système MULTICS, lui-même parent d'UNIX (voir la traduction de René Cougnenc de `Le système Linux' de M. Welsh et L. Kaufman chez O'Reilly International Thomson), alors leurs tables de routage seront automatiquement réglées pour refléter le nouvel état du réseau même si l'une des liaisons est défectueuse. Configurer un tel réseau est simple, sur chaque routeur vous devez seulement faire deux choses. Dans ce cas, pour le routeur A :

root# route add -net 192.168.1.0 netmask 255.255.255.0 eth0
root# /usr/sbin/routed

Le démon de routage `routed' trouve automatiquement tous les ports actifs vers le réseau quand il démarre et écoute tous les messages sur chacun des périphériques réseau ce qui lui permet de déterminer et de mettre à jour sa table de routage.

C'était une très brève explication du routage dynamique et de son utilisation. Si vous voulez d'avantage d'explications reportez-vous aux références listées en début de document.

Les points importants relatifs au routage dynamique sont :

  1. Vous n'avez besoin d'utiliser un démon de routage dynamique que quand votre machine Linux peut choisir entre plusieurs routes pour une destination donnée. C'est la cas par exemple lorsque vous envisagez d'utiliser IP masquerade.

  2. Le démon de routage dynamique modifiera automatiquement votre table de routage pour tenir compte des changements survenus dans votre réseau.

  3. RIP est adapté aux réseaux de petite et moyenne taille.