Linux 2.4 Advanced Routing HOWTO <author>Netherlabs BV (bert hubert <bert.hubert@netherlabs.nl>)&nl; Gregory Maxwell <greg@linuxpower.cx> &nl; Remco van Mook <remco@virtu.nl> &nl; Martijn van Oosterhout <kleptog@cupid.suninternet.com> &nl; Paul B Schroeder <paulsch@us.ibm.com> &nl; Jasper Spaans <jasper@spaans.ds9a.nl> &nl; howto@ds9a.nl<newline> Traduction de Laurent Foucher <foucher@gch.iut-tlse3.fr>, Philippe Latu <philippe.latu@linux-france.org> et Guillaume Allègre <Guillaume.Allegre@imag.fr><newline> <date>v0.3.0 $Date: 2001/07/24 09:11:18 $ <abstract> Une approche pratique d'iproute2, de la mise en forme du trafic et un peu de netfilter. </abstract> <!-- Table des matières --> <toc> <!-- Début du document --> <sect>Dédicace <p> Ce document est dédié à beaucoup de gens ; dans ma tentative de tous me les rappeler, je peux en citer quelques-uns : <p> <itemize> <item>Rusty Russell <item>Alexey N. Kuznetsov <item>La fine équipe de Google <item>L'équipe de Casema Internet </itemize> <sect>Introduction <p> Bienvenue, cher lecteur. <p> Ce document a pour but de vous éclairer sur la manière de faire du routage avancé avec Linux 2.2/2.4. Méconnus par les utilisateurs, les outils standard de ces noyaux permettent de faire des choses spectaculaires. Les commandes comme "route" et "ifconfig" sont des interfaces vraiment pauvres par rapport à la grande puissance potentielle d'iproute2. <p> J'espère que cet HOWTO deviendra aussi lisible que le très réputé Netfilter, de Rusty Russell. Vous pouvez nous contacter en nous écrivant à <url name="équipe HOWTO" url="mailto:HOWTO@ds9a.nl">. Cependant, postez, s'il vous plait, vos questions sur la liste de diffusion (voir la section correspondante) pour celles qui ne sont pas directement liées à cet HOWTO. Avant de vous perdre dans cet HOWTO, si la seule chose que vous souhaitez faire est de la mise en forme de trafic simple, allez directement au chapitre 'Autres possibilités', et lisez ce qui concerne CBQ.init. <sect1>Conditions de distribution et Mise en garde <p> Ce document est distribué avec l'espoir qu'il sera utile et utilisé. Sauf mention contraire, les documents Linux HOWTO sont la propriété de leurs auteurs respectifs. Les documents Linux HOWTO peuvent être reproduits et distribués en totalité ou en partie, sur tout support physique ou électronique, tant que cette notice de droit d'auteur est présente sur chaque copie. La redistribution commerciale est autorisée et encouragée ; néammoins, l'auteur souhaite être informé de toute distribution de ce genre. Toute traduction, travail dérivé, ou agrégat incorporant tout ou partie d'un ou plusieurs documents Linux HOWTO doit être couvert par ce même droit d'auteur. Ce qui veut dire que vous ne pouvez produire un travail dérivé d'un HOWTO et imposer des restrictions supplémentaires concernant sa distribution. En un mot, si votre dorsale STM-64 est tombée ou distribue de la pornographie à vos estimés clients, cela n'est pas de notre faute. Désolé. Copyright (c) 2001 par Bert Hubert, Gregory Maxwell et Martijn van Oosterhout, Remco van Mook, Paul B. Schroeder et autres. Copiez et distribuez (vendez ou donnez) librement ce document, dans n'importe quel format. Les demandes de corrections et/ou de commentaires sont à adresser à la personne qui maintient ce document. Vous pouvez créer un travail dérivé et le distribuer à condition : <enum> <item>d'envoyer votre travail dérivé (dans le format le plus approprié, tel que sgml) au LDP (Linux Documentation Project), ou autre, pour une diffusion sur Internet. Si ce n'est pas au LDP, faites savoir au LDP où il est disponible ; <item>que la licence de votre travail dérivé soit la même, ou utilisez la GPL. Incluez une notification du copyright et, au moins, un pointeur vers la licence utilisée ; <item>de créditer pour leur travail les auteurs précédents et les principaux contributeurs. </enum> Si vous envisagez un travail dérivé autre qu'une traduction, vous êtes invité à discuter de vos projets avec le mainteneur actuel. Il est aussi demandé que, si vous publiez cet HOWTO sur un support papier, vous en envoyiez des exemplaires aux auteurs pour une "relecture critique" :-) <sect1>Connaissances préalables <p> Comme le titre l'implique, ceci est un HOWTO "avancé". Bien qu'il ne soit pas besoin d'être un expert réseau, certains prérequis sont nécessaires. Voici d'autres références qui pourront vous aider à en apprendre plus : <descrip> <tag><url url="http://netfilter.samba.org/unreliable-guides/networking-concepts-HOWTO/index.html" name="Rusty Russell's networking-concepts-HOWTO"></tag> Très bonne introduction, expliquant ce qu'est un réseau, et comment on le connecte à d'autres réseaux. <tag>Linux Networking-HOWTO (ex Net-3 HOWTO)</tag> Excellent document, bien que très bavard. Il vous apprendra beaucoup de choses qui sont déjà configurées si vous êtes capable de vous connecter à Internet. Probablement à <file>/usr/doc/HOWTO/NET-HOWTO.txt</file> mais peut aussi être trouvé <url url="http://www.linuxports.com/howto/networking" name="en ligne"> </descrip> <sect1>Ce que Linux peut faire pour vous <p> Une petite liste des choses qui sont possibles : <p> <itemize> <item>Maîtriser la bande passante pour certains ordinateurs <item>Maîtriser la bande passante VERS certains ordinateurs <item>Vous aider à partager équitablement votre bande passante <item>Protéger votre réseau des attaques de type Déni de Service <item>Protéger le réseau local des accès de vos clients <item>Multiplexer plusieurs serveurs en un seul, pour l'équilibrage de charge, ou une disponibilité améliorée <item>Restreindre l'accès à vos ordinateurs <item>Limiter l'accès de vos utilisateurs vers d'autres hôtes <item>Faire du routage basé sur l'ID utilisateur (eh oui !), l'adresse MAC, l'adresse IP source, le port, le type de service, l'heure, ou le contenu. </itemize> <p> Peu de personnes utilisent couramment ces fonctionnalités avancées. Il y a plusieurs raisons à cela. Bien que la documentation soit fournie, la prise en main est difficile. Les commandes de contrôle du trafic ne sont pratiquement pas documentées. <sect1>Notes diverses <p> Il y a plusieurs choses qui doivent être notées au sujet de ce document. Bien que j'en aie écrit la majeure partie, je ne veux vraiment pas qu'il reste tel quel. Je crois beaucoup à l'Open Source, je vous encourage donc à envoyer des remarques, des mises à jour, des corrections, etc. N'hésitez pas à m'avertir des coquilles ou d'erreurs pures et simples. Si mon anglais vous paraît parfois peu naturel, ayez en tête, s'il vous plaît, que l'anglais n'est pas ma langue natale. N'hésitez pas à m'envoyer vos suggestions [NdT : en anglais !] Si vous pensez que vous êtes plus qualifié que moi pour maintenir une section, ou si vous pensez que vous pouvez écrire et maintenir de nouvelles sections, vous êtes le bienvenu. Pour vous aider, vous trouverez beaucoup de mentions FIXME (NdT : "à corriger"). Les corrections sont toujours les bienvenues. Si vous trouvez une mention FIXME, vous saurez que vous êtes en territoire inconnu. Cela ne veut pas dire qu'il n'y a pas d'erreurs ailleurs, faites donc très attention. Si vous avez validé quelque chose, faites-le nous savoir, ce qui nous permettra de retirer la mention FIXME. Je prendrai quelques libertés tout au long de cet HOWTO. Par exemple, je pars de l'hypothèse d'une connexion Internet à 10 Mbits, bien que je sache très bien que cela n'est pas vraiment courant. <sect1>Accès, CVS et propositions de mises à jour <p> L'adresse canonique de cet HOWTO est <url url="http://www.ds9a.nl/2.4Routing" name="Ici">. Nous avons maintenant un CVS en accès anonyme disponible depuis le monde entier. Cela est intéressant pour plusieurs raisons. Vous pouvez facilement télécharger les nouvelles versions de ce HOWTO et soumettre des patches. En outre, cela permet aux auteurs de travailler sur le source de facon indépendante, ce qui est une bonne chose aussi. <tscreen><verb> $ export CVSROOT=:pserver:anon@outpost.ds9a.nl:/var/cvsroot $ cvs login CVS password: [enter 'cvs' (without 's)] $ cvs co 2.4routing cvs server: Updating 2.4routing U 2.4routing/2.4routing.sgml </verb></tscreen> Si vous repérez une erreur, ou voulez ajouter quelque chose, faites le en local, exécutez <tt>cvs diff -u</tt>, et envoyez-nous le résultat. Un fichier Makefile est fourni pour vous aider à créer des fichiers PostScript, dvi, pdf, html et texte. Vous pouvez avoir à installer les sgml-tools, ghostscript et tetex pour obtenir tous les formats de sortie. <sect1>Liste de diffusion <p> <label id="MLIST"> Les auteurs reçoivent de plus en plus de courriers électroniques à propos de cet HOWTO. Vu l'intérêt de la communité, il a été décidé la mise en place d'une liste de diffusion où les personnes pourront discuter du routage avancé et du contrôle de trafic. Vous pouvez vous abonner à la liste <url url="http://mailman.ds9a.nl/mailman/listinfo/lartc" name="ici">. <p> Il devra être noté que les auteurs sont très hésitant à répondre à des questions qui n'ont pas été posées sur la liste. Nous aimerions que la liste devienne une sorte de base de connaissance. Si vous avez une question, recherchez, s'il vous plait, d'abord dans l'archive, et ensuite postez là dans la liste de diffusion. <sect1>Plan du document <p> Nous allons essayer de faire des manipulations intéressantes dès le début, ce qui veut dire que tout ne sera pas expliqué en détail tout de suite. Veuillez passer sur ces détails, et accepter de considérer qu'ils deviendront clairs par la suite. Le routage et le filtrage sont deux choses distinctes. Le filtrage est très bien documenté dans le HOWTO de Rusty, disponible ici : <itemize> <item><url url="http://netfilter.samba.org/unreliable-guides/" name="Rusty's Remarkably Unreliable Guides"> </itemize> Nous nous focaliserons principalement sur ce qu'il est possible de faire en combinant netfilter et iproute2. <sect>Introduction à iproute2 <sect1>Pourquoi iproute2 ? <p> La plupart des distributions Linux et des UNIX utilisent couramment les vénérables commandes "arp", "ifconfig" et "route". Bien que ces outils fonctionnent, ils montrent quelques comportements inattendus avec les noyaux Linux des séries 2.2 et plus. Par exemple, les tunnels GRE font partie intégrante du routage de nos jours, mais ils nécessitent des outils complètement différents. Avec iproute2, les tunnels font partie intégrante des outils. Les noyaux Linux des séries 2.2 et plus ont un sous-système réseau complètement réécrit. Ce nouveau codage de la partie réseau apporte à Linux des performances et des fonctionnalités qui n'ont pratiquement pas d'équivalent dans les autres systèmes d'exploitation. En fait, le nouveau logiciel de filtrage, routage et de classification possède plus de fonctionnalités que les logiciels fournis sur beaucoup de routeurs dédiés, de pare-feux et de produits de mise en forme (shaping) du trafic. Dans les systèmes d'exploitation existants, au fur et à mesure que de nouveaux concepts réseau apparaissaient, les développeurs sont parvenus à les greffer sur les structures existantes. Ce travail constant d'empilage de couches a conduit à des codes réseau aux comportements étranges, un peu comme les langues humaines. Dans le passé, Linux émulait le mode de fonctionnement de SunOS, ce qui n'était pas l'idéal. La nouvelle structure d'iproute2 a permis de formuler clairement des fonctionnalités impossibles à implanter dans le sous-système réseau précédent. <sect1>Un tour d'horizon d'iproute2 <p> Linux possède un système sophistiqué d'allocation de bande passante appelé Contrôle de trafic (Traffic Control). Ce système supporte différentes méthodes pour classer, ranger par ordre de priorité, partager et limiter le trafic entrant et sortant. Nous commencerons par un petit tour d'horizon des possibilités d'iproute2. <sect1>Prérequis <p> Vous devez être sûr que vous avez installé les outils utilisateur (NdT : userland tools, par opposition à la partie "noyau" d'iproute2). Le paquet concerné s'appelle "iproute" sur RedHat et Debian. Autrement, il peut être trouvé à <tt>ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss??????.tar.gz</tt>. Vous pouvez aussi essayer <url url="ftp://ftp.inr.ac.ru/ip-routing/iproute2-current.tar.gz" name="iproute2-current.tar.gz"> pour la dernière version. Certains éléments d'iproute vous imposent l'activation de certaines options du noyau. Il devra également être noté que toutes les versions de RedHat jusqu'à la version 6.2 incluse n'ont pas les fonctionnalités du contrôle de trafic dans le noyau par défaut. FIXME: Est-ce que quelqu'un peut confirmer que la 7.0 a les éléments nécessaires déjà compilés ? Soyez également sûr que vous avez le support netlink, en utilisant son propre noyau (NdT : compilé par vous). Iproute2 en a besoin. <sect1>Explorer votre configuration courante <p> Cela peut vous paraître surprenant, mais iproute2 est déjà configuré ! Les commandes courantes <tt>ifconfig</tt> et <tt>route</tt> utilisent déjà les appels système avancés d'iproute2, mais essentiellement avec les options par défaut (c'est-à-dire ennuyeuses). L'outil <tt>ip</tt> est central, et nous allons lui demander de nous montrer les interfaces. <sect2><tt>ip</tt> nous montre nos liens <p> <tscreen><verb> [ahu@home ahu]$ ip link list 1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: dummy: <BROADCAST,NOARP> mtu 1500 qdisc noop link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1400 qdisc pfifo_fast qlen 100 link/ether 48:54:e8:2a:47:16 brd ff:ff:ff:ff:ff:ff 4: eth1: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100 link/ether 00:e0:4c:39:24:78 brd ff:ff:ff:ff:ff:ff 3764: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 10 link/ppp </verb></tscreen> <p>La sortie peut varier, mais voici ce qui est affiché pour mon routeur NAT (NdT : translation d'adresse) chez moi. J'expliquerai seulement une partie de la sortie, dans la mesure où tout n'est pas directement pertinent. La première interface que nous voyons est l'interface loopback. Bien que votre ordinateur puisse fonctionner sans, je vous le déconseille. La taille de MTU (unité maximum de transmission) est de 3924 octets, et loopback n'est pas supposé être mis en file d'attente, ce qui prend tout son sens dans la mesure où cette interface est le fruit de l'imagination de votre noyau. Je vais passer sur l'interface dummy pour l'instant, et il se peut qu'elle ne soit pas présente sur votre ordinateur. Il y a ensuite mes deux interfaces physiques, l'une du côté de mon modem câble, l'autre servant mon segment ethernet à la maison. De plus, nous voyons une interface ppp0. Notons l'absence d'adresses IP. Iproute déconnecte les concepts de "liens" et "d'adresses IP". Avec l'IP aliasing, le concept de l'adresse IP canonique est devenu, de toute façon, sans signification. <tt>ip</tt> nous montre bien, cependant, l'adresse MAC, l'identifiant matériel de nos interfaces ethernet. <sect2><tt>ip</tt> nous montre nos adresses IP <p> <tscreen><verb> [ahu@home ahu]$ ip address show 1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 brd 127.255.255.255 scope host lo 2: dummy: <BROADCAST,NOARP> mtu 1500 qdisc noop link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1400 qdisc pfifo_fast qlen 100 link/ether 48:54:e8:2a:47:16 brd ff:ff:ff:ff:ff:ff inet 10.0.0.1/8 brd 10.255.255.255 scope global eth0 4: eth1: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100 link/ether 00:e0:4c:39:24:78 brd ff:ff:ff:ff:ff:ff 3764: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 10 link/ppp inet 212.64.94.251 peer 212.64.94.1/32 scope global ppp0 </verb></tscreen> <p> Cela contient plus d'informations : ip montre toutes nos adresses, et à quelles cartes elles appartiennent. "inet" signifie Internet (IPv4). Il y a beaucoup d'autres familles d'adresses, mais elles ne nous concernent pas pour le moment. Examinons eth0 de plus près. Il est dit qu'il est relié à l'adresse internet "10.0.0.1/8". Qu'est-ce que cela signifie ? Le /8 désigne le nombre de bits réservés à l'adresse réseau. Il y a 32 bits, donc il reste 24 bits pour désigner une partie de notre réseau. Les 8 premiers bits de 10.0.0.1 correspondent à 10.0.0.0, notre adresse réseau, et notre masque de sous-réseau est 255.0.0.0. Les autres bits repèrent des machines directement connectées à cette interface, donc 10.250.3.13 est directement disponible sur eth0, comme l'est 10.0.0.1 dans notre exemple. Avec ppp0, le même concept existe, bien que les nombres soient différents. Son adresse est 212.64.94.251, sans masque de sous-réseau. Cela signifie que vous avez une liaison point à point et que toutes les adresses, à l'exception de 212.64.94.251, sont distantes. Il y a cependant plus d'informations. En effet, on nous dit que de l'autre côté du lien, il n'y a encore qu'une seule adresse, 212.64.94.1. Le /32 nous précise qu'il n'y a pas de "bits réseau". Il est absolument vital que vous compreniez ces concepts. Référez-vous à la documentation mentionnée au début de cet HOWTO si vous avez des doutes. Vous pouvez aussi noter "qdisc", qui désigne la "Queueing Discipline" (gestion de la mise en file d'attente). Cela deviendra vital plus tard. <sect2><tt>ip</tt> nous montre nos routes <p> Nous savons maintenant comment trouver les adresses 10.x.y.z, et nous sommes capables d'atteindre 212.64.94.1. Cela n'est cependant pas suffisant, et nous avons besoin d'instructions pour atteindre le monde. L'Internet est disponible via notre connexion ppp, et il se trouve que 212.64.94.1 est prêt à propager nos paquets à travers le monde, et à nous renvoyer le résultat. <tscreen><verb> [ahu@home ahu]$ ip route show 212.64.94.1 dev ppp0 proto kernel scope link src 212.64.94.251 10.0.0.0/8 dev eth0 proto kernel scope link src 10.0.0.1 127.0.0.0/8 dev lo scope link default via 212.64.94.1 dev ppp0 </verb></tscreen> Cela se comprend de soi-même. Les 4 premières lignes donnent explicitement ce qui était sous-entendu par <tt>ip address show </tt>, la dernière ligne nous indiquant que le reste du monde peut être trouvé via 212.64.94.1, notre passerelle par défaut. Nous pouvous voir que c'est une passerelle à cause du mot "via", qui nous indique que nous avons besoin d'envoyer les paquets vers 212.64.94.1, et que c'est elle qui se chargera de tout. En référence, voici ce que l'ancien utilitaire "route" nous propose : <tscreen><verb> [ahu@home ahu]$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 212.64.94.1 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0 10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo 0.0.0.0 212.64.94.1 0.0.0.0 UG 0 0 0 ppp0 </verb></tscreen> <sect1>ARP <p> ARP est le Protocole de Résolution d'Adresse (Address Resolution Protocol). Il est décrit dans le <url url="http://www.faqs.org/rfcs/rfc826.html" name="RFC 826">. ARP est utilisé par une machine d'un réseau local pour retrouver l'adresse matérielle (la localisation) d'une autre machine sur le même réseau. Les machines sur Internet sont généralement connues par leur nom auquel correspond une adresse IP. C'est ainsi qu'une machine sur le réseau foo.com est capable de communiquer avec une autre machine qui est sur le réseau bar.net. <!-- Rel (GA) : je trouve ces explications très confuses pour --> <!-- un novice et inutiles pour un type expérimenté en réseau :-( --> Une adresse IP, cependant, ne peut pas vous indiquer la localisation physique de la machine. C'est ici que le protocole ARP entre en jeu. Prenons un exemple très simple. Supposons que j'aie un réseau composé de plusieurs machines, dont la machine "foo" d'adresse IP 10.0.0.1 et la machine "bar" qui a l'adresse IP 10.0.0.2. Maintenant, foo veut envoyer un "ping" vers bar pour voir s'il est actif, mais foo n'a aucune indication sur la localisation de bar. Donc, si foo décide d'envoyer un "ping" vers bar, il a besoin d'envoyer une requête ARP. Cette requête ARP est une façon pour foo de crier sur le réseau "Bar (10.0.0.2) ! Où es-tu ?". Par conséquent, toutes les machines sur le réseau entendront foo crier, mais seul bar (10.0.0.2) répondra. Bar enverra une réponse ARP directement à foo ; ce qui revient à dire : "Foo (10.0.0.1) ! je suis ici, à l'adresse 00:60:94:E:08:12". Après cette simple transaction utilisée pour localiser son ami sur le réseau, foo est capable de communiquer avec bar jusqu'à ce qu'il (le cache ARP de foo) oublie où bar est situé. Maintenant, voyons comment cela fonctionne. Vous pouvez consulter votre cache (table) arp (neighbor) comme ceci : <tscreen><verb> [root@espa041 /home/src/iputils]# ip neigh show 9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable 9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud reachable </verb></tscreen> Comme vous pouvez le voir, ma machine espa041 (9.3.76.41) sait où trouver espa042 (9.3.76.42) et espagate (9.3.76.1). Maintenant, ajoutons une autre machine dans le cache arp. <tscreen><verb> [root@espa041 /home/paulsch/.gnome-desktop]# ping -c 1 espa043 PING espa043.austin.ibm.com (9.3.76.43) from 9.3.76.41 : 56(84) bytes of data. 64 bytes from 9.3.76.43: icmp_seq=0 ttl=255 time=0.9 ms --- espa043.austin.ibm.com ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.9/0.9/0.9 ms [root@espa041 /home/src/iputils]# ip neigh show 9.3.76.43 dev eth0 lladdr 00:06:29:21:80:20 nud reachable 9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable 9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud reachable </verb></tscreen> Par conséquent, lorsque espa041 a essayé de contacter espa043, l'adresse matérielle de espa043 (sa localisation) a alors été ajoutée dans le cache ARP. Donc, tant que la durée de vie de l'entrée correspondant à espa043 dans le cache ARP n'est pas dépassée, espa041 sait localiser espa043 et n'a plus besoin d'envoyer de requête ARP. Maintenant, effaçons espa043 de notre cache ARP. <tscreen><verb> [root@espa041 /home/src/iputils]# ip neigh delete 9.3.76.43 dev eth0 [root@espa041 /home/src/iputils]# ip neigh show 9.3.76.43 dev eth0 nud failed 9.3.76.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable 9.3.76.1 dev eth0 lladdr 00:06:29:21:73:c8 nud stale </verb></tscreen> Maintenant, espa041 a à nouveau oublié la localisation d'espa043 et aura besoin d'envoyer une autre requête ARP la prochaine fois qu'il voudra communiquer avec lui. Vous pouvez aussi voir ci-dessus que l'état d'espagate (9.3.76.1) est passé en "stale". Cela signifie que la localisation connue est encore valide, mais qu'elle devra être confirmée à la première transaction avec cette machine. <sect>Règles - bases de données des politiques de routage <p> Si vous avez un routeur important, il se peut que vous vouliez satisfaire les besoins de différentes personnes, qui peuvent être traitées différemment. Les bases de données des politiques de routage vous aident à faire cela, en gérant plusieurs ensembles de tables de routage. Si vous voulez utiliser cette fonctionnalité, assurez vous que le noyau est compilé avec les options "IP : Advanced router" et "IP: policy routing". Quand le noyau doit prendre une décision de routage, il recherche quelle table consulter. Par défaut, il y a trois tables. L'ancien outil <tt>route</tt> modifie les tables "main" (principale) et "local" (locale), comme le fait l'outil <tt>ip</tt> (par défaut). Les règles par défaut : <tscreen><verb> [ahu@home ahu]$ ip rule list 0: from all lookup local 32766: from all lookup main 32767: from all lookup default </verb></tscreen> Nous voyons que toutes les règles sont appliquées à tous les paquets ("from all"). Nous avons vu la table "main" précédemment, sa sortie s'effectuant avec <tt>ip route ls</tt>, mais les tables "local" et "default" sont nouvelles. Si nous voulons faire des choses fantaisistes, nous pouvons créer des règles qui pointent vers des tables différentes et qui nous permettent de redéfinir les règles de routage du système. Pour savoir exactement ce que fait le noyau en présence d'un assortiment de règles plus complet, référez-vous à la documentation ip-cref d'Alexey [NdT : dans le paquet iproute(2) de votre distribution]. <sect1>Routage simple par l'adresse source <p> Prenons encore une fois un exemple réel. J'ai 2 modems câble, connectés à un routeur Linux NAT ("masquerading"). Les personnes habitant avec moi me paient pour avoir accès à Internet. Supposons qu'un de mes co-locataires visite seulement hotmail et veuille payer moins. C'est d'accord pour moi, mais il utilisera le modem le plus lent. Le modem câble "rapide" est connu sous 212.64.94.251 et est en liaison PPP avec 212.64.94.1. Le modem câble "lent" est connu sous diverses adresses ip, 212.64.78.148 dans notre exemple avec un lien vers 195.96.98.253. La table locale : <tscreen><verb> [ahu@home ahu]$ ip route list table local broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1 local 10.0.0.1 dev eth0 proto kernel scope host src 10.0.0.1 broadcast 10.0.0.0 dev eth0 proto kernel scope link src 10.0.0.1 local 212.64.94.251 dev ppp0 proto kernel scope host src 212.64.94.251 broadcast 10.255.255.255 dev eth0 proto kernel scope link src 10.0.0.1 broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1 local 212.64.78.148 dev ppp2 proto kernel scope host src 212.64.78.148 local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 </verb></tscreen> Il y a beaucoup de choses évidentes, mais aussi des choses qui ont besoin d'être précisées quelque peu, ce que nous allons faire. La table de routage par défaut est vide. Regardons la table principale ("main") : <tscreen><verb> [ahu@home ahu]$ ip route list table main 195.96.98.253 dev ppp2 proto kernel scope link src 212.64.78.148 212.64.94.1 dev ppp0 proto kernel scope link src 212.64.94.251 10.0.0.0/8 dev eth0 proto kernel scope link src 10.0.0.1 127.0.0.0/8 dev lo scope link default via 212.64.94.1 dev ppp0 </verb></tscreen> Maintenant, nous générons une nouvelle règle que nous appellerons "John", pour notre hypothétique co-locataire. Bien que nous puissions travailler avec des nombres IP purs, il est plus facile d'ajouter notre table dans le fichier <file>/etc/iproute2/rt_tables</file>. <tscreen><verb> # echo 200 John >> /etc/iproute2/rt_tables # ip rule add from 10.0.0.10 table John # ip rule ls 0: from all lookup local 32765: from 10.0.0.10 lookup John 32766: from all lookup main 32767: from all lookup default </verb></tscreen> Maintenant, tout ce qu'il reste à faire est de générer la table "John", et de vider le cache des routes : <tscreen><verb> # ip route add default via 195.96.98.253 dev ppp2 table John # ip route flush cache </verb></tscreen> Et voilà qui est fait. Il ne reste plus, comme exercice laissé au lecteur, qu'à implanter cela dans ip-up. <sect>GRE et autres tunnels <p> Il y a trois sortes de tunnels sous Linux : l'IP dans un tunnel IP, le tunnel GRE et les tunnels qui existent en dehors du noyau (comme, par exemple, PPTP). <sect1>Quelques remarques générales à propos des tunnels : <p> Les tunnels peuvent faire des choses très inhabituelles et vraiment sympa. Ils peuvent aussi absolument tout détraquer si vous ne les avez pas configurés correctement. Ne définissez pas votre route par défaut sur un tunnel, à moins que vous ne sachiez <bf>exactement</bf> ce que vous faites. De plus, le passage par un tunnel augmente le poids des en-têtes (overhead), puisqu'un en-tête IP supplémentaire est nécessaire. Typiquement, ce surcoût est de 20 octets par paquet. Donc, si la taille maximum de votre paquet sur votre réseau (MTU) est de 1500 octets, un paquet qui est envoyé à travers un tunnel sera limité à une taille de 1480 octets. Cela n'est pas nécessairement un problème, mais soyez sûr d'avoir bien étudié la fragmentation et le réassemblage des paquets IP quand vous prévoyez de relier des réseaux de grande taille par des tunnels. Et bien sûr, la manière la plus rapide de creuser un tunnel est de creuser des deux côtés. <p> <sect1>IP dans un tunnel IP <p> Ce type de tunnel est disponible dans Linux depuis un long moment. Il nécessite deux modules, ipip.o et new_tunnel.o. Disons que vous avez trois réseaux : 2 réseaux internes A et B, et un réseau intermédiaire C (ou disons Internet). Les caractéristiques du réseau A sont : <tscreen><verb> réseau 10.0.1.0 masque de sous-réseau 255.255.255.0 routeur 10.0.1.1 </verb></tscreen> Le routeur a l'adresse 172.16.17.18 sur le réseau C. et le réseau B : <tscreen><verb> réseau 10.0.2.0 masque de sous-réseau 255.255.255.0 routeur 10.0.2.1 </verb></tscreen> Le routeur a l'adresse 172.19.20.21 sur le réseau C. En ce qui concerne le réseau C, nous supposerons qu'il transmettra n'importe quel paquet de A vers B et vice-versa. Il est également possible d'utiliser l'Internet pour cela. Voici ce qu'il faut faire : Premièrement, assurez-vous que les modules sont installés : <tscreen><verb> insmod ipip.o insmod new_tunnel.o </verb></tscreen> Ensuite, sur le routeur du réseau A, faites la chose suivante : <tscreen><verb> ifconfig tunl0 10.0.1.1 pointopoint 172.19.20.21 route add -net 10.0.2.0 netmask 255.255.255.0 dev tunl0 </verb></tscreen> et sur le routeur du réseau B : <tscreen><verb> ifconfig tunl0 10.0.2.1 pointopoint 172.16.17.18 route add -net 10.0.1.0 netmask 255.255.255.0 dev tunl0 </verb></tscreen> Et quand vous aurez terminé avec votre tunnel : <tscreen><verb> ifconfig tunl0 down </verb></tscreen> Vite fait, bien fait. Vous ne pouvez pas transmettre les paquets de diffusion (broadcast), ni le trafic IPv6 à travers un tunnel IP-IP. Vous ne pouvez connecter que deux réseaux IPv4 qui, normalement, ne seraient pas capables de se "parler", c'est tout. Dans la mesure où la compatibilité a été conservée, ce code tourne depuis un bon moment, et il reste compatible depuis les noyaux 1.3. Le tunnel Linux IP dans IP ne fonctionne pas avec d'autres systèmes d'exploitation ou routeurs, pour autant que je sache. C'est simple, ça marche. Utilisez-le si vous le pouvez, autrement utilisez GRE. <sect1>Le tunnel GRE <p> GRE est un protocole de tunnel qui a été à l'origine développé par Cisco, et qui peut réaliser plus de choses que le tunnel IP dans IP. Par exemple, vous pouvez aussi transporter du trafic multi-diffusion (multicast) et de l'IPv6 à travers un tunnel GRE. Dans Linux, vous aurez besoin du module ip_gre.o. <sect2>Le tunnel IPv4 <p> Dans un premier temps, intéressons-nous au tunnel IPv4 : Disons que vous avez trois réseaux : 2 réseaux internes A et B, et un réseau intermédiaire C (ou disons internet). Les caractéristiques du réseau A sont : <tscreen><verb> réseau 10.0.1.0 masque de sous-réseau 255.255.255.0 routeur 10.0.1.1 </verb></tscreen> Le routeur a l'adresse 172.16.17.18 sur le réseau C. Appelons ce réseau neta. Et pour le réseau B : <tscreen><verb> réseau 10.0.2.0 masque de sous-réseau 255.255.255.0 routeur 10.0.2.1 </verb></tscreen> Le routeur a l'adresse 172.19.20.21 sur le réseau C. Appelons ce réseau netb. En ce qui concerne le réseau C, nous supposerons qu'il transmettra n'importe quels paquets de A vers B et vice-versa. Comment et pourquoi, on s'en fiche. <p> Sur le routeur du réseau A, nous faisons la chose suivante : <tscreen><verb> ip tunnel add netb mode gre remote 172.19.20.21 local 172.16.17.18 ttl 255 ip link set netb up ip addr add 10.0.1.1 dev netb ip route add 10.0.2.0/24 dev netb </verb></tscreen> Discutons un peu de cela. Sur la ligne 1, nous avons ajouté un périphérique tunnel, que nous avons appelé netb (ce qui est évident, dans la mesure où c'est là que nous voulons aller). De plus, nous lui avons dit d'utiliser le protocole GRE (mode gre), que l'adresse distante est 172.19.20.21 (le routeur de l'autre coté), que nos paquets "tunnelés" devront être générés à partir de 172.16.17.18 (ce qui autorise votre serveur à avoir plusieurs adresses IP sur le réseau C et ainsi vous permet de choisir laquelle sera utilisée pour votre tunnel) et que le champ TTL de vos paquets sera fixé à 255 (ttl 255). La deuxième ligne active le périphérique. Sur la troisième ligne, nous avons donné à cette nouvelle interface l'adresse 10.0.1.1. C'est bon pour de petits réseaux, mais quand vous commencez une exploitation minière (BEAUCOUP de tunnels !), vous pouvez utiliser une autre gamme d'adresses IP pour vos interfaces "tunnel" (dans cet exemple, vous pourriez utiliser 10.0.3.0). <p>Sur la quatrième ligne, nous positionnons une route pour le réseau B. Notez la notation différente pour le masque de sous-réseau. Si vous n'êtes pas familiarisé avec cette notation, voici comment ça marche : vous écrivez le masque de sous-réseau sous sa forme binaire, et vous comptez tous les 1. Si vous ne savez pas comment faire cela, rappelez-vous juste que 255.0.0.0 est /8, 255.255.0.0 est /16 et 255.255.255.0 est /24. Et 255.255.254.0 est /23, au cas où ça vous intéresserait. <p> Mais arrêtons ici, et continuons avec le routeur du réseau B. <tscreen><verb> ip tunnel add neta mode gre remote 172.16.17.18 local 172.19.20.21 ttl 255 ip link set neta up ip addr add 10.0.2.1 dev neta ip route add 10.0.1.0/24 dev neta </verb></tscreen> Et quand vous voudrez retirer le tunnel sur le routeur A : <tscreen><verb> ip link set netb down ip tunnel del netb </verb></tscreen> Bien sûr, vous pouvez remplacer netb par neta pour le routeur B. <sect2>Le tunnel IPv6 <p> De petites choses à propos des adresses IPv6 :<p> Les adresses IPv6 sont, en comparaison avec les adresses IPv4, monstrueusement grosses. Voici un exemple : <verb>3ffe:2502:200:40:281:48fe:dcfe:d9bc</verb> Donc, pour rendre l'écriture plus facile, il y a quelques règles : <itemize> <item>Ne pas utiliser les zéros de tête, comme dans IPv4 ; <item>Utiliser des double-points de séparation tous les 16 bits (2 octets) ; <item>Quand vous avez beaucoup de zéros consécutifs, vous pouvez écrire <tt>::</tt>. Vous ne pouvez faire cela qu'une seule fois par adresse et seulement pour une longueur de 16 bits. </itemize> En utilisant ces règles, l'adresse 3ffe:0000:0000:0000:0000:0020:34A1:F32C peut être écrite 3ffe::20:34A1:F32C, ce qui est beaucoup plus court. <p> À propos des tunnels. Supposons que vous ayez le réseau IPv6 suivant, et que vous vouliez le connecter à une dorsale IPv6 (6bone), ou à un ami. <tscreen><verb> Réseau 3ffe:406:5:1:5:a:2:1/96 </verb></tscreen> Votre adresse IPv4 est 172.16.17.18, et le routeur 6bone a une adresse IPv4 172.22.23.24. <p> <tscreen><verb> ip tunnel add sixbone mode sit remote 172.22.23.24 local 172.16.17.18 ttl 255 ip link set sixbone up ip addr add 3ffe:406:5:1:5:a:2:1/96 dev sixbone ip route add 3ffe::/15 dev sixbone </verb></tscreen> Voyons cela de plus près. Sur la première ligne, nous avons créé un périphérique tunnel appelé sixbone. Nous lui avons affecté le mode "sit" (qui est le tunnel IPv6 sur IPv4) et lui avons dit où l'on va (remote) et d'où l'on vient (local). TTL est configuré à son maximum, 255. Ensuite, nous avons rendu le périphérique actif (up). Puis, nous avons ajouté notre propre adresse réseau et configuré une route pour 3ffe::/15 à travers le tunnel. <p> Les tunnels GRE constituent actuellement le type préféré de tunnel. C'est un standard qui est largement adopté, même à l'extérieur de la communauté Linux, ce qui constitue une bonne raison de l'utiliser. </p> <sect1>Tunnels dans l'espace utilisateur <p> Il y a des dizaines d'implémentations de tunnels à l'extérieur du noyau. Les plus connus sont bien sûr PPP et PPTP, mais il y en a bien plus (certains propriétaires, certains sécurisés, d'autres qui n'utilisent pas IP), qui dépassent le cadre de cet HOWTO. <sect>Tunnel IPv6 avec Cisco et/ou une dorsale IPv6 (6bone) <p> Par Marco Davids <marco@sara.nl> NOTE au mainteneur : En ce qui me concerne, ce tunnel IPv6-IPv4 n'est pas, par définition, un tunnel GRE. Vous pouvez réaliser un tunnel IPv6 sur IPv4 au moyen des périphériques tunnels GRE (tunnels GRE N'IMPORTE QUOI vers IPv4), mais le périphérique utilisé ici ("sit") ne permet que des tunnels IPv6 sur IPv4, ce qui est quelque chose de différent. <sect1>Tunnel IPv6 <p> Voici une autre application des possibilités de tunnels de Linux. Celle-ci est populaire parmi les premiers adeptes d'IPv6, ou les pionniers si vous préférez. L'exemple pratique décrit ci-dessous n'est certainement pas la seule manière de réaliser un tunnel IPv6. Cependant, c'est la méthode qui est souvent utilisée pour réaliser un tunnel entre Linux et un routeur Cisco IPv6. L'expérience m'a apprise que c'est ce type d'équipement que beaucoup de personnes ont. Dix contre un que ceci s'appliquera aussi pour vous ;-). De petites choses à propos des adresses IPv6 :<p> Les adresses IPv6 sont, en comparaison avec les adresses IPv4, vraiment grandes : 128 bits contre 32 bits. Et ceci nous fournit la chose dont nous avons besoin : beaucoup, beaucoup d'adresses IP : 340,282,266,920,938,463,463,374,607,431,768,211,465 pour être précis. A part ceci, IPv6 (ou IPng pour Next Generation (génération suivante)) est supposé fournir des tables de routage plus petites sur les routeurs des dorsales Internet, une configuration plus simple des équipements, une meilleure sécurité au niveau IP et un meilleur support pour la Qualité de Service (QoS). Un exemple : 2002:836b:9820:0000:0000:0000:836b:9886 Ecrire les adresses IPv6 peut être un peu lourd. Il existe donc des règles qui rendent la vie plus facile : <itemize> <item> Ne pas utiliser les zéros de tête, comme dans IPv4 ; <item>Utiliser des double-points de séparation tous les 16 bits ou 2 octets ; <item>Quand vous avez beaucoup de zéros consécutifs, vous pouvez écrire <tt>::</tt>. Vous ne pouvez, cependant, faire cela qu'une seule fois par adresse et seulement pour une longueur de 16 bits. </itemize> L'adresse 2002:836b:9820:0000:0000:0000:836b:9886 peut être écrite 2002:836b:9820::836b:9886, ce qui est plus amical. IPv6 a pour but d'être le successeur de l'actuel IPv4. Dans la mesure où cette technologie est relativement récente, il n'y a pas encore de réseau natif IPv6 à l'échelle mondiale. Pour permettre un développement rapide, la dorsale IPv6 (6bone) a été introduite. Les réseaux natifs IPv6 sont interconnectés grâce à l'encapsulation du protocole IPv6 dans des paquets IPv4, qui sont envoyés à travers l'infrastructure IPv4 existante, d'une site IPv6 à un autre. C'est dans ce cas où les tunnels sont montés. Pour être capable d'utiliser IPv6, vous devrez avoir un noyau qui le supporte. Il y a beaucoup de bons documents qui expliquent la manière de réaliser cela. Mais, tout se résume à quelques étapes : <itemize> <item>Récupérer une distribution Linux récente, avec une glibc convenable. <item>Récupérer alors les sources à jour du noyau. </itemize> Si tout cela est fait, vous pouvez alors poursuivre en compilant un noyau supportant l'IPv6 : <itemize> <item>Aller dans /usr/src/linux et tapez : <item>make menuconfig <item>Choisir "Networking Options" <item>Sélectionner "The IPv6 protocol", "IPv6: enable EUI-64 token format", "IPv6: disable provider based addresses" </itemize> ACTUCE :Ne compiler pas ces options en tant que module. Ceci ne marchera souvent pas bien. En d'autres termes, compilez IPv6 directement dans votre noyau. Vous pouvez alors sauvegarder votre configuration comme d'habitude et entreprendre la compilation de votre noyau. ASTUCE: Avant de faire cela, modifier votre Makefile comme suit : EXTRAVERSION = -x ; --> ; EXTRAVERSION = -x-IPv6 Il y a beaucoup de bonnes documentations sur la compilation et l'installation d'un noyau. Cependant, ce document ne traite pas de ce sujet. Si vous rencontrez des problèmes à ce niveau, allez et recherchez dans la documentation des renseignements sur la compilation du noyau Linux correspondant à vos propres spécifications. Le fichier /usr/src/linux/README peut constitué un bon départ. Après avoir réalisé tout ceci, et redémarré avec votre nouveau noyau flamband neuf, vous pouvez lancer la commande '/sbin/ifconfig -a' et noter un nouveau périphérique 'sit0'. SIT signifie Simple Internet Transition (Transition Simple d'Internet). Vous pouvez vous auto-complimentez : vous avez maintenant franchi une étape importante vers IP, la prochaine génération ;-) Passons maintenant à l'étape suivante. Vous voulez connecter votre hôte, ou peut-être même tout votre réseau LAN à d'autres réseaux IPv6. Cela pourrait être la dorsale IPv6 "6bone" qui a été spécialement mise en place dans ce but particulier. Supposons que vous avez le réseau IPv6 suivant : 3ffe:604:6:8::/64 et que vous vouliez le connecter à une dorsale IPv6 ou à un ami. Notez, s'il vous plait, que la notation sous-réseau /64 est similaire à celle des adresses IPv4. Votre adresse IPv4 est 145.100.24.181 et le routeur 6bone a l'adresse IPv4 145.100.1.5 <tscreen><verb> # ip tunnel add sixbone mode sit remote 145.100.1.5 [local 145.100.24.181 ttl 225] # ip link set sixbone up # ip addr add 3FFE:604:6:7::2/126 dev sixbone # ip route add 3ffe::0/16 dev sixbone </verb></tscreen> Discutons de ceci. Dans la première ligne, nous avons créé un périphérique appelé sixbone. Nous lui avons donné l'attribut sit (mode sit) (qui est le tunnel IPv6 dans IPv4) et nous lui avons dit où aller (remote) et d'où nous venions (local). TTL est configuré à son maximum, 255. Ensuite, nous avons rendu le périphérique actif (up). Après cela, nous avons ajouté notre propre adresse réseau et configuré une route pour 3ffe::/15 (qui est actuellement la totalité du 6bone) à travers le tunnel. Si la machine sur laquelle vous mettez en place tout ceci est votre passerelle IPv6, ajoutez alors les lignes suivantes : <tscreen><verb> # echo 1 >/proc/sys/net/ipv6/conf/all/forwarding # /usr/local/sbin/radvd </verb></tscreen> La dernière, radvd est, comme zebra, un démon d'annonce qui permet de supporter les fonctionnalités d'autoconfiguration d'IPv6. Recherchez le avec votre moteur de recherche favori. Vous pouvez vérifier les choses comme ceci : <tscreen><verb> # /sbin/ip -f inet6 addr </verb></tscreen> Si vous arrivez à avoir radvd tournant sur votre passerelle IPv6 et que vous démarrez une machine avec IPv6 sur votre réseau local, vous serez ravi de voir les bénéfices de l'autoconfiguration IPv6 : <tscreen><verb> # /sbin/ip -f inet6 addr 1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue inet6 ::1/128 scope host 3: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100 inet6 3ffe:604:6:8:5054:4cff:fe01:e3d6/64 scope global dynamic valid_lft forever preferred_lft 604646sec inet6 fe80::5054:4cff:fe01:e3d6/10 scope link </verb></tscreen> Vous pouvez maintenant configurer votre serveur de noms pour les adresses IPv6. Le type A a un équivalent pour IPv6 : AAAA. L'équivalent de in-addr.arpa est : ip6.int. Il y a beaucoup d'informations disponibles sur ce sujet. Il y a un nombre croissant d'applications IPv6 disponibles, comme le shell sécurisé, telnet, inetd, Mozilla le navigateur, Apache le serveur web et beaucoup d'autres. Mais ceci est en dehors du sujet de ce document de routage ;-). Sur le site Cisco, la configuration ressemblera à ceci : <tscreen><verb> ! interface Tunnel1 description IPv6 tunnel no ip address no ip directed-broadcast ipv6 enable ipv6 address 3FFE:604:6:7::1/126 tunnel source Serial0 tunnel destination 145.100.24.181 tunnel mode ipv6ip ! ipv6 route 3FFE:604:6:8::/64 Tunnel1 </verb></tscreen> Si vous n'avez pas un Cisco à votre disposition, essayez un des prestataires de tunnel IPv6 disponible sur Internet. Ils sont prêts à configurer leur Cisco avec un tunnel suplémentaire pour vous, le plus souvent au moyen d'une agréable interface web. Cherchez "ipv6 tunnel broker" avec votre moteur de recherche favori. <sect>IPsec : IP sécurisé à travers l'Internet <p> FIXME: Pas de rédacteur ! En attendant, voir: <url url="http://www.freeswan.org/" name="Le projet FreeS/WAN">. <sect>Routage multi-diffusion (multicast) <p> FIXME: Pas de rédacteur ! <sect>Utilisation de la mise en file d'attente basée sur des classes ("Class Based Queueing") pour la gestion de la bande passante <p> Quand je l'ai découvert, cela m'a <em>vraiment</em> soufflé. Linux 2.2 contient toutes les fonctionnalités pour la gestion de la bande passante, de manière comparable à un système dédié de haut niveau. Linux dépasse même ce que l'ATM et le Frame peuvent fournir. Les deux unités de base du Contrôle de Trafic sont les filtres et les files d'attente. Les filtres placent le trafic dans des files d'attente, qui recueillent ainsi le trafic et décident ce qu'il faut envoyer en premier, envoyer plus tard, ou éliminer. Il existe plusieurs variantes de filtres et de files d'attente. Les filtres les plus communs sont fwmark et u32. Le premier vous permet d'utiliser le code Netfilter de Linux pour sélectionner le trafic, et le second vous permet de sélectionner ce trafic à partir de N'IMPORTE QUEL en-tête. La file d'attente la plus connue est la Class Based Queue (File d'attente basée sur des classes). CBQ est une super-file d'attente, qui peut contenir d'autres files d'attente (même d'autres CBQ). Il n'est peut-être pas évident de voir ce que la mise en file d'attente peut avoir à faire avec la gestion de bande passante, mais ça marche vraiment. Pour cadre de référence de cette section, j'ai pris l'exemple d'un fournisseur d'accès chez qui j'ai appris les ficelles du métier, pour ne pas le citer : Casema Internet en Hollande. Casema, qui est actuellement un câble-opérateur, a des besoins internet pour ses clients et pour son propre compte. La plupart des ordinateurs de la société ont un accès Internet. En réalité, ils ont beaucoup d'argent à dépenser et n'utilisent pas Linux pour la gestion de la bande passante. Nous étudierons comment notre fournisseur d'accès aurait pu utiliser Linux pour gérer sa bande passante. <sect1>Qu'est-ce que la mise en file d'attente ? <p> Avec la mise en file d'attente, nous déterminons l'ordre dans lequel les données sont <em>envoyées</em>. Il est important de le comprendre, nous ne pouvons que mettre en forme les données que nous transmettons. Comment ce changement de prioriré détermine-t-il la vitesse de transmission ? Imaginez une caisse enregistreuse capable de traiter 3 clients par minute. Les personnes souhaitant payer vont attendre en file indienne en bout de queue. C'est une "file d'attente FIFO". (NdT : FIFO = First In, First Out, premier entré, premier sorti) Supposons maintenant que vous laissiez toujours certaines personnes s'insérer au milieu de la queue, et non en fin. Ces personnes attendront moins de temps et donc pourront faire leurs courses plus rapidement. Avec la manière dont Internet travaille, nous n'avons pas de contrôle direct de ce que les personnes nous envoient. C'est un peu comme votre boîte aux lettres (physique !) chez vous. Il n'y a pas de façon d'influencer le nombre de lettres que vous recevez, à moins de contacter tout le monde. Cependant, l'Internet est principalement basé sur TCP/IP qui possède quelques fonctionnalités qui vont pouvoir nous aider. TCP/IP n'a pas d'aptitude à connaître les performances d'un réseau entre deux hôtes. Il commence à envoyer des paquets, de plus en plus rapidement ('slow start') et quand des paquets commencent à se perdre, il ralentit. C'est comme si vous ne lisiez que la moitié de votre courrier en espérant que vos correspondants arrêteront de vous en envoyer. À la différence du courrier, ça marche sur l'Internet :-) FIXME: Expliquer la congestion des fenêtres <tscreen><verb> [L'Internet] ---<E3, T3, peu importe>--- [Routeur Linux] --- [Bureau+FAI] eth1 eth0 </verb></tscreen> Maintenant, notre routeur Linux a deux interfaces que je vais appeler eth0 et eth1. Eth1 est connecté à notre routeur qui transmet les paquets venant de ou allant vers notre fibre optique. Eth0 est connecté à un sous-réseau qui contient à la fois le pare-feu de la société et notre équipement de tête, à travers lequel nos clients peuvent se connecter. Dans la mesure où nous ne pouvons limiter que ce que nous envoyons, nous avons besoin de deux ensembles de règles séparés, mais très similaires. En modifiant la mise en file d'attente sur eth0, nous déterminons à quelle vitesse les données reçues sont envoyées à nos clients. On détermine ainsi la bande passante descendante disponible vers eux, en résumé, leur "vitesse de téléchargement". Sur eth1, nous déterminons à quelle vitesse nous envoyons les données sur Internet, à quelle vitesse nos utilisateurs, à la fois ceux de la société et les clients, peuvent émettre les données. <sect1>Première tentative de partage de bande passante <p> CBQ nous permet de créer plusieurs classes, et même des classes incluses dans d'autres classes. Les divisions les plus larges peuvent être appelées des agences. Au sein de ces classes, se trouveraient des classes comme "traitement par lot" et "traitement interactif". Par exemple, nous pourrions avoir une connexion Internet de 10 Mbits devant être partagée par nos clients et les besoins de la société. Nous ne devons pas permettre à quelques personnes de la société de monopoliser un gros volume de bande passante, qui devrait être vendue à nos clients. D'un autre côté, nos clients ne doivent pas pouvoir grignoter le trafic réservé à nos bureaux. Avant, une manière de résoudre cela était d'utiliser le Frame relay/ATM et de créer des circuits virtuels. Cela fonctionne, mais les réseaux Frame Relay ne sont pas suffisament maillés et ATM est terriblement inefficace dans le transport du trafic IP. Ni l'un ni l'autre ne possède de moyens standardisés pour distribuer le trafic sur différents circuits virtuels (VC). Cependant, si vous utilisez ATM, Linux peut habilement réaliser des tâches de classification de trafic pour vous. Une autre manière de procéder consiste à commander plusieurs connexions séparées mais ce n'est ni pratique ni élégant et ça ne résoudra pas tous vos problèmes. CBQ à la rescousse ! Clairement, nous avons ici deux classes principales, "ISP" et "Office". Au départ, on ne se préoccupe pas vraiment de ce que les divisions font de leur bande passante, et donc, nous ne subdiviserons pas plus loin leurs classes. Nous décidons que les clients devront toujours avoir 8 Mbits de trafic descendant garanti, et nos bureaux 2 Mbits. La configuration du contrôle de trafic est faite avec l'outil <tt>tc</tt>, du paquet iproute2. <tscreen><verb> # tc qdisc add dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000 </verb></tscreen> <p>Bon, beaucoup de chiffres ici. Qu'avons-nous fait ? Nous avons configuré la gestion de la mise en file d'attente (queuing discipline) de eth0. Par "root", nous signifions que cette file d'attente est la racine. Nous lui avons donné la référence (handle) "10:". Nous voulons faire du "CBQ", nous le mentionnons donc sur la ligne de commande. Nous indiquons au noyau qu'il peut allouer 10 Mbits et que la taille moyenne d'un paquet est aux alentours de 1000 octets. Maintenant, nous devons générer notre classe racine, à partir de laquelle toutes les autres descendront : <tscreen><verb> # tc class add dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate \ 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000 </verb></tscreen> <p> Encore des nombres à gérer - l'implémentation CBQ dans Linux est très générique. Avec "parent 10:0", nous indiquons que cette classe descend de la file d'attente racine générée plus tôt, et référencée par "10:". Avec "classid 10:1", nous baptisons cette nouvelle classe. Nous ne disons vraiment rien de plus au noyau. Nous générons simplement une classe qui englobe toute la bande passante disponible sur l'interface. Nous avons aussi spécifié que le MTU (plus l'en-tête) est de 1514 octets. Nous appliquons une pondération à cette classe avec un paramètre de réglage de 1 Mbit. Maintenant, nous créons notre classe ISP : <tscreen><verb> # tc class add dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate \ 8Mbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 \ bounded </verb></tscreen> <p> Nous allouons 8 Mbits et nous indiquons que cette classe ne doit pas dépasser cette limite par l'ajout du paramètre "bounded". Autrement, elle aurait commencé à emprunter de la bande passante aux autres classes. De plus, cette classe pourra prêter sa bande passante à d'autres classes. Nous en discuterons plus tard. Pour finir, nous générons la classe "Office" (bureau) : <tscreen><verb> # tc class add dev eth0 parent 10:1 classid 10:200 cbq bandwidth 10Mbit rate \ 2Mbit allot 1514 weight 200Kbit prio 5 maxburst 20 avpkt 1000 \ bounded </verb></tscreen> Pour rendre les choses un peu plus claires, voici un diagramme qui montre nos classes : <tscreen><verb> +-------------[10: 10Mbit]----------------------+ |+-------------[10:1 root 10Mbit]--------------+| || || || +-[10:100 8Mbit]-+ +--[10:200 2Mbit]-----+ || || | | | | || || | ISP | | Office | || || | | | | || || +----------------+ +---------------------+ || || || |+---------------------------------------------+| +-----------------------------------------------+ </verb></tscreen> Nous avons maintenant indiqué au noyau quelles sont nos classes, mais pas encore comment gérer les files d'attente. Nous le faisons à présent, d'un seul coup pour les deux classes. <tscreen><verb> # tc qdisc add dev eth0 parent 10:100 sfq quantum 1514b perturb 15 # tc qdisc add dev eth0 parent 10:200 sfq quantum 1514b perturb 15 </verb></tscreen> Dans ce cas, nous installons le gestionnaire de mise en file d'attente Stochastic Fairness Queueing (approx. "statistiquement équitable") ou sfq, qui n'est pas vraiment le plus équitable, mais qui marche bien pour les grandes bandes passantes, sans utiliser trop de temps CPU. Il existe d'autres gestionnaires de file d'attente qui sont meilleurs, mais qui nécessitent plus de temps CPU. Le gestionnaire de mise en file d'attente Token Bucket Filter (filtre à seau de jetons) est souvent utilisé. Maintenant, la seule chose qui reste à faire est de dire au noyau quels sont les paquets qui appartiennent à une classe. Nous le ferons tout d'abord nativement avec iproute2, mais des applications plus intéressantes sont possibles en combinaison avec netfilter. <tscreen><verb> # tc filter add dev eth0 parent 10:0 protocol ip prio 100 u32 match ip dst \ 150.151.23.24 flowid 10:200 # tc filter add dev eth0 parent 10:0 protocol ip prio 25 u32 match ip dst \ 150.151.0.0/16 flowid 10:100 </verb></tscreen> Ici, on suppose que notre société (classe Office) est cachée derrière un pare-feu avec l'adresse IP 150.151.23.24 et que toutes nos autres adresses IP devront être considérées comme faisant partie de la classe ISP. La classificateur u32 est un modèle très simple ; des règles de classification plus sophistiquées sont possibles lorsque l'on utilise netfilter pour marquer nos paquets. On peut ensuite utiliser ce marquage avec <tt>tc</tt>. Maintenant, nous avons divisé équitablement la bande passante descendante, et nous avons besoin de faire la même chose avec le flux montant. Pour abréger, voici toutes les commandes en bloc : <tscreen><verb> # tc qdisc add dev eth1 root handle 20: cbq bandwidth 10Mbit avpkt 1000 # tc class add dev eth1 parent 20:0 classid 20:1 cbq bandwidth 10Mbit rate \ 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000 # tc class add dev eth1 parent 20:1 classid 20:100 cbq bandwidth 10Mbit rate \ 8Mbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 \ bounded # tc class add dev eth1 parent 20:1 classid 20:200 cbq bandwidth 10Mbit rate \ 2Mbit allot 1514 weight 200Kbit prio 5 maxburst 20 avpkt 1000 \ bounded # tc qdisc add dev eth1 parent 20:100 sfq quantum 1514b perturb 15 # tc qdisc add dev eth1 parent 20:200 sfq quantum 1514b perturb 15 # tc filter add dev eth1 parent 20:0 protocol ip prio 100 u32 match ip src \ 150.151.23.24 flowid 20:200 # tc filter add dev eth1 parent 20:0 protocol ip prio 25 u32 match ip src \ 150.151.0.0/16 flowid 20:100 </verb></tscreen> <sect1>Que faire de la bande passante en excès ? <p> Dans notre exemple, il se trouve que même si les clients du fournisseur d'accès ne sont pas en majorité connectés (disons 8 heures du matin), nos bureaux n'ont toujours que 2 Mbits, ce qui est un peu du gaspillage. En enlevant le paramètre "bounded", les classes pourront se prêter de la bande passante les unes aux autres. Il se peut que des classes ne souhaitent pas prêter leur bande passante à d'autres. Deux fournisseurs d'accès rivaux sur un même lien peuvent ne pas vouloir s'offrir mutuellement de la bande passante pour des prunes. Dans ce cas, vous pouvez ajouter le mot-clé "isolated" à la fin de vos lignes "tc class add". <sect1>Subdivisions de classes <p> FIXME: suppositions qui n'ont pas du tout été testées ! Les essayer  ! Nous pouvons aller plus loin. Supposons que tous les employés décident de lancer leur client "napster", il est toujours possible que notre base de données de routage dépasse la capacité de bande passante. Pour ce cas de figure, nous créons deux sous-classes, "Human" et "Database". Notre base de données a toujours besoin de 500 Kbits, il nous reste donc 1,5 Mbits pour la consommation de la classe "Human". Nous devons donc créer deux nouvelles classes à l'intérieur de la classe Office : <tscreen><verb> # tc class add dev eth0 parent 10:200 classid 10:250 cbq bandwidth 10Mbit rate \ 500Kbit allot 1514 weight 50Kbit prio 5 maxburst 20 avpkt 1000 \ bounded # tc class add dev eth0 parent 10:200 classid 10:251 cbq bandwidth 10Mbit rate \ 1500Kbit allot 1514 weight 150Kbit prio 5 maxburst 20 avpkt 1000 \ bounded </verb></tscreen> FIXME: Finir cet exemple! <sect1>Équilibrage de charge sur plusieurs interfaces <p> Il y a plusieurs manières de faire ceci. Une des plus faciles et des plus directes est 'TEQL' - True (ou Trivial) Link Equalizer. Comme la plupart des éléments en relation avec la gestion de file d'attente, l'équilibrage de charge est bidirectionnel. Les deux équipements terminaux du lien ont besoin de participer pour un effet optimal. Imaginer la situation suivante : <tscreen><verb> +-------+ eth1 +-------+ | |==========| | 'réseau 1' -----| A | | B |---- 'réseau 2' | |==========| | +-------+ eth2 +-------+ </verb></tscreen> A et B sont des routeurs que nous supposerons pour le moment fonctionner sous Linux. Si le trafic va du réseau 1 vers le réseau 2, le routeur A a besoin de distribuer les paquets sur les deux liens allant vers B. Le routeur B a besoin d'être configuré pour accepter ceci. On a la même chose dans le sens inverse, pour les paquets allant du réseau 2 vers le réseau 1. Le routeur B a besoin d'envoyer les paquets à la fois sur eth1 et eth2. La répartition est faite par un périphérique 'TEQL', comme ceci (cela ne pouvait pas être plus simple) : <tscreen><verb> # tc qdisc add dev eth1 root teql0 # tc qdisc add dev eth2 root teql0 </verb></tscreen> Ceci a besoin d'être fait sur les deux hôtes. Le périphérique teql0 est basiquement un distributeur tourniquet au dessus de eth1 et eth2 pour l'envoi des paquets. Aucunes données n'arrivent jamais à travers un périphérique teql, mais apparaissent sur eth1 et eth2. Nous n'avons pour le moment que les périphériques et nous avons également besoin d'un routage correct. L'une des possibilités pour réaliser cela est d'assigner un réseau /31 sur chacun des liens, ainsi que sur le périphérique teql0 : FIXME: Avons nous besoin de quelque chose comme 'nobroadcast' ? Un /31 est trop petit pour contenir une adresse réseau et une adresse de diffusion. Si cela ne marche pas comme prévu, essayer un /30, et ajuster les addresses IP. Vous pouvez même essayer sans attribuer d'adresses à eth1 et eth2. Sur le router A: <tscreen><verb> # ip addr add dev eth1 10.0.0.0/31 # ip addr add dev eth2 10.0.0.2/31 # ip addr add dev teql0 10.0.0.4/31 </verb></tscreen> Sur le router B: <tscreen><verb> # ip addr add dev eth1 10.0.0.1/31 # ip addr add dev eth2 10.0.0.3/31 # ip addr add dev teql0 10.0.0.5/31 </verb></tscreen> Le routeur A devrait maintenant être capable de pinguer 10.0.0.1, 10.0.0.3 et 10.0.0.5 à travers les deux liens physiques et le périphérique "égalisé". Le routeur A devrait maintenant être capable de pinguer 10.0.0.0, 10.0.0.2 et 10.0.0.4 à travers les liens. Si cela marche, le routeur A peut prendre 10.0.0.5 comme route vers le réseau 2 et le routeur B 10.0.0.4 comme route vers le réseau 1. Pour le cas particulier où le réseau 1 est votre réseau chez vous et où le réseau 2 est l'Internet, le routeur A peut prendre 10.0.0.5 comme passerelle par défaut. <sect2>Avertissement <p> Rien n'est aussi simple qu'il y parait. Eth1 et eth2 sur les deux routeurs A et B doivent avoir le filtrage par chemin inverse désactivé. Dans le cas contraire, ils rejetteront les paquets destinés à des adresses autres que les leurs : <tscreen><verb> # echo 0 > /proc/net/ipv4/conf/eth1/rp_filter # echo 0 > /proc/net/ipv4/conf/eth2/rp_filter </verb></tscreen> Il y a un sale problème de réarrangement des paquets. Supposons que six paquets aient besoin d'être envoyés de A vers B. Eth1 peut, par exemple, traiter les paquets 1, 3 et 5 et eth2 les paquets 2, 4 et 6. Dans un monde idéal, le routeur B devrait recevoir ces paquets dans l'ordre 1, 2, 3, 4, 5, 6. Mais le fait le plus probable est que le noyau les reçoive comme ceci : 2, 1, 4, 3, 6, 5. Le problème est que cela va perturber TCP/IP. Alors qu'il n'y a pas de problèmes pour les liens transportant différentes sessions TCP/IP, vous ne serez pas capable de regrouper plusieurs liens et obtenir par ftp un simple fichier beaucoup plus rapidement, à moins que le système d'exploitation envoyant ou recevant ne soit Linux. En effet, celui-ci n'est pas facilement perturbé par de simples réarrangements. Cependant, l'équilibrage de charge est une bonne idée pour de nombreuses applications. <sect>D'autres gestionnaires de mise en file d'attente (queueing disciplines) <p> Le noyau Linux nous offre beaucoup de gestionnaires de mises en file d'attente. Le plus largement utilisé est de loin la file d'attente pfifo_fast, qui est celle par défaut. Cela explique aussi pourquoi ces fonctionnalités avancées sont si robustes. Un autre modèle de file d'attente ne coûte rien en développement. Chacune de ces files d'attente a ses forces et ses faiblesses. Toutes n'ont peut-être pas été bien testées. <sect1>pfifo_fast <p> Cette file d'attente, comme son nom l'indique (fifo = premier entré, premier sorti), signifie qu'il n'y a pas de traitement spécial pour les paquets reçus. En fait, ce n'est pas tout à fait vrai. Cette file d'attente a trois "bandes". À l'intérieur de chacune de ces bandes, la règle FIFO est appliquée. Cependant, tant qu'il y a un paquet en attente dans la "bande" 0, la "bande" 1 ne sera pas traitée. Il en va de même pour la "bande" 1 et la "bande" 2. <sect1>Stochastic Fairness Queueing <p> SFQ, comme dit précédemment, n'est pas vraiment déterministe, mais marche (en moyenne). Ses principaux avantages sont qu'elle a besoin de peu de CPU et de mémoire. Une véritable mise en file d'attente équitable nécessite que le noyau garde une trace de toutes les sessions courantes. Stochastic Fairness Queueing (SFQ) est une implémentation simple de la famille des algorithmes de mise en file d'attente équitable. Cette implémentation est moins précise, mais nécessite aussi moins de calculs que les autres tout en étant presque parfaitement équitable. Le concept clé dans SFQ est la conversation (ou flux), qui est une séquence de paquets de données ayant suffisamment de paramètres communs pour les distinguer des autres conversations. Les paramètres utilisés dans le cas de paquets IP sont les adresses de source et de destination, ainsi que le numéro de protocole. SFQ consiste en l'allocation dynamique de files d'attente FIFO, une par conversation. Le gestionnaire de mise en file d'attente travaille en tourniquet (round-robin), envoyant un paquet de chaque FIFO à chaque tour. C'est pour cette raison qu'il est réputé équitable. Le principal avantage de SFQ est qu'il autorise le partage équitable du lien entre plusieurs applications et évite la monopolisation de la bande passante par un client. SFQ ne peut cependant pas distinguer les flux interactifs des flux de masse. On a, en général, recours à CBQ pour effectuer cette distinction, et diriger le flux de masse vers SFQ. [NdT : par flux de masse, il faut entendre gros flot de données, transmis en continu, comme un transfert FTP, par opposition à un flux interactif, comme celui généré par des requêtes HTTP]. <sect1>Token Bucket Filter <p> Le Token Bucket Filter (TBF) est une file d'attente simple. Elle ne fait que passer les paquets entrants avec un taux de transfert dont les limites sont fixées administrativement. Il est possible de placer en mémoire tampon de courtes rafales de données. L'implémentation TBF consiste en un tampon (seau), constamment rempli par des morceaux d'informations virtuelles appelés jetons, avec un débit spécifique (débit de jeton). Le paramètre le plus important du tampon est sa taille, qui est le nombre de jetons qu'il peut stocker. Chaque jeton arrivant laisse sortir un paquet de données entrant de la file d'attente. Ce paquet est alors effacé du seau. L'association de cet algorithme avec les deux flux de jetons et de données, nous donne trois scénarios possibles : <itemize> <item> Les données arrivent dans TBF avec un débit <em>égal</em> au débit des jetons entrants. Dans ce cas, chaque paquet entrant a son jeton correspodant et passe la file d'attente sans délai. <item> Les données arrivent dans TBF avec un débit <em>plus petit</em> que le débit des jetons. Seuls quelques jetons sont supprimés quand les paquets de données sortent de la file d'attente. Les jetons s'accumulent donc jusqu'à atteindre la taille du tampon. Les jetons en réserve peuvent être utilisés pour envoyer des données avec un débit supérieur au débit des jetons, si de courtes rafales de données arrivent. <item> Les données arrivent dans TBF avec un débit <em>plus grand</em> que le débit des jetons. Dans ce cas, un dépassement de filtre a lieu. Les données entrantes peuvent être envoyées sans perte jusqu'à ce que les jetons accumulés soient utilisés. Après, les paquets au-dessus de la limite sont éliminés. </itemize> <p> Le dernier scénario est très important, parce qu'il autorise la mise en forme administrative de la bande passante disponible pour les données traversant le filtre. L'accumulation de jetons autorise l'émission de courtes rafales de données sans perte, mais toute surcharge restante causera la perte systématique des paquets. Le noyau Linux semble aller au-delà de cette spécification, et nous autorise aussi à limiter la vitesse de la transmission par rafales. Cependant, Alexey nous avertit : <tscreen> Noter que le débit de pointe de TBF est beaucoup plus coriace : avec un MTU à 1500, P_crit = 150 Koctets/s. Donc, si vous avez besoin d'un débit de pointe plus grand, utilisez une alpha avec HZ=1000 :-) </tscreen> FIXME: Est-ce encore vrai avec TSC (pentium+) ou équivalent ? <!-- NdT : Ce commentaire n'est pas très clair. Je le traduis comme trouvé dans le document original. C'est comme ceci (de sch_tbf.c): Noter que la résolution minimale de la synchronisation est 1/HZ. Si aucun nouveau paquet n'arrive pendant cette période, ou si le périphérique n'est pas réveillé par un EOI d'un paquet précédent. Donc, cela est vrai aussi longtemps que la machine est relativement silencieuse. Sur un routeur avec beaucoup de trafic, on est limité par la bande passante de l'interface. --> FIXME: Si ce n'est pas le cas, ajouter une section sur l'augmentation de fréquence <sect1>Random Early Detect <p> RED comporte quelques finesses supplémentaires. Quand une session TCP/IP démarre, on ne connaît pas la bande passante disponible. TCP/IP commence donc à transmettre lentement et va de plus en plus vite, mais est limité par le temps de latence au bout duquel les ACKs (acquittements) reviennent. Une fois qu'un lien est saturé, RED commence à éliminer des paquets, ce qui indique à TCP/IP que le lien est congestionné, et qu'il devrait ralentir. La finesse réside dans le fait que RED simule la congestion réelle, et commence parfois à éliminer des paquets avant que le lien ne soit complètement saturé. Une fois que le lien est complètement saturé, il se comporte comme un contrôleur normal. Pour plus d'informations sur le sujet, voir le chapitre Dorsale. <sect1>Ingress policer qdisc <p> Ingress qdisc sert si vous avez besoin de limiter le débit d'un hôte sans l'aide de routeurs ou d'autres machines Linux. Vous pouvez gérer la bande passante entrante et jeter des paquets quand cette bande passante dépasse le débit désiré. Cela peut, par exemple, préserver votre hôte d'une attaque SYN flood. Cela peut aussi servir à ralentir TCP/IP, qui réagit à la perte des paquets par la réduction de la vitesse. FIXME: au lieu d'éliminer des paquets, pouvons-nous également les envoyer vers une vraie file d'attente ? FIXME: la mise en forme en éliminant des paquets semble moins désirable que d'utiliser, par exemple, un filtre token bucket. Pas sûr cependant, les routeurs Cisco travaillent de cette manière, et les gens semblent en être contents. Voir la référence <ref id="CAR" name="IOS Committed Access Rate"> à la fin de ce document. <!-- FIXME: Ce fixme était une question, pas un fait établi :-) - ahu Ancien texte : Pour les connexions TCP/IP, il est préférable de retarder les paquets plutôt que de les éliminer. TCP/IP répond aux paquets perdus par une réduction brutale de la vitesse, tandis que si le paquet est simplement retardé, le ralentissement est plus graduel. C'est également mieux pour l'utilisation de la bande passante, dans la mesure où les paquets éliminés doivent être réenvoyés. Cela n'est pas tout à fait vrai, voir les séries W. Stevens TCP/IP Illustrated - ahu --> En résumé, vous pouvez utiliser cela pour limiter la vitesse de téléchargement des fichiers et, donc, laisser plus de bande passante disponible pour les autres. Voir la section sur la protection de votre hôte des attaques SYN flood pour un exemple de la manière dont cela marche. <sect1>DSMARK <p> Ce chapitre a été écrit par Esteve Camps <esteve@hades.udg.es>. <sect2>Introduction <p> Avant tout, il serait préférable de lire les RFC écrits sur ce sujet (RFC2474, RFC2475, RFC2597 et RFC2598) sur le <url url="http://www.ietf.org/html.carters/diffserv-charter.html" name=" site web du groupe de travail DiffServ IETF"> et sur le <url url="http://ica1www.epfl.ch/~almesber" name="site web de Werner Almesberger"> (Il a écrit le code permettant le support des Services Différenciés sous Linux). <sect2> A quoi Dsmark est-il relié ? <p> Dsmark est un gestionnaire de mise en file d'attente qui offre les fonctionnalités dont ont besoin les services différenciés (Differentiated Services) (également appelé DiffServ, ou tout simplement DS). DiffServ est l'une des deux architectures actuelles de la Qualité de Service (QoS : Quality of Services) (l'autre est appelée "Integrated Services" (services intégrés)) et il se base sur la valeur du champ DS contenue dans l'entête IP du paquet. <p> Une des premières solutions dans IP pour offrir des niveaux de qualité de service était le champ Type de Service (octet TOS) dans l'entête IP. En modifiant la valeur de ce champ, nous pouvions choisir un niveau élevé/faible du débit, du délai ou de la fiabilité. Cependant, cela ne fournissait pas une flexibilité suffisante pour les besoins de nouveaux services (comme les applications temps réel, les applications interactives et autres). Après ceci, de nouvelles architectures sont apparues. L'une d'elle a été DiffServ qui a gardé les bits TOS et les a renommé champ DS. <sect2>Guide des services différenciés <p> Les services différenciés sont orientés groupes. Cela signifie que nous ne savons rien des flux (ce sera le but des "integrated Services" (services intégrés)). Nous connaisons par contre les aggrégations de flux et nous appliquerons des comportements différents suivant l'aggrégation à laquelle appartient le paquet. <p> Quand un paquet arrive à un noeud de bord (noeud d'entrée du domaine DiffServ) et entre dans un domaine DiffServ, nous devrons avoir une politique, une mise en forme et/ou un marquage de ces paquets (le marquage fait référence à la mise en place d'une valeur dans le champ DS. Cela ressemble aux vaches :-) ). Ce sera cette marque/valeur que les noeuds internes de votre domaine DiffServ regarderons pour déterminer quel comportement ou niveau de qualité de service appliquer. <p> Comme vous pouvez le déduire, les Services Différenciés impliquent un domaine sur lequel toutes les règles DS devront être appliquées. Vous pouvez raisonner de la façon suivante : "Je classifierai tous les paquets entrant dans mon domaine. Une fois qu'ils seront entrés dans mon domaine, ils seront soumis aux règles que ma classification impose et chaque noeud traversé appliquera son niveau de qualité de service". <p> En fait, vous pouvez appliquer vos propres politiques dans vos domaines locaux, mais des <em>autorisations au niveau service</em> devront être considérées lors de la connexion à d'autres domaines DS. <p> En ce moment, vous vous posez peut-être beaucoup de questions. DiffServ est plus vaste que ce que j'ai expliqué. En fait, vous pouvez comprendre que je ne peux pas résumer plus de trois RFC en 50 lignes :-). <sect2>Travailler avec Dsmark <p> Comme le spécifie la bibliographie concernant DiffServ, nous différençions les noeuds frontières et les noeuds intérieurs. Ce sont deux éléments importants dans le chemin qu'emprunte le trafic. Les deux réalisent une classification quand un paquet arrive. Le résultat peut être utilisé à différents endroits lors du processus DS avant que le paquet ne soit libéré vers le réseau. Cela est possible car le nouveau code diffserv fourni une structure appelée sk_buff, incluant un nouveau champ appelé skb->tcindex. Ce champ mémorisera le résultat de la classification initiale et pourra être utilisé à plusieurs reprises dans le traitement DS. <p> La valeur skb->tc_index sera initialement configurée par le gestionnaire de mise en file d'attente DSMARK. Cette valeur sera extraite du champ DS de l'entête IP de tous les paquets reçus. En outre, le classificateur cls_tcindex lira tout ou une partie de la valeur skb->tcindex et l'utilisera pour sélectionner les classes. <p> Mais, avant tout, regardons la commande qdisc DSMARK et ses paramètres : <tscreen><verb> ... dsmark indices INDICES [ default_index DEFAULT_INDEX ] [ set_tc_index ] </verb></tscreen> Que signifient ces paramètres ? <itemize> <item><bf>indices</bf>: taille de la table des couples (masque,valeur). La valeur maximum est 2^n, où n>=0. <item><bf>Default_index</bf>: l'index d'entrée par défaut de la table si aucune correspondance n'est trouvée. <item><bf>Set_tc_index</bf>: indique au gestionnaire dsmark de récupérer le champs DS et de l'enregistrer dans skb->tc_index. </itemize> Regardons DSMARK procéder. <sect2>Comment SCH_DSMARK travaille. <p> Ce gestionnaire de mise en file d'attente réalisera les étapes suivantes : <itemize> <item>Si vous avez déclaré l'option set_tc_index dans la commande qdisc, le champ DS est récupéré et mémorisé dans la variable skb->tc_index. <item>Le classificateur est invoqué. Celui-ci sera exécuté et retournera un identificateur de classe (class ID) qui sera enregistré dans la variable skb->tc_index. Si aucun filtre correspondant n'est trouvé, nous considérons l'option default_index comme étant l'identificateur de classe à enregistrer. Si, ni set_tc_index, ni default_index n'ont été déclarés, alors les résultats peuvent ne pas être prédits. <item>Après avoir été envoyé dans le gestionnaire de file d'attente interne, où le résultat du filtre peut être réutilisé, l'identificateur de classe retourné par le gestionnaire est stocké dans la variable skb->tc_index. Cette valeur sera utilisée plus tard pour indexer la table masque-valeur. Le résultat de l'opération suivante sera assigné au paquet : <tscreen><verb> Nouveau_champ_DS = ( Ancien_champ_DS & masque ) | valeur </verb></tscreen> <item>La nouvelle valeur résultera donc d'un ET logique entre les valeurs du champ_DS et du masque, suivi d'un OU logique avec le paramètre valeur. Regarder la figure suivante pour comprendre tout ce processus : </itemize> <tscreen> <verb> skb->ihp->tos - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > | | ^ | -- Si vous déclarez set_tc_index, nous configurons | | <-----Peut changer | la valeur DS dans la variable skb->tc_index | |O le champ DS | A| |R +-|-+ +------+ +---+-+ File d'attente-+ +---N|-----|----+ | | | |filtre|--->| | |--> . . . -->| | | D| | | | | |----->| tc |--->| | | interne | |---->| v | | | | | |index |--->| | | +---------------+ | ---->(masque,valeur)| -->| O | +------+ +-|-+--------------^----+ / | (. , .) | | | | ^ | | | | (. , .) | | | +----------|---------|----------------|-------|--+ (. , .) | | | sch_dsmark | | | | | +-|------------|---------|----------------|-------|------------------+ | | | <- tc_index -> | | | |(lecture)| peut changer | | <--------------Index de la table | | | | | des couples v | v v | (masque,valeur) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -> skb->tc_index </verb> </tscreen> <P> Comment faire le marquage ? Il suffit de modifier le masque et la valeur associé à la classe que vous voulez marquer. Regarder la ligne de code suivante : <tscreen> tc class change dev eth0 classid 1:1 dsmark mask 0x3 value 0xb8 </tscreen> Cela modifie le couple (masque,valeur) dans la table de hachage, et re-marque les paquets appartenant à la classe 1:1. Vous devez "changer" ces valeurs en raison des valeurs par défaut que le couple (masque, valeur) obtient initiallement (voir le tableau ci-dessous). <p> Nous allons maintenant expliquer comment le filtre TC_INDEX travaille, et comment il s'intègre dans tout cela. En outre, le filtre TC_INDEX peut être utiliser dans des configurations autres que celles incluant les services DS. <sect2>Le filtre TC_INDEX <p> Voici la commande de base pour déclarer un filtre TC_INDEX : <tscreen> <verb> ... tcindex [ hash SIZE ] [ mask MASK ] [ shift SHIFT ] [ pass_on | fall_through ] [ classid CLASSID ] [ police POLICE_SPEC ] </verb> </tscreen> Ensuite, nous montrons l'exemple utilisé pour expliquer le mode opératoire de TC_INDEX. Soyez attentif aux mots en gras : &nl;&nl; tc qdisc add dev eth0 handle 1:0 root dsmark indices 64 <bf>set_tc_index</bf>&nl; tc filter add dev eth0 parent 1:0 protocol ip prio 1 tcindex <bf>mask 0xfc shift 2</bf>&nl; tc qdisc add dev eth0 parent 1:0 handle 2:0 cbq bandwidth 10Mbit cell 8 avpkt 1000 mpu 64&nl; # Classe du trafic EF&nl; tc class add dev eth0 parent 2:0 classid 2:1 cbq bandwidth 10Mbit rate 1500Kbit avpkt 1000 prio 1 bounded isolated allot 1514 weight 1 maxburst 10&nl; # Gestionnaine de file d'attente fifo pour le trafic EF&nl; tc qdisc add dev eth0 parent 2:1 pfifo limit 5&nl; tc filter add dev eth0 parent 2:0 protocol ip prio 1 <bf>handle 0x2e</bf> tcindex <bf>classid 2:1 pass_on</bf>&nl; &nl;&nl; (Ce code n'est pas complet. Ce n'est qu'un extrait de l'exemple EFCBQ inclus dans la distribution iproute2). <p> Avant tout, supposons que nous recevons un paquet marqué comme EF. Si vous lisez le RFC2598, vous verrez que DSCP recommande une valeur de 101110 pour le trafic EF. Cela signifie que le champ DS sera égal à 10111000 (rappelez vous que les bits les moins significatifs de l'octet TOS ne sont pas utilisés dans DS) ou 0xb8 en notation hexadécimale. <p> <tscreen> <verb> FILTRE TC INDEX +---+ +-------+ +---+-+ +------+ +-+ +-------+ | | | | | | | |FILTRE| +-+ +-+ | | | | | |----->| MASK | -> | | | -> |HANDLE|->| | | | -> | | -> | | | | . | =0xfc | | | | |0x2E | | +----+ | | | | | | | . | | | | | +------+ +--------+ | | | | | | . | | | | | | | | | -->| | . | SHIFT | | | | | | | |--> | | . | =2 | | | +----------------------------+ | | | | | | | | | CBQ 2:0 | | | | | +-------+ +---+--------------------------------+ | | | | | | | +-------------------------------------------------------------+ | | DSMARK 1:0 | +-------------------------------------------------------------------------+ </verb> </tscreen> <p> Le paquet arrive alors avec la valeur du champ DS configurée à 0xb8. Comme je l'ai expliqué avant, le gestionnaire de mise en file d'attente dsmark, identifié par 1:0 dans cet exemple, récupère le champ DS et l'enregistre dans la variable skb->tc_index. L'étape suivante consistera à associer un filtre à ce gestionnaire de mise en file d'attente (la seconde ligne dans cet exemple). Les opérations suivantes seront réalisées : <tscreen> <verb> Valeur1 = skb->tc_index & MASK Clé = Valeur1 >> SHIFT </verb> </tscreen> <p> Dans cet exemple, MASK=0xFC et SHIFT=2. <tscreen> <verb> Valeur1 = 10111000 & 11111100 = 10111000 Clé = 10111000 >> 2 = 00101110 -> 0x2E en hexadécimal </verb> </tscreen> <p> La valeur retournée correspondra à un identificateur de filtre du gestionnaire de file d'attente interne (dans l'exemple, identifier par 2:0). Si un filtre avec cet identificateur (id) existe, les conditions de contrôle et de performance seront vérifiées (au cas où le filtre inclut ceci) et l'identificateur de classe sera retourné (dans notre exemple, classid 2:1) et stocké dans la variable skb->tc_index. <P> Si aucun filtre avec cet identificateur n'est trouvé, le résultat dépendra de la déclaration de l'option fall_through. Si tel est le cas, la valeur Clé est retouné comme identificateur de classe. Si cela n'est pas le cas, une erreur est retournée et le traitement continue avec les filtres restant. Faites attention si vous utilisez l'option fall_through ; ceci ne peut être fait que si une relation existe entre les valeurs de la variable skb->tc_index et les identificateurs de classe. <P> Les derniers paramètres à commenter sont hash et pass_on. Le premier est relié à la taille de la table de hachage. Pass_on sera utilisé pour indiquer d'essayer le filtre suivant dans le cas où aucun identificateur de classe égal au résultat du filtre n'est trouvée. L'action par défaut est fall_through (regarder la table suivante). <P> Finalement, regardons quelles sont les valeurs possibles pour la configuration de tous ces paramètres TCINDEX : <tscreen> <verb> Nom TC Valeur Défaut ----------------------------------------------------------------- Hash 1...0x10000 Dépendant de l'implémentation Mask 0...0xffff 0xffff Shift 0...15 0 Fall through / Pass_on Flag Fall_through Classid Major:minor Rien Police ..... Rien </verb> </tscreen> <P> Ce type de filtre est très puissant. Il est nécessaire d'explorer toutes les possibilités. En outre, ce filtre n'est pas seulement utilisé dans les configurations DiffServ. Vous pouvez l'utiliser comme n'importe quel autre filtre. <p> Je vous recommande de regarder les exemples DiffServ inclus dans la distribution iproute2. Je vous promet que j'essaierai de compléter ce texte dès que possible. Tout ce que j'ai expliqué est le résultat de nombreux tests. Merci de me dire si je me suis trompé quelque part. <sect>Autres informations <p> Esteve Camps Chust <marvin@grn.es>&nl; Ce texte est un extrait de ma thèse sur le "support QoS dans Linux", septembre 2000.&nl; <P> Documents sources :&nl; <itemize> <item><url url="http://ica1www.epfl.ch/~almesber" name="Draft-almesberger-wajhak-diffserv-linux-01.txt">. <item>Exemples de la distribution iproute2. <item><url url="http://www.qosforum.com/white-papers/qosprot_v3.pdf" name="White Paper-QoS protocols and architectures"> et <url url="http://www.qosforum.com/docs/faq" name="Foires Aux Questions IP QoS">, les deux par <em>Quality of Service Forum</em>. </itemize> <sect1>WRR <p> Cette file d'attente n'est pas incluse dans les noyaux standard, mais peut être téléchargée à partir de <url url="http://wipl-wrr.dkik.dk/wrr/">. Cette file d'attente n'a été testée qu'avec les noyaux 2.2, mais marchera probablement également avec les noyaux 2.4. La file d'attente WRR partage la bande passante entre ses classes en utilisant la technique du tourniquet pondéré. Ceci est similaire à la file d'attente CBQ qui contient des classes sur lesquelles l'on peut associer arbitrairement des files d'attente. Toutes les classes qui ont suffisamment de demandes obtiendront la bande passante proportionnellement au poid associé des classes. Les poids peuvent être configurés manuellement en utilisant le programme <tt>tc</tt>. Ils peuvent également être configurés pour décroître automatiquement pour les classes transférant moins de données. La file d'attente a un classificateur intégré qui assigne les paquets venant ou allant vers différentes machines à différentes classes. On peut utiliser soit l'adresse MAC soit l'adresse IP de l'addresse source ou de destination. L'adresse MAC ne peut cependant n'être utilisée que quand la boite Linux est un pont ethernet. Les classes sont automatiquement assignées aux machines en fonction des paquets vus. Ce gestionnaire de mise en file d'attente peut être très utile au site comme les résidences étudiantes où des individus sans liens particuliers partagent une connection Internet. Un ensemble de scripts pour configurer un tel cas de figure pour ce genre de site est proposé dans la distribution WRR. <sect>Netfilter et iproute - marquage de paquets <p> Jusqu'à maintenant, nous avons vu comment iproute travaille, et netfilter a été mentionné plusieurs fois. Vous ne perdrez pas votre temps à consulter <url name="Rusty's Remarkably Unreliable Guides" url="http://netfilter.samba.org/unreliable-guides/">. Le logiciel Netfilter peut être trouvé <url name="ici" url="http://netfilter.filewatcher.org/">. Netfilter nous permet de filtrer les paquets, ou de désosser leurs en-têtes. Une de ses fonctionnalités particulières est de pouvoir marquer un paquet avec un nombre, grâce à l'option --set-mark. Comme exemple, la commande suivante marque tous les paquets destinés au port 25, en l'occurence le courrier sortant. <tscreen><verb> # iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 25 \ -j MARK --set-mark 1 </verb></tscreen> Disons que nous avons plusieurs connexions, une qui est rapide (et chère, au mégaoctet) et une qui est plus lente, mais avec un tarif moins élevé. Nous souhaiterions que le courrier passe par la route la moins chère. Nous avons déjà marqué le paquet avec un "1" et nous allons maintenant renseigner la base de données de la politique de routage pour qu'elle agisse sur ces paquets marqués. <tscreen><verb> # echo 201 mail.out >> /etc/iproute2/rt_tables # ip rule add fwmark 1 table mail.out # ip rule ls 0: from all lookup local 32764: from all fwmark 1 lookup mail.out 32766: from all lookup main 32767: from all lookup default </verb></tscreen> Nous allons maintenant générer la table mail.out avec une route vers la ligne lente, mais peu coûteuse. <tscreen><verb> # /sbin/ip route add default via 195.96.98.253 dev ppp0 table mail.out </verb></tscreen> Voilà qui est fait. Il se peut que nous voulions mettre en place des exceptions, et il y a beaucoup de moyens de le faire. Nous pouvons modifier la configuration de netfilter pour exclure certains hôtes, ou nous pouvons insérer une règle avec une priorité plus faible qui pointe sur la table principale pour nos hôtes faisant exception. Nous pouvons aussi utiliser cette fonctionnalité pour nous conformer aux bits TOS en marquant les paquets avec différents types de service et les nombres correspondants. On crée ensuite les règles qui agissent sur ces types de service. De cette façon, on peut dédier une ligne RNIS aux connexions interactives. Inutile de la dire, cela marche parfaitement sur un hôte qui fait de la translation d'adresse (NAT), autrement dit du "masquerading". IMORTANT : Nous avons reçu une information selon laquelle MASQ et SNAT entrent en conflit avec le marquage de paquets. Rusty Russell l'explique dans <url url="http://lists.samba.org/pipermail/netfilter/2000-November/006089.html" name="ce courrier">. Désactiver le filtrage de chemin inverse pour que cela fonctionne correctement. Note : pour marquer les paquets, vous aurez besoin de valider quelques options du noyau : <tscreen><verb> IP: advanced router (CONFIG_IP_ADVANCED_ROUTER) [Y/n/?] IP: policy routing (CONFIG_IP_MULTIPLE_TABLES) [Y/n/?] IP: use netfilter MARK value as routing key (CONFIG_IP_ROUTE_FWMARK) [Y/n/?] </verb></tscreen> Voir aussi <ref id="SQUID" name="Cache web transparent utilisant netfilter, iproutes2, ipchains et squid"> dans le chapitre "Livre de recettes". <sect>D'autres classificateurs <p> Les classificateurs sont les moyens par lesquels le noyau décide dans quelle file d'attente un paquet sera placé. Il y a divers classificateurs, chacun d'eux pouvant être utilisé pour différents buts. <descrip> <tag>fw</tag> Base la décision sur la façon dont la pare-feu a marqué les paquets. <tag>u32</tag> Base la décision sur les champs à l'intérieur du paquet (c'est-à-dire l'adresse IP source, etc.) <tag>route</tag> Base la décision sur la route à emprunter par le paquet. <tag>rsvp, rsvp6</tag> Base la décision sur la cible (destination, protocole) et, optionnellement, sur la source (je pense). <tag>tcindex</tag> FIXME: Remplissez-moi </descrip> Notez qu'il y a généralement plusieurs manières de classifier un paquet. Cela dépend du système de classification que vous souhaitez utiliser. Les classificateurs acceptent en général quelques arguments communs. Ils sont listés ici pour des raisons pratiques : <descrip> <tag>protocol</tag> Le protocole que ce classificateur acceptera. Généralement, on n'acceptera que le trafic IP. Exigé. <tag>parent</tag> La référence à laquelle ce classificateur est attaché. Cette référence doit être une classe déjà existante. Exigé. <tag>prio</tag> La priorité de ce classificateur. Les plus grand nombres seront testés en premier. <tag>handle</tag> Cette référence a plusieurs significations suivant les différents filtres. FIXME: En ajouter d'autres </descrip> Toutes les sections suivantes supposeront que vous essayez de mettre en forme le trafic allant vers <tt>HostA</tt>. Ces sections suppposeront que la classe racine a été configurée sur 1: et que la classe vers laquelle vous voulez envoyer le trafic sélectionné est 1:1. <sect1>Le classificateur "fw" <p>Le classificateur "fw" s'appuie sur le marquage des paquets à mettre en forme par le pare-feu. Donc, nous configurerons d'abord le pare-feu pour les marquer : <tscreen><verb> # iptables -I PREROUTING -t mangle -p tcp -d HostA \ -j MARK --set-mark 1 </verb></tscreen> Maintenant, tous les paquets vers cette machine (HostA) sont balisés avec la marque 1. À présent, nous construisons les règles de mise en forme pour mettre en forme les paquets. Nous avons juste besoin d'indiquer que les paquets balisés avec la marque 1 vont vers la classe 1:1. C'est fait par la commande suivante : <tscreen><verb> # tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 1 fw classid 1:1 </verb></tscreen> Cela devrait se comprendre de soi-même. On attache à la classe 1:0 un filtre avec la priorité 1 pour filtrer tous les paquets marqués à 1 par le pare-feu vers la classe 1:1. Noter l'utilisation du paramètre "handle" pour indiquer la marque attendue. C'est tout ce qu'il y a à faire ! C'est le procédé le plus simple (à mon humble avis). Je pense que les autres procédés sont plus difficiles à comprendre. Notez que toute la puissance du pare-feu peut être utilisée avec ce classificateur. Cela inclut l'analyse des adresses MAC, des identificateurs d'utilisateurs (user ID) et tout ce que le firewall peut traiter. <sect1>Le classificateur "u32" <p> Le filtre u32 est le filtre le plus avancé dans l'implémentation courante. Il est entièrement basé sur des tables de hachage, ce qui le rend robuste quand il y a beaucoup de règles de filtrage. Dans sa forme la plus simple, le filtre u32 est une liste d'enregistrements, chacun consistant en deux champs : un sélecteur et une action. Les sélecteurs, décrits ci-dessous, sont comparés avec le paquet IP traité jusqu'à la première correspondance, et l'action associée est accomplie. Le type d'action le plus simple serait de diriger le paquet vers une classe CBQ définie. La ligne de commande du programme filtre <tt>tc</tt>, utilisé pour configurer le filtre, consiste en trois parties : la spécification du filtre, un sélecteur et une action. La spécification du filtre peut être définie comme : <tscreen><verb> tc filter add dev IF [ protocol PROTO ] [ (preference|priority) PRIO ] [ parent CBQ ] </verb></tscreen> Le champ <tt>protocol</tt> décrit le protocole sur lequel le filtre sera appliqué. Nous ne discuterons que du cas du protocole <tt>ip</tt>. Le champ <tt>preference</tt>(<tt>priority</tt> peut être utilisé comme alternative) fixe la priorité du filtre que l'on définit. C'est important dans la mesure où vous pouvez avoir plusieurs filtres (listes de règles) avec des priorités différentes. Chaque liste sera scrutée dans l'ordre d'ajout des règles. Alors, la liste avec la priorité la plus faible (celle qui a le numéro de préférence le plus élevé) sera traitée. Le champ <tt>parent</tt> définit le sommet de l'arbre CBQ (par ex. 1:0) auquel le filtre doit être attaché. Les options décrites s'appliquent à tous les filtres, pas seulement à u32. <sect2>Le sélecteur U32 <p> Le sélecteur U32 contient la définition d'un modèle, qui sera comparé au paquet traité. Plus précisément, il définit quels bits doivent correspondre dans l'en-tête du paquet, et rien de plus, mais cette méthode simple est très puissante. Jetons un oeil sur l'exemple suivant, directement tiré d'un filtre assez complexe réellement existant : <tscreen><verb> # filter parent 1: protocol ip pref 10 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:3 \ match 00100000/00ff0000 at 0 </verb></tscreen> <p> Pour l'instant, laissons de côté la première ligne - tous ces paramètres décrivent les tables de hachage du filtre. Focalisons-nous sur la ligne de sélection contenant le mot-clé <tt>match</tt>. Ce sélecteur fera correspondre les en-têtes IP dont le second octet sera 0x10 (0010). Comme nous pouvons le deviner, le nombre 00ff est le masque de correspondance, disant au filtre quels bits il doit regarder. Ici, c'est 0xff, donc l'octet correspondra si c'est exactement 0x10. Le mot-clé <tt>at</tt> signifie que la correspondance doit démarrer au décalage spécifié (en octets) - dans notre cas, c'est au début du paquet. Traduisons tout cela en langage humain : le paquet correspondra si son champ Type de Service (TOS) a le bit "faible délai" positionné. Analysons une autre règle : <tscreen><verb> # filter parent 1: protocol ip pref 10 u32 fh 800::803 order 2051 key ht 800 bkt 0 flowid 1:3 \ match 00000016/0000ffff at nexthdr+0 </verb></tscreen> <p> L'option <tt>nexthdr</tt> désigne l'en-tête suivant encapsulé dans le paquet IP, c'est à dire celui du protocole de la couche supérieure. La correspondance commencera également au début du prochain en-tête. Elle devrait avoir lieu dans le deuxième mot de 32 bits de l'en-tête. Dans les protocoles TCP et UDP, ce champ contient le port de destination du paquet. Le nombre est donné dans le format big-endian, c'est-à-dire les bits les plus significatifs en premier. Il faut donc lire 0x0016 comme 22 en décimal, qui correspond au service SSH dans le cas de TCP. Comme vous le devinez, cette correspondance est ambiguë sans un contexte, et nous en discuterons plus loin. <p> Ayant compris tout cela, nous trouverons le sélecteur suivant très facile à lire : <tt>match c0a80100/ffffff00 at 16</tt>. Ce que nous avons ici, c'est une correspondance de trois octets au 17ème octet, en comptant à partir du début de l'en-tête IP. Cela correspond aux paquets qui ont une adresse de destination quelconque dans le réseau 192.168.1/24. Après avoir analysé les exemples, nous pouvons résumer ce que nous avons appris. <sect2>Sélecteurs généraux <p> Les sélecteurs généraux définissent le modèle, le masque et le décalage qui seront comparés au contenu du paquet. En utilisant les sélecteurs généraux, vous pouvez rechercher des correspondances sur n'importe quel bit de l'en-tête IP (ou des couches supérieures). Ils sont quand même plus difficiles à écrire et à lire que les sélecteurs spécifiques décrits ci-dessus. La syntaxe générale des sélecteurs est : <tscreen><verb> match [ u32 | u16 | u8 ] PATTERN MASK [ at OFFSET | nexthdr+OFFSET] </verb></tscreen> <p> Un des mots-clés <tt>u32</tt>,<tt>u16</tt> ou <tt>u8</tt> doit spécifier la longueur du modèle en bits. PATTERN et MASK se rapporteront à la longueur définie par ce mot-clé. Le paramètre OFFSET est le décalage, en octets, pour le démarrage de la recherche de correspondance. Si le mot-clef <tt>nexthdr+</tt> est présent, le décalage sera relatif à l'en-tête de la couche réseau supérieure. <p> Quelques exemples : <tscreen><verb> # tc filter add dev ppp14 parent 1:0 prio 10 u32 \ match u8 64 0xff at 8 \ flowid 1:4 </verb></tscreen> <p> Un paquet correspondra à cette règle si sa "durée de vie" (TTL) est de 64. TTL est le champ démarrant juste après le 8ème octet de l'en-tête IP. <tscreen><verb> # tc filter add dev ppp14 parent 1:0 prio 10 u32 \ match u8 0x10 0xff at nexthdr+13 \ protocol tcp \ flowid 1:3 \ </verb></tscreen> <p> Cette règle correspondra seulement aux paquets TCP avec le bit ACK positionné. Ici, nous pouvons voir un exemple d'utilisation de deux sélecteurs, le résultat final étant un ET logique de leurs résultats. Si vous jetez un oeil sur un schéma de l'en-tête TCP, vous pouvez voir que le bit ACK est le second bit (0x10) du 14ème octet de l'en-tête TCP (<tt>at nexthdr+13</tt>). Comme second sélecteur, si vous voulez vous compliquer la vie, vous pouvez écrire <tt>match u8 0x06 0xff at 9</tt> à la place du sélecteur spécifique <tt>protocol tcp</tt>, puisque 6 est le numéro du protocole TCP, spécifié au 10ème octet de l'en-tête IP. En revanche, dans cet exemple, vous ne pourrez pas utiliser de sélecteur spécifique pour la première correspondance, simplement parce qu'il n'y a pas de sélecteur spécifique pour désigner les bits TCP ACK. <sect2>Les sélecteurs spécifiques <p> La table suivante contient la liste de tous les sélecteurs spécifiques que les auteurs de cette section ont trouvés dans le code source du programme <tt>tc</tt>. Ils rendent simplement la vie plus facile en accroissant la lisibilité de la configuration du filtre. FIXME: emplacement de la table - la table est dans un fichier séparé "selector.html" FIXME: C'est encore en Polonais :-( FIXME: doit être "sgmlisé" Quelques exemples : <tscreen><verb> # tc filter add dev ppp0 parent 1:0 prio 10 u32 \ match ip tos 0x10 0xff \ flowid 1:4 </verb></tscreen> La règle ci-dessus correspondra à des paquets qui ont le champ TOS égal à 0x10. Le champ TOS commence au deuxième octet du paquet et occupe 1 octet, ce qui nous permet d'écrire un sélecteur général équivalent : <tt>match u8 0x10 0xff at 1</tt>. Cela nous donne une indication sur l'implémentation du filtre u32 ; les règles spécifiques sont toujours traduites en règles générales, et c'est sous cette forme qu'elles sont stockées en mémoire par le noyau. Cela amène à une autre conclusion : les sélecteurs <tt>tcp</tt> et <tt>udp</tt> sont exactement les mêmes et c'est la raison pour laquelle vous ne pouvez pas utiliser un simple sélecteur <tt>match tcp dst 53 0xffff</tt> pour désigner un paquet TCP envoyé sur un port donné : cela désigne aussi les paquets UDP envoyés sur ce port. Vous devez également spécifier le protocole avec la règle suivante : <tscreen><verb> # tc filter add dev ppp0 parent 1:0 prio 10 u32 \ match tcp dst 53 0xffff \ match ip protocol 0x6 0xff \ flowid 1:2 </verb></tscreen> <!-- À FAIRE: Décrire plus d'options match offset hashkey classid | flowid divisor order link ht sample police --> <sect1>Le classificateur "route" <p> Ce classificateur filtre en se basant sur le résultat des tables de routage. Quand un paquet passant à travers les classes en atteint une qui est marquée avec le filtre "route", il divise le paquet en se basant sur l'information de la table de routage. <tscreen><verb> # tc filter add dev eth1 parent 1:0 protocol ip prio 100 route </verb></tscreen> Ici, nous ajoutons un classificateur <tt>route</tt> sur le noeud parent 1:0 avec la priorité 100. Quand un paquet atteint ce noeud (ce qui, puisqu'il est racine, arrive immédiatement), il consulte la table de routage et si une entrée de la table correspond, il envoie le paquet vers la classe donnée et lui donne une priorité de 100. Ensuite, pour finalement activer les choses, vous ajoutez l'entrée de routage appropriée. L'astuce ici est de définir "realm" en se basant soit sur la destination, soit sur la source. Voici la façon de faire cela : <tscreen><verb> # ip route add Host/Network via Gateway dev Device realm RealmNumber </verb></tscreen> Par exemple, nous pouvons définir notre réseau de destination 192.168.10.0 avec le nombre "realm" égal à 10 : <tscreen><verb> # ip route add 192.168.10.0/24 via 192.168.10.1 dev eth1 realm 10 </verb></tscreen> Quand on ajoute des filtres "route", on peut utiliser les nombres "realm" pour représenter les réseaux ou les hôtes et spécifier quelle est la correspondance entre les routes et les filtres. <tscreen><verb> # tc filter add dev eth1 parent 1:0 protocol ip prio 100 \ route to 10 classid 1:10 </verb></tscreen> La règle ci-dessus indique que les paquets allant vers le réseau 192.168.10.0 correspondent à la classe 1:10. Le filtre route peut aussi être utilisé avec les routes sources. Par exemple, il y a un sous-réseau attaché à notre routeur Linux sur eth2. <tscreen><verb> # ip route add 192.168.2.0/24 dev eth2 realm 2 # tc filter add dev eth1 parent 1:0 protocol ip prio 100 \ route from 2 classid 1:2 </verb></tscreen> Ici, le filtre spécifie que les paquets venant du réseau 192.168.2.0 (realm 2) correspondront à la classe 1:2. <sect1>Le classificateur "rsvp" <p>FIXME: à remplir <sect1>Le classificateur "tcindex" <p>FIXME: à remplir <sect>Paramètres réseau du noyau <p> Le noyau utilise de nombreux paramètres qui peuvent être ajustés en différentes circonstances. Bien que, comme d'habitude, les paramètres par défaut conviennent à 99% des installations, nous ne pourrions pas appeler ce document "HOWTO avancé" sans en dire un mot. Les éléments intéressants sont dans /proc/sys/net, jetez-y un oeil. Tout ne sera pas documenté ici au départ, mais nous y travaillons. <sect1>Filtrage du Chemin Inverse (Reverse Path Filtering) <p> Par défaut, les routeurs routent tout, même les paquets qui visiblement n'appartiennent pas à votre réseau. Un exemple courant est l'espace des adresses IP privées s'échappant sur Internet. Si vous avez une interface avec une route pour 195.96.96.0/24 dessus, vous ne vous attendrez pas à voir arriver des paquets venant de 212.64.94.1. arriver des paquets venant de 212.64.94.1. Beaucoup d'utilisateurs veulent désactiver cette fonctionnalité. Les développeurs du noyau ont permis de le faire facilement. Il y a des fichiers dans <file>/proc</file> où vous pouvez ordonner au noyau de le faire pour vous. La méthode est appelée "Reverse Path Filtering" (Filtrage par chemin inverse). Pour faire simple, si la réponse à ce paquet ne sort pas par l'interface par laquelle il est entré, alors c'est un paquet "bogué" et il sera ignoré. Les instructions suivantes vont activer cela pour toutes les interfaces courantes et futures. <tscreen><verb> # for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do > echo 2 > $i > done </verb></tscreen> En reprenant l'exemple du début, si un paquet arrivant sur le routeur Linux par eth1 prétend venir du réseau Bureau+FAI, il sera éliminé. De même, si un paquet arrivant du réseau Bureau prétend être de quelque part à l'extérieur du pare-feu, il sera également éliminé. Ce qui est présenté ci-dessus est le filtrage de chemin inverse complet. Le paramétrage par défaut filtre seulement sur les adresses IP des réseaux directement connectés. Ce paramétrage par défaut est utilisé parce que le filtrage complet échoue dans le cas d'un routage asymétrique (où il y a des paquets arrivant par un chemin et ressortant par un autre, comme dans le cas du trafic satellite, ou si vous avez des routes dynamiques (bgp, ospf, rip) dans votre réseau. Les données descendent vers la parabole satellite et les réponses repartent par des lignes terrestres normales). Si cette exception s'applique dans votre cas (vous devriez être au courant), vous pouvez simplement désactiver le <file>rp_filter</file> sur l'interface d'arrivée des données satellite. Si vous voulez voir si des paquets sont éliminés, le fichier <file>log_martians</file> du même répertoire indiquera au noyau de les enregistrer dans votre syslog. <tscreen><verb> # echo 1 >/proc/sys/net/ipv4/conf/<interfacename>/log_martians </verb></tscreen> FIXME: Est-ce que la configuration des fichiers dans .../conf/{default,all} suffit ? - martijn <sect1>Configurations obscures <p> Bon, il y a beaucoups de paramètres qui peuvent être modifiés. Nous essayons de tous les lister. Voir aussi une documentation partielle dans <file>Documentation/ip-sysctl.txt</file>. Certaines de ces configurations ont des valeurs par défaut différentes suivant que vous répondez "Yes" ou "No" à la question "Configure as router and not host" lors de la compilation du noyau. <sect2>ipv4 générique <p> En remarque générale, les fonctionnalités de limitation de débit ne fonctionnent pas sur l'interface loopback. N'essayez donc pas de les tester localement. Les limites sont exprimées en "jiffies" ("tic-tac") et sont contraintes d'utiliser le "token bucket filter" mentionné plus tôt. [NdT : le terme "jiffies" désigne un mouvement régulier, faisant référence au "tic-tac" d'un horloge.] Le noyau a une horloge interne qui tourne à "HZ" impulsions (ou "jiffies") par seconde. Sur intel, "HZ" est la plupart du temps de 100. Donc, configurer un fichier *_rate à, disons 50, autorise 2 paquets par seconde. Le "token bucket filter" est également configuré pour autoriser une rafale de données de au plus 6 paquets, si suffisamment de jetons ont été gagnés. Plusieurs éléments de la liste suivante proviennent du fichier /usr/src/linux/Documentation/networking/ip-sysctl.txt, écrit par Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> et Andi Kleen <ak@muc.de> <descrip> <tag>/proc/sys/net/ipv4/icmp_destunreach_rate</tag> Si le noyau décide qu'il ne peut pas délivrer un paquet, il le rejettera et enverra à la source du paquet un ICMP notifiant ce rejet. <tag>/proc/sys/net/ipv4/icmp_echo_ignore_all</tag> N'agit en aucun cas comme écho pour les paquets. Ne configurez pas ceci par défaut. Cependant, si vous êtes utilisé comme relai dans une attaque de Deni de Services, cela peut être utile. <tag>/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts [Utile]</tag> Si vous pinguez l'adresse de diffusion d'un réseau, tous les hôtes sont censés répondre. Cela permet de coquettes attaques de déni de service. Mettez cette valeur à 1 pour ignorer ces messages de diffusion. <tag>/proc/sys/net/ipv4/icmp_echoreply_rate</tag> Le débit auquel les réponses echo sont envoyées aux destinataires. <tag>/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses</tag> Configurer ceci pour ignorer les erreurs ICMP d'hôtes du réseau réagissant mal aux trames envoyées vers ce qu'ils perçoivent comme l'adresse de diffusion. <tag>/proc/sys/net/ipv4/icmp_paramprob_rate</tag> Un message ICMP relativement peu connu, qui est envoyé en réponse à des paquets qui ont des entêtes IP ou TCP erronées. Avec ce fichier, vous pouvez contrôler le débit auquel il est envoyé. <tag>/proc/sys/net/ipv4/icmp_timeexceed_rate</tag> Voici la célèbre cause des "étoiles Solaris" dans traceroute. Limite le nombre de messages ICMP Time Exceeded envoyés. <tag>/proc/sys/net/ipv4/igmp_max_memberships</tag> Nombre maximal de sockets igmp (multidiffusion) en écoute sur l'hôte. FIXME: Est-ce vrai ? <tag>/proc/sys/net/ipv4/inet_peer_gc_maxtime</tag> FIXME : Ajouter une petite explication sur le stockage des partenaires internet (inet peer) ?&nl; Intervalle de temps minimum entre deux passages du ramasse-miettes. Cet intervalle est pris en compte lors d'une faible (voire inexistante) utilisation du pool. Mesuré en "jiffies". [NdT : Le pool désigne ici la liste des adresses IP des partenaires internet.] <tag>/proc/sys/net/ipv4/inet_peer_gc_mintime</tag> Intervalle de temps minimum entre deux passages du ramasse-miettes. Cet intervalle est pris en compte lors d'une utilisation intensive du pool. Mesuré en "jiffies". <tag>/proc/sys/net/ipv4/inet_peer_maxttl</tag> Durée de conservation maximale des enregistrements. Les entrées non utilisées expireront au bout de cet intervalle de temps (cad quand le nombre d'entrée dans le pool est très petit). Mesuré en "jiffies". <tag>/proc/sys/net/ipv4/inet_peer_minttl</tag> Durée de conservation minimale des enregistrements. Devrait être suffisante pour prendre en compte le temps de vie des fragments sur l'hote qui doit réassembler les paquets. Cette durée minimale est garantie si le nombre d'éléments dans le pool est inférieur au seuil fixé par inet_peer_threshold <tag>/proc/sys/net/ipv4/inet_peer_threshold</tag> Taille approximative de l'espace de stockage des partenaires internet. A partir de ce seuil, les entrées sont effacées. Ce seuil détermine la durée de vie des entrées, ainsi que les intervalles de temps entre deux déclenchements du ramasse-miettes. Plus d'entrées, temps de vie plus faible, intervalle du ramasse-miettes plus faible. <tag>/proc/sys/net/ipv4/ip_autoconfig</tag> Ce fichier contient la valeur 1 si l'hôte a reçu sa configuration IP par RARP, BOOTP, DHCP ou un mécanisme similaire. Autrement, contient la valeur zéro. <tag>/proc/sys/net/ipv4/ip_default_ttl</tag> Durée de vie (TTL) des paquets. Fixer à la valeur sûre de 64. Augmentez-là si vous avez un réseau immense, mais pas "pour s'amuser" : les boucles sans fin d'un mauvais routage sont plus dangereuses si le TTL est élevé. Vous pouvez même envisager de diminuer la valeur dans certaines circonstances. <tag>/proc/sys/net/ipv4/ip_dynaddr</tag> Vous aurez besoin de positionner cela si vous utilisez la connexion à la demande avec une adresse d'interface dynamique. Une fois que votre interface a été configurée, toutes les sockets TCP locales qui n'ont pas eu de paquets de réponse seront retraitées pour avoir la bonne adresse. Cela résout le problème posé par une connexion défectueuse ayant configurée une interface, suivie par une deuxième tentative réussie (avec une adresse IP différente). <tag>/proc/sys/net/ipv4/ip_forward</tag> Le noyau doit-il essayer de transmettre les paquets ? Désactivé par défaut. <tag>/proc/sys/net/ipv4/ip_local_port_range</tag> Intervalle des ports locaux pour les connections sortantes. En fait, assez petit par défaut, 1024 à 4999. <tag>/proc/sys/net/ipv4/ip_no_pmtu_disc</tag> Configurez ceci si vous voulez désactiver la découverte du MTU de chemin, une technique pour déterminer le plus grand MTU possible sur votre chemin. Voir aussi la section sur la découverte du MTU de chemin dans le chapitre recette de cuisine. <tag>/proc/sys/net/ipv4/ipfrag_high_thresh</tag> Mémoire maximum utilisée pour réassembler les fragments IP. Quand ipfrag_high_thresh octets de mémoire sont alloués pour cela, le gestionnaire de fragments rejettera les paquets jusqu'à ce que ipfrag_low_thresh soit atteint. <tag>/proc/sys/net/ipv4/ip_nonlocal_bind</tag> Configurez ceci si vous voulez que vos applications soient capables de se lier à une adresse qui n'appartient pas à une interface de votre système. Ceci peut être utile quand votre machine est sur un lien non-permanent (ou même permanent). Vos services sont donc capables de démarrer et de se lier à une adresse spécifique quand votre lien est inactif. <tag>/proc/sys/net/ipv4/ipfrag_low_thresh</tag> Mémoire minimale utilisée pour réassembler les fragments IP. <tag>/proc/sys/net/ipv4/ipfrag_time</tag> Temps en secondes du maintien d'un fragment IP en mémoire. <tag>/proc/sys/net/ipv4/tcp_abort_on_overflow</tag> Une option booléenne controlant le comportement dans le cas de nombreuses connections entrantes. Quand celle-ci est activée, le noyau envoie rapidement des paquets RST quand un service est surchargé. <tag>/proc/sys/net/ipv4/tcp_fin_timeout</tag> <!--Ancien texte. A laisser en commentaire pour une meilleure compréhension Nombre de secondes d'attente du paquet FIN de l'ordinateur distant. Pendant ce temps, la session est à l'état FIN_WAIT2. Après ce délai, la session disparaît, même si le paquet FIN n'est pas arrivé. --> Temps de maintien de l'état FIN-WAIT-2 pour une socket dans le cas où elle a été fermée de notre coté. Le partenaire peut être défectueux et ne jamais avoir fermé son coté, ou même mourir de manière inattendue. La valeur par défaut est de 60 secondes. La valeur usuelle utilisée dans le noyau 2.2 était de 180 secondes. Vous pouvez la remettre, mais rappelez vous que si votre machine a un serveur WEB surchargé, vous risquez de dépasser la mémoire avec des kilotonnes de sockets mortes. Les sockets FIN-WAIT2 sont moins dangereuses que les sockets FIN-WAIT1 par qu'elles consomment au maximum 1,5K de mémoire mais, elles ont tendance à vivre plus longtemps. Cf tcp_max_orphans. <tag>/proc/sys/net/ipv4/tcp_keepalive_time</tag> Durée entre l'envoi de deux messages "keepalive" quand l'option "keepalive" est activée. &nl; Par défaut : 2 heures. <tag>/proc/sys/net/ipv4/tcp_keepalive_intvl</tag> A quelle fréquence les sondes sont retransmises quand une sonde n'a pas été acquitée. &nl; Par défaut : 75 secondes <tag>/proc/sys/net/ipv4/tcp_keepalive_probes</tag> Combien de sondes TCP "keepalive" seront envoyées avant de décider que la connection est brisée. &nl; Par défaut : 9. &nl; En multipliant par tcp_keepalive_intvl, cela donne le temps qu'un lien peut être actif sans donner de réponses après l'envoi d'un "keepalive". <tag>/proc/sys/net/ipv4/tcp_max_orphans</tag> Nombre maximum de sockets TCP qui ne sont pas reliées à un descripteur de fichier utilisateur, géré par le système. Si ce nombre est dépassé, les connections orphelines sont immédiatement réinitialisées et un avertissement est envoyé. Cette limite n'existe seulement que pour prévenir des attaques de déni de services simples. Vous ne devez pas compter sur ceci ou diminuer cette limite artificiellement, mais plutôt l'augmenter (probablement après avoir augmenté la mémoire) si les conditions du réseau réclament plus que cette valeur par défaut et régler vos services réseau pour qu'ils détruisent sans tarder de tel état. Laissez-moi vous rappeller encore que chaque orphelin consomme jusqu'à environ 64K de mémoire non swappable. <tag>/proc/sys/net/ipv4/tcp_orphan_retries</tag> Combien d'essais avant de détruire une connection TCP, fermée par notre coté. La valeur par défaut de 7 correspond à un temps de environ 50s à 16 min suivant le RTO. Si votre machine supporte un serveur Web, vous pouvez envisager de baisser cette valeur, dans la mesure où de telles sockets peuvent consommer des ressources significatives. Cf tcp_max_orphans. <tag>/proc/sys/net/ipv4/tcp_max_syn_backlog</tag> Nombre maximal de requêtes d'une connection mémorisée, qui n'avait pas encore reçue d'accusé de réception du client connecté. La valeur par défaut est de 1024 pour des systèmes avec plus de 128 Mo de mémoire et 128 pour des machines avec moins de mémoire. Si un serveur souffre de surcharge, essayez d'augmenter ce nombre. Attention ! Si vous positionnez une valeur supérieure à 1024, il serait préférable de changer TCP_SYNQ_HSIZE dans le fichier include/net/tcp.h pour garder TCP_SYNQ_HSIZE*16 <= tcp_max_syn_backlog et de recompiler de noyau. <tag>/proc/sys/net/ipv4/tcp_max_tw_buckets</tag> Nombre maximal de sockets timewait gérées par le système simultanément. Si ce nombre est dépassé, la socket timewait est immédiatement détruite et un message d'avertissement est envoyé. Cette limite n'existe que pour prévenir des attaques de déni de services simples. Vous ne devez pas diminuer cette limite artificiellement, mais plutôt l'augmenter (probablement après avoir augmenté la mémoire) si les conditions du réseau réclament plus que cette valeur par défaut. <tag>/proc/sys/net/ipv4/tcp_retrans_collapse</tag> Compatibilité bug à bug avec certaines imprimantes défectueuses. Tentative d'envoi de plus gros paquets lors de la retransmission pour contourner le bug de certaines piles TCP. <tag>/proc/sys/net/ipv4/tcp_retries1</tag> Combien d'essais avant de décider que quelque chose est erroné et qu'il est nécessaire d'informer de cette suspicion la couche réseau. La valeur minimal du RFC est de 3, qui est celle par défaut et qui correspond à un temps de environ 3 sec à 8 min suivant le RTO. <tag>/proc/sys/net/ipv4/tcp_retries2</tag> Combien d'essais avant de détruire une connection TCP active. La RFC 1122 précise que la limite ne devrait pas dépasser 100 secondes. C'est un nombre trop petit. La valeur par défaut de 15 correspond à un temps de environ 13 à 30 minutes suivant le RTO. <tag>/proc/sys/net/ipv4/tcp_rfc1337</tag> Ce booléen active un rectificatif pour "l'assassinat hazardeux des time-wait dans tcp", décrit dans le RFC 1337. Si activé, le noyau rejette les paquets RST pour les sockets à l'état de time-wait.&nl; Par défaut : 0 <tag>/proc/sys/net/ipv4/tcp_sack</tag> Utilise un ACK sélectif qui peut être utilisé pour signifier que des paquets spécifiques sont manquant. Facilite ainsi une récupération rapide. <tag>/proc/sys/net/ipv4/tcp_stdurg</tag> Utilise l'interprétation de la RFC Host Requirements du champ TCP pointeur urgent. &nl; La plupart des hôtes utilisent la vieille interprétation BSD. Donc, si vous activez cette option, il se peut que Linux ne communique plus correctement avec eux. &nl; Par défaut : FALSE (FAUX) <tag>/proc/sys/net/ipv4/tcp_syn_retries</tag> Nombre de paquets SYN que le noyau enverra avant de tenter l'établissement d'une nouvelle connection. <tag>/proc/sys/net/ipv4/tcp_synack_retries</tag> Pour ouvrir l'autre coté de la connexion, le noyau envoie un SYN avec un ACK superposé (piggyback), pour accuser réception du SYN précédemment envoyé. Ceci est la deuxième partie de la poignée de main à trois voies (threeway handshake). Cette configuration détermine le nombre de paquets SYN+ACK à envoyer avant que le noyau n'abandonne la connection. <tag>/proc/sys/net/ipv4/tcp_timestamps</tag> Les estampilles horaires sont utilisées, entre autre, pour se protéger du rebouclage des numéros de séquence. On peut concevoir qu'un lien à 1 gigabit puisse de nouveau rencontrer un numéro de séquence précédent avec une valeur hors-ligne parcequ'il était d'une génération précédente. L'estampille horaire permet de reconnaître cet "ancien paquet". <tag>/proc/sys/net/ipv4/tcp_tw_recycle</tag> Mise en place du recyclage rapide des sockets TIME-WAIT. La valeur par défaut est 1. Celle-ci ne devrait pas être changée sans le conseil/demande d'experts techniques. <tag>/proc/sys/net/ipv4/tcp_window_scaling</tag> TCP/IP autorise normalement des fenêtres jusqu'à une taille de 65535 octets. Pour des réseaux vraiment rapides, cela peut ne pas être assez. Les options "windows scaling" autorisent des fenêtres jusqu'au gigaoctet, ce qui est adapté pour les produits à grande bande passante. </descrip> <sect2>Configuration périphérique par périphérique <p> DEV peut désigner soit une interface réelle, soit "all", soit "default". Default change également les paramètres des interfaces qui seront créées par la suite. <descrip> <tag>/proc/sys/net/ipv4/conf/DEV/accept_redirects</tag> Si un routeur décide que vous l'utilisez à tort (c'est-à-dire qu'il a besoin de ré-envoyer votre paquet sur la même interface), il vous enverra un message ICMP Redirect. Cela présente cependant un petit risque pour la sécurité, et vous pouvez le désactiver, ou utiliser les redirections sécurisées. <tag>/proc/sys/net/ipv4/conf/DEV/accept_source_route</tag> Plus vraiment utilisé. On l'utilisait pour être capable de donner à un paquet une liste d'adresses IP à visiter. Linux peut être configuré pour satisfaire cette option IP. <tag>/proc/sys/net/ipv4/conf/DEV/bootp_relay</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/conf/DEV/forwarding</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/conf/DEV/log_martians</tag> Voir la section sur le "reverse path filters" <tag>/proc/sys/net/ipv4/conf/DEV/mc_forwarding</tag> Si vous faites de la transmission multidiffusion (multicast) sur cette interface. <tag>/proc/sys/net/ipv4/conf/DEV/proxy_arp</tag> Si vous configurez ceci à 1, toutes les autres interfaces répondront aux requêtes arp destinées à l'adresse de cette interface. Peut être très utile si vous mettez en place des "pseudo-ponts ip". Prenez bien garde d'avoir des masques de sous-réseau correctes avant d'activer cette option. <tag>/proc/sys/net/ipv4/conf/DEV/rp_filter</tag> Voir la section sur le "reverse path filters" <tag>/proc/sys/net/ipv4/conf/DEV/secure_redirects</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/conf/DEV/send_redirects</tag> Si nous envoyons les redirections mentionnées ci-dessus. <tag>/proc/sys/net/ipv4/conf/DEV/shared_media</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/conf/DEV/tag</tag> FIXME: à remplir </descrip> <sect2> Politique de voisinage <p> DEV peut désigner soit une interface réelle, soit "all", soit "default". Default change également les paramètres des interfaces qui seront créées par la suite. <descrip> <tag>/proc/sys/net/ipv4/neigh/DEV/anycast_delay</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/app_solicit</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/base_reachable_time</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/delay_first_probe_time</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/gc_stale_time</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/locktime</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/mcast_solicit</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/proxy_delay</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/proxy_qlen</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/retrans_time</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/ucast_solicit</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/neigh/DEV/unres_qlen</tag> FIXME: à remplir </descrip> <sect2>Configuration du routage <p> <descrip> <tag>/proc/sys/net/ipv4/route/error_burst</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/error_cost</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/flush</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/gc_elasticity</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/gc_interval</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/gc_min_interval</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/gc_thresh</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/gc_timeout</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/max_delay</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/max_size</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/min_adv_mss</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/min_delay</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/min_pmtu</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/mtu_expires</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/redirect_load</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/redirect_number</tag> FIXME: à remplir <tag>/proc/sys/net/ipv4/route/redirect_silence</tag> FIXME: à remplir </descrip> <sect>Application du contrôle de trafic aux dorsales <p> Ce chapitre est conçu comme une introduction au routage de dorsales (backbones). Ces liaisons impliquent souvent des bandes passantes supérieures à 100 mégabits/s, ce qui nécessite une approche différente de celle de votre modem ADSL à la maison. <sect1>Files d'attente de routeurs <p> Le comportement normal des files d'attente de routeurs est appelé "tail-drop" (NdT : élimine le reste). Le "tail-drop" consiste à mettre en file d'attente un certain volume de trafic et à éliminer tout ce qui déborde. Ce n'est pas du tout équitable et cela conduit à des retransmissions de synchronisation. Quand une retransmission de synchronisation a lieu, la brusque rafale de rejet d'un routeur qui a atteint sa limite entraînera une rafale de retransmissions retardée qui inondera à nouveau le routeur congestionné. Dans le but d'en finir avec les congestions occasionnelles des liens, les routeurs de dorsales intègrent souvent des files d'attente de grande taille. Malheureusement, bien que ces files d'attente offrent un bon débit, elles peuvent augmenter sensiblement les temps de latence et entraîner un comportement très saccadé des connections TCP pendant la congestion. Ces problèmes avec le "tail-drop" deviennent de plus en plus préoccupants avec l'augmentation de l'utilisation d'applications hostiles au réseau. Le noyau Linux nous offre la technique RED, abréviation de Random Early Detect, ou détection précoce directe. RED n'est pas la solution miracle à tous ces problèmes. Les applications qui n'intègrent pas correctement la technique de "l'exponential backoff" obtiennent toujours une part trop grande de bande passante. Cependant, avec la technique RED elles ne provoquent pas trop de dégâts sur le débit et les temps de latence des autres connexions. RED élimine statistiquement des paquets du flux avant qu'il n'atteigne sa limite "dure" (hard). Sur une dorsale congestionnée, cela entraîne un ralentissement en douceur de la liaison et évite les retransmissions de synchronisation. La technique RED aide aussi TCP à trouver une vitesse "équitable" plus rapidement : en permettant d'éliminer des paquets plus tôt, il conserve une file d'attente plus courte et des temps de latence mieux contrôlés. La probabilité qu'un paquet soit éliminé d'une connexion particulière est proportionnelle à la bande passante utilisée par cette connexion plutôt qu'au nombre de paquets qu'elle envoie. La technique RED est une bonne gestion de file d'attente pour les dorsales, où vous ne pouvez pas vous permettre le coût d'une mémorisation d'état par session qui est nécessaire pour une mise en file d'attente vraiment équitable. Pour utiliser RED, vous devez régler trois paramètres : Min, Max et burst. Min est la taille minimum de la file d'attente en octets avant que les rejets n'aient lieu, Max est le maximum "doux" (soft) en-dessous duquel l'algorithme s'efforcera de rester, et burst est le nombre maximum de paquets envoyés "en rafale". Vous devriez configurer Min en calculant le plus grand temps de latence acceptable pour la mise en file d'attente, multiplié par votre bande passante. Par exemple, sur mon lien ISDN à 64 Kbits/s, je voudrais avoir un temps de latence de base de mise en file d'attente de 200 ms. Je configure donc Min à 1600 octets (= 0,2 x 64000 / 8). Imposer une valeur Min trop petite va dégrader le débit et une valeur Min trop grande va dégrader le temps de latence. Sur une liaison lente, choisir un coefficient Min petit ne peut pas remplacer une réduction du MTU pour améliorer les temps de réponse. Vous devriez configurer Max à au moins deux fois Min pour éviter les synchronisations. Sur des liens lents avec de petites valeurs de Min, il peut être prudent d'avoir Max quatre fois plus grand que Min ou plus. Burst contrôle la réponse de l'algorithme RED aux rafales. Burst doit être choisi plus grand que min/avpkt (paquet moyen). Expérimentalement, j'ai trouvé que (min+min+max)/(3*avpkt) marche bien. De plus, vous devez configurer limit et avpkt. Limit est une valeur de sécurité : s'il y a plus de Limit octets dans la file, RED reprend la technique "tail-drop". Je choisis une valeur typique égale à 8 fois Max. Avpkt devrait être fixé à la taille moyenne d'un paquet. 1000 fonctionne correctement sur des liaisons Internet haut débit ayant un MTU de 1500 octets. Lire <url url="http://www.aciri.org/floyd/papers/red/red.html" name="the paper on RED queueing"> par Sally Floyd et Van Jacobson pour les informations techniques. FIXME: besoin de plus d'infos. Cela dépend de toi, Greg :-) - ahu <sect>Recettes de cuisine <p> Cette section contient des "recettes de cuisine" qui peuvent vous aider à résoudre vos problèmes. Un livre de cuisine ne remplace cependant pas une réelle compréhension, essayez donc d'assimiler ce qui suit. <!-- <sect1>Réserver de la bande passante pour votre serveur IRC <p> Récemment, les réseaux IRC ont subi des attaques distribuées de déni de service. Le but de ces attaques est d'empêcher la communication entre les serveurs qui maillent le réseau. Un pirate rejoint alors une partie isolée de son réseau. Puisque personne d'autre n'est là, le serveur lui attribue le statut d'opérateur. Le pirate arrête alors l'attaque, le réseau revient, et il prend alors le contrôle du "channel". Ce comportement idiot endommage sérieusement IRC mais, par chance, Linux est là pour le protéger :-) Il nous faut être plus malin que le script pirate moyen ; nous utiliserons donc les fonctionnalités avancées de netfilter pour nous aider. --> <sect1>Faire tourner plusieurs sites avec différentes SLA (autorisations) <p> Vous pouvez faire cela de plusieurs manières. Apache possède un module qui permet de le supporter, mais nous montrerons comment Linux peut le faire pour d'autres services. Les commandes ont été reprises d'une présentation de Jamal Hadi, dont la référence est fournie ci-dessous. Disons que nous avons deux clients, avec http, ftp et du streaming audio, et que nous voulions leur vendre une largeur de bande passante limitée. Nous le ferons sur le serveur lui-même. Le client A doit disposer d'au moins 2 mégabits, et le client B a payé pour 5 mégabits. Nous séparons nos clients en créant deux adresses IP virtuelles sur notre serveur. <tscreen><verb> # ip address add 188.177.166.1 dev eth0 # ip address add 188.177.166.2 dev eth0 </verb></tscreen> C'est à vous d'associer les différents serveurs à la bonne adresse IP. Tous les démons courants supportent cela. Nous pouvons tout d'abord attacher une mise en file d'attente CBQ à eth0 : <tscreen><verb> # tc qdisc add dev eth0 root handle 1: cbq bandwidth 10Mbit cell 8 avpkt 1000 \ mpu 64 </verb></tscreen> Nous créons ensuite les classes pour nos clients : <tscreen><verb> # tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 10Mbit rate \ 2MBit avpkt 1000 prio 5 bounded isolated allot 1514 weight 1 maxburst 21 # tc class add dev eth0 parent 1:0 classid 1:2 cbq bandwidth 10Mbit rate \ 5Mbit avpkt 1000 prio 5 bounded isolated allot 1514 weight 1 maxburst 21 </verb></tscreen> Nous ajoutons les filtres pour nos deux classes : <tscreen><verb> ##FIXME: Pourquoi cette ligne, que fait-elle ? Qu'est-ce qu'un diviseur ? ##FIXME: Un diviseur est lié à une table de hachage et au nombre de seaux -ahu # tc filter add dev eth0 parent 1:0 protocol ip prio 5 handle 1: u32 divisor 1 # tc filter add dev eth0 parent 1:0 prio 5 u32 match ip src 188.177.166.1 flowid 1:1 # tc filter add dev eth0 parent 1:0 prio 5 u32 match ip src 188.177.166.2 flowid 1:2 </verb></tscreen> Et voilà qui est fait. FIXME: Pourquoi pas un filtre token bucket ? Y a t-il un retour par défaut à pfifo_fast quelque part ? <sect1>Protéger votre machine des inondations SYN floods <p>D'après la documentation iproute d'Alexeys, adaptée à netfilter. Si vous utilisez ceci, prenez garde d'ajuster les nombres avec des valeurs raisonnables pour votre système. Si vous voulez protéger tout un réseau, oubliez ce script, qui est plus adapté à un hôte seul. Il apparaît que la toute dernière version de l'outil iproute2 soit nécessaire pour que ceci fonctionne avec le noyau 2.4.0. <tscreen><verb> #! /bin/sh -x # # script simple utilisant les capacités de Ingress # Ce script montre comment on peut limiter le flux entrant des SYN. # Utile pour la protection des TCP-SYN. Vous pouvez utiliser IPchains # pour bénéficier de puissantes fonctionnalités sur les SYN. # # chemins vers les divers utilitaires # À changer en fonction des vôtres # TC=/sbin/tc IP=/sbin/ip IPTABLES=/sbin/iptables INDEV=eth2 # # marque tous les paquets SYN entrant à travers $INDEV avec la valeur 1 ############################################################ $iptables -A PREROUTING -i $INDEV -t mangle -p tcp --syn \ -j MARK --set-mark 1 ############################################################ # # installe la file d'attente ingress sur l'interface associée ############################################################ $TC qdisc add dev $INDEV handle ffff: ingress ############################################################ # # Les paquets SYN ont une taille de 40 octets (320 bits), donc trois SYN # ont une taille de 960 bits (approximativement 1Kbit) ; nous limitons donc # les SYNs entrants à 3 par seconde (pas vraiment utile, mais sert à # montrer ce point -JHS ############################################################ $TC filter add dev $INDEV parent ffff: protocol ip prio 50 handle 1 fw \ police rate 1kbit burst 40 mtu 9k drop flowid :1 ############################################################ # echo "---- qdisc parameters Ingress ----------" $TC qdisc ls dev $INDEV echo "---- Class parameters Ingress ----------" $TC class ls dev $INDEV echo "---- filter parameters Ingress ----------" $TC filter ls dev $INDEV parent ffff: #supprime la file d'attente ingress #$TC qdisc del $INDEV ingress </verb></tscreen> <sect1>Limiter le débit ICMP pour empêcher les dénis de service <p> Récemment, les attaques distribuées de déni de service sont devenues une nuisance importante sur Internet. En filtrant proprement et en limitant le débit de votre réseau, vous pouvez à la fois éviter de devenir victime ou source de ces attaques. Vous devriez filtrer vos réseaux de telle sorte que vous n'autorisiez pas les paquets avec une adresse IP source non-locale à quitter votre réseau. Cela empêche les utilisateurs d'envoyer de manière anonyme des cochonneries sur Internet. <!-- FIXME: netfilter one liner. Is there a netfilter one-liner? - Martijn --> La limitation de débit peut faire encore mieux, comme vu plus haut. Pour vous rafraîchir la mémoire, revoici notre diagramme ASCII : <tscreen><verb> [Internet] ---<E3, T3, n'importe quoi>--- [routeur Linux] --- [Bureau+FAI] eth1 eth0 </verb></tscreen> Nous allons d'abord configurer les parties prérequises : <tscreen><verb> # tc qdisc add dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000 # tc class add dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate \ 10Mbit allot 1514 prio 5 maxburst 20 avpkt 1000 </verb></tscreen> Si vous avez des interfaces de 100 Mbits ou plus, ajustez ces nombres. Maintenant, vous devez déterminer combien de trafic ICMP vous voulez autoriser. Vous pouvez réaliser des mesures avec tcpdump, en écrivant les résultats dans un fichier pendant un moment, et regarder combien de paquets ICMP passent par votre réseau. Ne pas oublier d'augmenter la longueur du "snapshot". Si la mesure n'est pas possible, vous pouvez consacrer par exemple 5% de votre bande passante disponible. Configurons notre classe : <tscreen><verb> # tc class add dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate \ 100Kbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 250 \ bounded </verb></tscreen> Cela limite le débit à 100 Kbits sur la classe. Maintenant, nous avons besoin d'un filtre pour assigner le trafic ICMP à cette classe : <tscreen><verb> # tc filter add dev eth0 parent 10:0 protocol ip prio 100 u32 match ip protocol 1 0xFF flowid 10:100 </verb></tscreen> <sect1>Donner la priorité au trafic interactif <p> Si beaucoup de données arrivent à votre lien ou en partent, et que vous essayez de faire de la maintenance via telnet ou ssh, cela peut poser problème : d'autres paquets bloquent vos frappes clavier. Cela ne serait-il pas mieux si vos paquets interactifs pouvaient se faufiler dans le trafic de masse ? Linux peut faire cela pour vous. Comme précédemment, nous avons besoin de manipuler le trafic dans les deux sens. Evidemment, cela marche mieux s'il y a des machines Linux aux deux extrémités du lien, bien que d'autres UNIX soient capables de faire la même chose. Consultez votre gourou local Solaris/BSD pour cela. Le gestionnaire standard pfifo_fast a trois "bandes" différentes. Le trafic de la bande 0 est transmis en premier, le trafic des bandes 1 et 2 étant traité après. Il est vital que votre trafic interactif soit dans la bande 0 ! Ce qui suit est adapté du (bientôt obsolète) Ipchains-HOWTO : Il y a quatre bits rarement utilisés dans l'en-tête IP, appelés bits de Type de Service (TOS). Ils affectent la manière dont les paquets sont traités. Les quatre bits sont "Délai Minimum", "Débit Maximum", "Fiabilité Maximum" et "Coût Minimum". Seul un de ces bits peut être positionné. Rob van Nieuwkerk, l'auteur du code TOS-mangling dans ipchains, le configure comme suit : <tscreen> Le "Délai Minimum" est particulièrement important pour moi. Je le positionne à 1 pour les paquets interactifs sur mon routeur (Linux) qui envoie le trafic vers l'extérieur. Je suis derrière un modem à 33,6 Kbps. Linux répartit les paquets dans trois files d'attente. De cette manière, j'obtiens des performances acceptables pour le trafic interactif tout en téléchargeant en même temps. </tscreen> L'utilisation la plus commune est de configurer les connections telnet et ftp à "Délai Minimum" et les données FTP à "Débit Maximum". Cela serait fait comme suit, sur mon routeur : <tscreen><verb> # iptables -A PREROUTING -t mangle -p tcp --sport telnet \ -j TOS --set-tos Minimize-Delay # iptables -A PREROUTING -t mangle -p tcp --sport ftp \ -j TOS --set-tos Minimize-Delay # iptables -A PREROUTING -t mangle -p tcp --sport ftp-data \ -j TOS --set-tos Maximize-Throughput </verb></tscreen> En fait, cela ne marche que pour les données venant d'un telnet extérieur vers votre ordinateur local. Dans l'autre sens, ça se fait tout seul : telnet, ssh, et consorts configurent le champ TOS automatiquement pour les paquets sortants. Si vous avez un client incapable de le faire, vous pouvez toujours le faire avec netfilter. Sur votre machine locale : <tscreen><verb> # iptables -A OUTPUT -t mangle -p tcp --dport telnet \ -j TOS --set-tos Minimize-Delay # iptables -A OUTPUT -t mangle -p tcp --dport ftp \ -j TOS --set-tos Minimize-Delay # iptables -A OUTPUT -t mangle -p tcp --dport ftp-data \ -j TOS --set-tos Maximize-Throughput </verb></tscreen> <sect1>Cache web transparent utilisant netfilter, iproutes2, ipchains et squid <p> <label id="SQUID"> Cette section a été envoyée par le lecteur Ram Narula de "Internet for Education" (Internet pour l'éducation) (Thailande). La technique habituelle pour réaliser ceci dans Linux est probablement l'utilisation d'ipchains APRES s'être assuré que le trafic sortant du port 80 (web) est routé à travers le serveur faisant fonctionner squid. Il y a 3 méthodes communes pour être sûr que le trafic sortant du port 80 est routé vers le serveur faisant fonctionner squid et une quatrième est introduite ici. <descrip> <tag>La passerelle le fait.</tag> Si vous pouvez dire à votre passerelle que les paquets sortants à destination du port 80 doivent être envoyés vers l'adresse IP du serveur squid. <p> MAIS <p> Ceci amenerait une charge supplémentaire sur le routeur et des routeurs commerciaux peuvent même ne pas supporter ceci. <tag>Utiliser un commutateur Couche 4.</tag> Les commutateurs Couche 4 peuvent manipuler ceci sans aucun problème. <p> MAIS <p> Le coût pour un tel équipement est en général très élevé. Typiquement, un commutateur couche 4 coute normalement plus cher qu'un serveur classique + un bon serveur linux. <tag>Utiliser le serveur cache comme passerelle réseau</tag> Vous pouvez forcer TOUT le trafic à travers le serveur cache <p> MAIS <p> Ceci est plutôt risqué dans la mesure où Squid utilise beaucoup de ressources CPU, ce qui peut conduire à une baisse des performances de tout le réseau. Le serveur peut également ne plus fonctionner et personne sur le réseau ne pourra accéder à Internet si cela a lieu. <tag>Routeur Linux+NetFilter.</tag> En utilisant Netfilter, une autre technique peut être implémentée. Celle-ci consiste à utiliser Netfilter pour "marquer" les paquets à destination du port 80 et à utiliser iproute2 pour router les paquets "marqués" vers le serveur Squid. </descrip> <tscreen><verb> |----------------| | Implémentation | |----------------| Adresses utilisées 10.0.0.1 naret (serveur NetFilter) 10.0.0.2 silom (serveur Squid) 10.0.0.3 donmuang (Routeur connecté à Internet) 10.0.0.4 kaosarn (un autre serveur sur le réseau) 10.0.0.5 RAS 10.0.0.0/24 réseau principal 10.0.0.0/19 réseau total |----------------| |Schéma du réseau| |----------------| Internet | donmuang | ------------hub/commutateur---------- | | | | naret silom kaosarn RAS etc. </verb></tscreen> Premièrement, faire en sorte que tout le trafic passe par naret en étant sûr que c'est la passerelle par défaut, à l'exception de silom. La passerelle par défaut de silom doit être donmuang (10.0.0.3) ou ceci créerait une boucle du trafic web. <p> (Tous les serveurs sur mon réseau avait 10.0.0.1 comme passerelle par défaut qui était l'ancienne adresse du routeur donmuang. Cela m'a conduit à attribuer 10.0.0.3 comme adresse IP à donmuang et à donner 10.0.0.1 comme adresse IP à naret) <tscreen><verb> Silom ----- -configurer squid et ipchains </verb></tscreen> <p> Pour la configuration du serveur Squid sur silom, soyez sûr que celui-ci supporte le cache/proxy transparent (transparent caching/proxying). Le port par défaut pour squid est en général 3128. Tout le trafic pour le port 80 doit donc être rédirigé localement vers le port 3128. Ceci peut être fait en utilisant ipchains comme suit : <tscreen><verb> silom# ipchains -N allow1 silom# ipchains -A allow1 -p TCP -s 10.0.0.0/19 -d 0/0 80 -j REDIRECT 3128 silom# ipchains -I input -j allow1 </verb></tscreen> <p> Ou, avec netfilter: <tscreen><verb> silom# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128 </verb></tscreen> (note: vous pouvez avoir également d'autres entrées) <p> Pour plus d'informations sur la configuration du serveur Squid, se référer à la page FAQ Squid sur <url url="http://squid.nlanr.net" name="http://squid.nlanr.net">). <p> Soyez sûr que l"ip forwarding" est actif sur votre serveur et que la passerelle par défaut pour ce serveur est donmuand (PAS naret). <tscreen><verb> Naret ----- - configurer squid et ipchains - désactiver les messages icmp REDIRECT (si besoin) </verb></tscreen> <enum> <item>"Marquer" les paquets à destination du port 80 avec la valeur 2 <tscreen><verb> naret# iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 80 \ -j MARK --set-mark 2 </verb></tscreen> </item> <item>Configurer iproute2 de sorte qu'il route les paquets avec la marque 2 vers silom <tscreen><verb> naret# echo 202 www.out >> /etc/iproute2/rt_tables naret# ip rule add fwmark 2 table www.out naret# ip route add default via 10.0.0.2 dev eth0 table www.out naret# ip route flush cache </verb></tscreen> <p> Si donmuang et naret sont sur le même réseau, naret ne doit pas envoyer de messages icmp REDIRECT. Ceux-ci doivent être désactivés par : <tscreen><verb> naret# echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects naret# echo 0 > /proc/sys/net/ipv4/conf/default/send_redirects naret# echo 0 > /proc/sys/net/ipv4/conf/eth0/send_redirects </verb></tscreen> </item> </enum> La configuration est terminée, vérifions la. <tscreen><verb> Sur naret: naret# iptables -t mangle -L Chain PREROUTING (policy ACCEPT) target prot opt source destination MARK tcp -- anywhere anywhere tcp dpt:www MARK set 0x2 Chain OUTPUT (policy ACCEPT) target prot opt source destination naret# ip rule ls 0: from all lookup local 32765: from all fwmark 2 lookup www.out 32766: from all lookup main 32767: from all lookup default naret# ip route list table www.out default via 203.114.224.8 dev eth0 naret# ip route 10.0.0.1 dev eth0 scope link 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.1 127.0.0.0/8 dev lo scope link default via 10.0.0.3 dev eth0 (soyez sûr que silom appartienne à l'une des lignes ci-dessus. Dans ce cas, c'est la ligne avec 10.0.0.0/24) |------| |-FAIT-| |------| </verb></tscreen> <sect2>Schéma du trafic après l'implémentation <p> <tscreen><verb> |---------------------------------------| |Schéma du trafic après l'implémentation| |---------------------------------------| INTERNET /\ || \/ -----------------routeur donmuang--------------------- /\ /\ || || || || || \/ || naret silom || *trafic à destination du port 80=====>(cache) || /\ || || || \/ \/ \\===================================kaosarn, RAS, etc. </verb></tscreen> Noter que le réseau est asymétrique car il y a un saut supplémentaire sur le chemin sortant. <tscreen><verb> Voici le cheminement d'un paquet traversant le réseau de kaosarn allant et venant d'Internet. Pour le trafic web/http : requête http kaosarn->naret->silom->donmuang->internet réponse http de Internet->donmuang->silom->kaosarn Pour les requêtes non web/http (par ex. telnet) : données sortantes kaosarn->naret->donmuang->internet données entrantes d'Internet->donmuang->kaosarn </verb></tscreen> <sect1>Circonvenir aux problèmes de la découverte du MTU de chemin en configurant un MTU par routes <p> Pour envoyer de grande quantité de données, Internet fonctionne généralement mieux quand de grands paquets sont utilisés. Chaque paquet implique une décision de routage. Le transfert d'un fichier de 1Mo peut entrainer soit l'envoi de 700 paquets, en maximisant la taille des paquets, soit de 4000 paquets en utilisant la plus petite taille possible. Cependant, tous les éléments d'Internet ne supportent pas une capacité utile (payload) de 1460 octets par paquet. Il est de plus nécessaire d'essayer de trouver le plus grand paquet qui "conviendra" le mieux, dans le but d'optimiser la connection. Ce processus est appelé "Découverte du MTU de chemin", où MTU signifie 'Maximum Transfert Unit' (Unité de transfert maximum). Quand un routeur rencontre un paquet qui est trop gros pour être envoyé en un seul morceau, ET que celui-ci a été marqué avec le bit "Don't Fragment", il retourne un message ICMP indiquant qu'il a été obligé de rejetter le paquet. L'hôte emetteur prend acte de cette indication en envoyant des paquets plus petits et, par itération, peut trouver la taille optimum du paquet pour une connection à travers un chemin particulier. Ceci fonctionnait correctement jusqu'à ce que Internet soit découvert par des vandales qui s'efforcent de perturber les communications. Ceci a conduit les administrateurs à, soit bloquer, soit mettre en forme le trafic ICMP lors d'essais malencontreux dans le but d'améliorer la sécurité ou la robustesse de leurs services Internet. La conséquense, maintenant, est que la découverte du MTU de chemin fonctionne de moins en moins bien, et échoue pour certaines routes, conduisant à d'étranges sessions TCP/IP qui tombent peu de temps après. Bien que je n'ai pas de preuves de ceci, deux sites avec qui j'avais l'habitude d'avoir des problèmes faisait fonctionner à la fois Alteon et Acedirectors avant les systèmes affectés. Peut-être quelqu'un avec plus de connaissances peut fournir des indices quant à la raison de ce qui se passe. <sect2>Solution <p> Quand vous rencontrez des sites qui présentent ce problème, vous pouvez déactiver la découverte du MTU de chemin en le configurant manuellement. Koos van den Hout a peu près écrit : <tscreen> <p> Le problème suivant : j'ai configuré le mtu et mru de ma ligne dédiée fonctionnant avec ppp à 296 dans la mesure où le débit est de seulement 33k6 et que je ne peux pas influencer la file d'attente de l'autre coté. A 296, la réponse à l'appui d'un touche intervient dans un délai résonnable. Et, de mon coté, j'ai un routeur avec translation d'adresse (masquage) fonctionnant (bien sûr) sous Linux. Récemment, j'ai séparé le serveur du routeur de sorte que la plupart des applications fonctionnent sur une machine différente que celle qui réalise le routage. J'ai alors eu des problèmes en me connectant sur l'irc. Grosse panique ! Je vous assure que certains essais trouvaient que j'étais connecté à l'irc, me montrant même comme connecté sur l'irc mais je ne reçevais pas le "motd" (message of the day, message du jour) de l'irc. J'ai vérifié ce qui pouvait être erroné et ai noté que j'avais déjà eu des soucis liés au MTU en contactant certains sites web. Je n'avais aucun souci pour les atteindre quand le MTU était à 1500, le problème n'apparaissant que lorsque le MTU était configuré à 296. Puisque les serveurs irc bloquent tout le trafic dont il n'ont pas besoin pour leurs opérations immédiates, ils bloquent aussi l'icmp. J'ai manoeuvré pour convaincre les responsables d'un serveur web que ceci était la cause d'un problème, mais les responsables du serveur irc n'avaient pas l'intention de réparer ceci. Donc, je devais être sûr que le trafic masqué sortant partait avec le mtu faible du lien externe. Mais, je voulais que le trafic ethernet local ait le MTU normal (pour des choses comme le trafic nfs). Solution : <tscreen><verb> ip route add default via 10.0.0.1 mtu 296 </verb></tscreen> (10.0.0.1 étant ma passerelle par défaut, l'adresse interne de mon routeur masquant) </tscreen> En général, il est posible d'outrepasser la découverte du MTU de chemin en configurant des routes spécifiques. Par exemple, si seuls certains réseaux posent problèmes, ceci devrait aider : <tscreen><verb> ip route add 195.96.96.0/24 via 10.0.0.1 mtu 1000 </verb></tscreen> <sect1>Circonvenir aux problèmes de la découverte du MTU de chemin en imposant le MSS (pour les utilisateurs de l'ADSL, du cable, de PPPoE & PPtP) <p> Comme expliqué au dessus, la découverte du MTU de chemin ne marche pas aussi bien que cela devrait être. Si vous savez qu'un saut de votre réseau a un MTU limité (<1500), vous ne pouvez pas compter sur la découverte du MTU de chemin pour le découvrir. Outre le MTU, il y a encore un autre moyen de configurer la taille maximum du paquet, par ce qui est appelé le MSS (Maximum Segment Size, Taille Maximum du Segment). C'est un champ dans les options TCP du paquet SYN. Les noyaux Linux récents, et quelques pilotes de périphérique pppoe (notamment, l'excellent Roaring Penguin) implémente la possiblité de 'fixer le MSS'. Le bon coté de tout ceci est que, en positionnant la valeur MSS, vous dîtes à l'hôte distant de manière équivoque "n'essaie pas de m'envoyer des paquets plus grands que cette valeur". Aucun trafic ICMP n'est nécessaire pour faire fonctionner cela. Malheureusement, c'est de la bidouille évidente -- ça détruit la propriété «bout-en-bout» de la connexion en modifiant les paquets. Ayant dit cela, nous utilisons cette astuce dans beaucoup d'endroit et cela fonctionne comme un charme. Pour que tout ceci fonctionne, vous aurez besoin au moins de iptables-1.2.1a et de Linux 2.4.3 ou plus. La ligne de commande basique est : <tscreen><verb> # iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu </verb></tscreen> Ceci calcule le MSS approprié pour votre lien. Si vous vous sentez courageux, ou que vous pensez être le mieux placé pour juger, vous pouvez aussi faire quelque chose comme ceci : <tscreen><verb> # iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 128 </verb></tscreen> Ceci configure le MSS du paquet SYN à 128. Utilisez ceci si vous avez de la voix sur IP (VoIP) avec de tous petits paquets, et de grands paquets http qui provoquent des coupures dans vos communications vocales. <sect>Construire des ponts et des pseudo-ponts avec du Proxy ARP <p> Les ponts sont des périphériques qui peuvent être installés dans un réseau sans aucune reconfiguration. Un commutateur réseau est basiquement un pont multi-ports. Un pont est souvent un commutateur avec 2 ports. Cependant, Linux supporte très bien plusieurs interfaces dans un pont, le conduisant à fonctionner comme un vrai commutateur. Les ponts sont souvent déployés quant on est confronté à un réseau défaillant qui a besoin d'être réparé sans aucune modification. Dans la mesure où un pont est un équipement de niveau 2, la couche sous la couche IP, les routeurs et serveurs ne sont pas conscients de son existance. Ceci signifie que vous pouvez bloquer ou modifier certains paquets de manière transparente, ou mettre en forme le trafic. Un autre élément positif est qu'un pont peut souvent être remplacé par un cable croisé ou un hub quand il tombe en panne. L'aspect négatif est que le mise en place d'un pont peut engendrer beaucoup de confusion, à moins qu'il ne soit très bien configuré. Le pont n'apparait pas dans les traceroute, mais pourtant des paquets disparaissent sans raison ou sont changés en allant d'un point A à un point B. Vous devriez également vous demander si une organisation qui "ne veut rien changer" fait le bon choix. Le "pont Linux 2.4" est documenté sur <url url="http://www.math.leidenuniv.nl/~buytenh/bridge" name="cet page">. <sect1>Etat des ponts et iptables <p> Au moment de Linux 2.4.3, le pont et iptables ne se "voient" pas l'un l'autre sans une aide. Si vous "pontez" les paquets de eth0 à eth1, ils ne "passent" pas par iptables. Ceci signifie que vous ne pouvez pas faire de filtrage, de translation d'adresse (NAT), de dessosage ou quoique ce soit d'autres. Il y a plusieurs projets essayant de corriger ceci, le meilleur étant celui de l'auteur du code du pont Linux 2.4, Lennert Buytenhek. La mise à jour n'est cependant pas encore terminée, mais elle fonctionne quelque peu. Elle peut être trouvée sur <url url="http://www.math.leidenuniv.nl/~buytenh/bridge/devel/bridge-nf/" name="the experimental bridge patches page">. Nous comptons que ce problème soit bientôt résolu. <sect1>Pont et mise en forme <p> Ca marche comme dans les réclames. Soyez sûr du coté attribué à chaque interface. Autrement, il se peut que vous mettiez en forme le trafic sortant au niveau de votre interface interne, ce qui ne marchera pas. Utilisez tcpdump si nécessaire. <sect1>Pseudo-pont avec du Proxy-ARP <p> Si vous voulez juste implémenter un pseudo-pont, allez jusqu'à la section "Implémentez-le". Cependant, il est sage de lire un peu la façon dont il fonctionne en pratique. Un pseudo-pont travaille de manière un peu différente. Par défaut, un pont transmet les paquets sans les altérer d'une interface à une autre. Il ne regarde que l'adresse matérielle des paquets pour déterminer où ils doivent aller. Ceci signifie que vous pouvez "pontez" un trafic que Linux ne comprend pas, aussi longtemps qu'il y a une adresse matérielle. Un "pseudo-pont" travaille différemment et ressemble plus à un routeur caché qu'à un pont. Mais, comme un pont, il a un impact faible sur l'architecture du réseau. Le fait qu'il ne soit pas un pont présente l'avantage que les paquets traversent réellement le noyau, et peuvent être filtrés, modifiés, redirigés ou reroutés. Un pont réel peut également réaliser ces tours de force, mais il a besoin d'un code spécial, comme le Ethernet Frame Diverter, ou la mise à jour mentionnée au dessus. Un autre avantage d'un pseudo-pont est qu'il ne transmet pas les paquets qu'il ne comprend pas, nettoyant ainsi votre réseau de beaucoup de cochonneries. Dans le cas où vous avez besoin de ces cochonneries (comme les paquets SAP, ou Netbeui), utilisez un vrai pont. <sect2>ARP & Proxy-ARP <p> Quand un hôte veut dialoguer avec un autre hôte sur le même segment physique, il envoie un paquet du Protocole de Résolution d'Adresse (ARP) qui, en simplifiant quelque peu, est lu comme ceci : "Qui a 10.0.0.1, le dire à 10.0.0.7". En réponse à ceci, 10.0.0.1 renvoie un petit paquet "ici". 10.0.0.7 envoie alors des paquets à l'adresse matérielle mentionnée dans le paquet "ici". Il met dans un cache cette adresse matérielle pour un temps relativement long et, après l'expiration du cache, repose sa question. Quand on construit un pseudo-pont, on configure le pont pour qu'il réponde à ces paquets ARP, les hôtes du réseau envoyant alors leurs paquets au pont. Le pont traite alors ces paquets et les envoie à l'interface adaptée. Donc, en résumé, quand un hôte d'un coté du pont demande l'adresse matérielle d'un hôte se situant de l'autre coté, le pont répond avec un paquet qui dit "transmets le moi". De cette façon, tout le trafic de données est transmis à la bonne place et il traverse toujours le pont. <sect2>Implémentez-le <p> Les versions anciennes du noyau linux permettait de faire du proxy ARP uniquement à une granularité sous réseaux. Ainsi, pour configurer un pseudo-pont, il fallait spécifier les bonnes routes vers les deux cotés du pont, et également créer les règles proxy-ARP correspondantes. C'était pénible, déjà par la quantité de texte qu'il fallait taper, puis parce qu'il était facile de se tromper et créer des configurations éronnées, où le pont répondait à des requêtes pour des réseaux qu'il ne savait pas router. Avec Linux 2.4 (et peut-être bien le 2.2), cette possibilité a été retirée et a été remplacée par une option dans le répertoire /proc, appelée "proxy-arp". La procédure pour construire un pseudo-pont est maintenant : <enum> <item>Assigner une adresse à chaque interface, la "gauche" et la "droite" <item>Créer des routes pour que votre machine connaisse quels hôtes résident à gauche et quels hôtes résident à droite <item>Activer le proxy-ARP sur chaque interface&nl; echo 1 > /proc/sys/net/ipv4/conf/ethL/proxy_arp&nl; echo 1 > /proc/sys/net/ipv4/conf/ethR/proxy_arp&nl; où L et R désignent les numéros de l'interface du coté gauche (Left) et de celle du coté droit (Right) </enum> N'oubliez pas également d'activer l'option ip_forwarding ! Quant on convertit un vrai pont, il se peut que vous trouviez cette option déactivée dans la mesure où il n'y en a pas besoin pour un pont. Une autre chose que vous devriez considérer lors de la conversion est que vous aurez besoin d'effacer le cache arp des ordinateurs du réseau. Le cache arp peut contenir d'anciennes adresses matérielles du pont qui ne sont plus correctes. Sur un cisco, ceci est réalisé en utilisant la commande 'clear arp-cache' et, sous linux, en utilisant 'arp -d ip.adresse'. Vous pouvez aussi attendre l'expiration manuelle du cache, ce qui peut être plutôt long. <sect>Routage avancé sur Linux <p> Cette section est destinée à tous les gens qui voudraient savoir comment fonctionne le système complet ou qui ont une configuration si bizarre qu'ils ont besoin d'informations "bas niveau" pour le faire fonctionner. Cette section est complètement facultative. Il est tout à fait possible qu'elle soit trop complexe et pas vraiment destinée aux utilisateurs normaux. Vous avez été averti. FIXME: Décider ce qui doit réellement être ici. <sect1>Comment la mise en file d'attente des paquets fonctionne-t-elle en pratique ? <p>C'est la base du fonctionnement du système de mise en file d'attente d'un paquet. Lister les étapes que le noyau réalise pour classifier un paquet, etc. FIXME: à écrire. <sect1>Utilisation avancée du système de mise en file d'attente des paquets <p>Passer par l'exemple extrêmement rusé de Alexeys impliquant les bits inutilisés dans le champs TOS. FIXME: à écrire. <sect1>D'autres systèmes de mise en forme des paquets <p>Je voudrais inclure une brève description sur les autres systèmes de mise en forme des paquets dans d'autres systèmes d'exploitation et les comparer à celui de Linux. Puisque Linux est l'un des rares OS qui ont une pile TCP/IP originale (non dérivée de BSD), je pense qu'il serait intéressant de savoir comment les autres font cela. Malheureusement je n'ai aucune expérience sur d'autres systèmes, aussi je ne peux pas l'écrire. FIXME: Personne ? - Martijn <sect>Routage Dynamique - OSPF et BGP <p> Si votre réseau commence à devenir vraiment gros, ou si vous commencez à considérer Internet comme votre propre réseau, vous avez besoin d'outils qui routent dynamiquement vos données. Les sites sont souvent reliés entre eux par de multiples liens, et de nouveaux liens surgissent en permanence. L'Internet utilise la plupart du temps les standards OSPF et BGP4 (rfc1771). Linux supporte les deux, par le biais de <tt>gated</tt> et <tt>zebra</tt>. Ce sujet est pour le moment hors du propos de ce document, mais laissez-nous vous diriger vers des travaux de référence : Vue d'ensemble : Cisco Systems <url url="http://www.cisco.com/univercd/cc/td/doc/cisintwk/idg4/nd2003.htm" name="Cisco Systems Designing large-scale IP internetworks"> Pour OSPF : Moy, John T. "OSPF. The anatomy of an Internet routing protocol" Addison Wesley. Reading, MA. 1998. Halabi a aussi écrit un très bon guide sur la conception du routage OSPF, mais il semble avoir été effacé du site Web de Cisco. Pour BGP : Halabi, Bassam "Internet routing architectures" Cisco Press (New Riders Publishing). Indianapolis, IN. 1997. Il existe aussi Cisco Systems <url url="http://www.cisco.com/univercd/cc/td/doc/cisintwk/ics/icsbgp4.htm" name="Using the Border Gateway Protocol for Interdomain Routing"> Bien que les exemples soient spécifiques à Cisco, ils sont remarquablement semblables au langage de configuration de Zebra :-) <sect>Autres possibilités <p> Ce chapitre est une liste des projets ayant une relation avec le routage avancé et la mise en forme du trafic sous Linux. Certains de ces liens mériteraient des chapitres spécifiques, d'autres sont très bien documentés, et n'ont pas besoin de HOWTO en plus. <p> <descrip> <tag>Implémentation VLAN 802.1Q pour Linux <url url="http://scry.wanfear.com/~greear/vlan.html" name="(site)"></tag> <p> VLAN est une façon très sympa de diviser vos réseaux d'une manière plus virtuelle que physique. De bonnes informations sur les VLAN pourront être trouvées <url url="ftp://ftp.netlab.ohio-state.edu/pub/jain/courses/cis788-97/virtual_lans/index.htm" name="ici">. Avec cette implémentation, votre boite Linux pourra dialoguer VLAN avec des machines comme les Cisco Catalyst, 3Com: {Corebuilder, Netbuilder II, SuperStack II switch 630}, Extreme Ntwks Summit 48, Foundry: {ServerIronXL, FastIron}. <tag>Implémantation alternative VLAN 802.1Q pour Linux<url url="http://vlan.sourceforge.net " name="(site)"></tag> Une implémantation alternative de VLAN pour Linux. Ce projet a démarré suite au désaccord avec l'architecture et le style de codage du projet VLAN 'établi', avec comme résultat une structure de l'ensemble plus clair. <tag>Serveur Linux Virtuel (Linux Virtual Server )<url url="http://www.LinuxVirtualServer.org/" name="(site)"></tag> <p> Ces personnes sont très talentueuses. Le Serveur Virtuel Linux est un serveur à haute disponibilité, hautement évolutif, construit autour d'une grappe (cluster) de serveurs, avec un équilibreur de charge tournant sur le système d'exploitation Linux. L'architecture du cluster est transparent pour les utilisateurs finaux, qui ne voient qu'un simple serveur virtuel. En résumé, que vous ayez besoin d'équilibrer votre charge ou de contrôler votre trafic, LVS aura une manière de le faire. Certaines de leurs techniques sont positivement diaboliques !. Par exemple, ils permettent à plusieurs machines d'avoir une même adresse IP, mais en désactivant l'ARP dessus. Seule la machine LVS qui a, elle, l'ARP actif, décide de l'hôte qui manipulera le paquet entrant. Celui-ci est envoyé avec la bonne adresse MAC au serveur choisi. Le trafic sortant passe directement par le routeur, et non par la machine LVS, qui, par conséquent n'a pas besoin de voir vos 5Gbit/s de données allant sur Internet. Cette machine LVS ne peut alors pas être un goulot d'étranglement. L'implémentation de LVS nécessite une mise à jour pour les noyaux 2.0 et 2.2, alors qu'un module Netfilter est disponible dans le 2.4. Il n'y a donc pas besoin de mise à jour pour cette version du noyau. Le support 2.4 est encore en développement. Battez vous donc avec et envoyez vos commentaires ou vos mises à jour. <tag>CBQ.init <url url="ftp://ftp.equinox.gu.net/pub/linux/cbq/" name="(site)"></tag> Configurer CBQ peut être un peu intimidant, spécialement si votre seul souhait est de mettre en forme le trafic d'ordinateurs placés derrière un routeur. CBQ.init peut vous aider à configurer Linux à l'aide d'une syntaxe simplifiée. Par exemple, si vous voulez que tous les ordinateurs de votre réseau 192.168.1.0/24 (sur eth1 10 Mbits) aient leur vitesse de téléchargement limitée à 28 Kbits, remplissez le fichier de configuration de CBQ.init avec ce qui suit : <tscreen><verb> DEVICE=eth1,10Mbit,1Mbit RATE=28Kbit WEIGHT=2Kbit PRIO=5 RULE=192.168.1.0/24 </verb></tscreen> Utiliser simplement ce programme si le 'comment et pourquoi' ne vous intéresse pas. Nous utilisons CBQ.init en production et il marche très bien. On peut même faire des choses plus avancées, comme la mise en forme dépendant du temps. La documentation est directement intégrée dans le script, ce qui explique l'absence d'un fichier README. <tag>Scripts faciles de mise en forme Chronox<url url="http://www.chronox.de" name="(site)"></tag> Stephan Mueller (smueller@chronox.de) a écrit deux scripts utiles, "limit.conn" et "shaper". Le premier vous permet de maîtriser une session de téléchargement, comme ceci : <tscreen><verb> # limit.conn -s SERVERIP -p SERVERPORT -l LIMIT </verb></tscreen> Il fonctionne avec Linux 2.2 et 2.4. Le second script est plus compliqué et peut être utilisé pour mettre en place des files d'attente différentes basées sur les règles iptables. Celles-ci sont utilisées pour marquer les paquets qui sont alors mis en forme. <tag>Implémentation du Protocole Redondant Routeur Virtuel <url url="http://w3.arobas.net/~jetienne/vrrpd/index.html" name="(site)"></tag> <p> Ceci est purement pour la redondance. Deux machines avec leurs propres adresses IP et MAC créent une troisième adresse IP et MAC virtuelle. Bien que destiné à l'origine uniquement aux routeurs, qui ont besoin d'adresses MAC constantes, cela marche également pour les autres serveurs. <p> La beauté de cette approche est l'incroyable facilité de la configuration. Pas de compilation de noyau ou de nécessité de mise à jour, tout se passe dans l'espace utilisateur. Lancer simplement ceci sur toutes les machines participant au service : <tscreen><verb> # vrrpd -i eth0 -v 50 10.0.0.22 </verb></tscreen> Et vous voilà opérationnel ! 10.0.0.22 est maintenant géré par l'un de vos serveurs, probablement le premier à avoir lancé le démon vrrp. Déconnectez maintenant cet ordinateur du réseau et très rapidement, l'adresse 10.0.0.22 et l'adresse MAC seront gérées par l'un des autres ordinateurs. J'ai essayé ceci et il a été actif et opérationnel en 1 minute. Pour une raison étrange, ma passerelle par défaut a été supprimée. Cependant, l'option -n permet de prévenir cela. Voici une défaillance en "direct" : <tscreen><verb> 64 bytes from 10.0.0.22: icmp_seq=3 ttl=255 time=0.2 ms 64 bytes from 10.0.0.22: icmp_seq=4 ttl=255 time=0.2 ms 64 bytes from 10.0.0.22: icmp_seq=5 ttl=255 time=16.8 ms 64 bytes from 10.0.0.22: icmp_seq=6 ttl=255 time=1.8 ms 64 bytes from 10.0.0.22: icmp_seq=7 ttl=255 time=1.7 ms </verb></tscreen> Pas *un* paquet ping n'a été perdu ! Après 4 paquets, j'ai déconnecté mon P200 du réseau, et mon 486 a pris le relai, ce qui est visible par l'augmentation du temps de latence. </descrip> <sect>Lectures supplémentaires <p> <descrip> <tag><url url="http://snafu.freedom.org/linux2.2/iproute-notes.html" name="http://snafu.freedom.org/linux2.2/iproute-notes.html"></tag> Contient beaucoup d'informations techniques, et de commentaires sur le noyau. <tag><url url="http://www.davin.ottawa.on.ca/ols/" name="http://www.davin.ottawa.on.ca/ols/"></tag> Transparents de Jamal Hadi Salim, un des auteurs du contrôleur de trafic de Linux. <tag><url url="http://defiant.coinet.com/iproute2/ip-cref/" name="http://defiant.coinet.com/iproute2/ip-cref/"></tag> Version HTML de la documentation LaTeX d'Alexeys ; explique une partie d'iproute2 en détails. <tag><url url="http://www.aciri.org/floyd/cbq.html" name="http://www.aciri.org/floyd/cbq.html"></tag> Sally Floyd a une bonne page sur CBQ, incluant ses publications originales. Aucune n'est spécifique à Linux, mais il y a un travail de discussion sur la théorie et l'utilisation de CBQ. Contenu très technique, mais une bonne lecture pour ceux qui sont intéressés. <tag><url url="http://ceti.pl/~ekravietz/cbq/NET4_tc.html" name="http://ceti.pl/~ekravietz/cbq/NET4_tc.html"></tag> Un autre HOWTO, en polonais ! Vous pouvez cependant copier/coller les lignes de commandes, elles fonctionnent de la même façon dans toutes les langues. L'auteur travaille en collaboration avec nous et sera peut être bientôt un auteur de sections de cet HOWTO. <tag><url url="http://snafu.freedom.org/linux2.2/docs/draft-almesberger-wajhak-diffserv-linux-00.txt" name="Les services différenciés sur Linux"></tag> Discussion sur l'utilisation de Linux dans un environnement compatible diffserv. Assez loin des besoins quotidiens de votre routeur, mais néanmoins très intéressant. Nous pourrons inclure une section sur le sujet, plus tard. <tag><url url="http://www.cisco.com/univercd/cc/td/doc/product/software/ios111/cc111/car.htm" name="IOS Committed Access Rate"></tag> <label id="CAR"> Des gens de Cisco qui ont pris la louable habitude de mettre leur documentation en ligne. La syntaxe de Cisco est différente mais les concepts sont identiques, sauf qu'on fait mieux, et sans matériel qui coûte autant qu'une voiture :-) <tag>TCP/IP Illustrated, volume 1, W. Richard Stevens, ISBN 0-201-63346-9</tag> Sa lecture est indispensable si vous voulez réellement comprendre TCP/IP, et de plus elle est divertissante. </descrip> <sect>Remerciements <p> Notre but est de faire la liste de tous les personnes qui ont contribué à ce HOWTO, ou qui nous ont aidés à expliquer le fonctionnement des choses. Alors qu'il n'existe pas de liste dans Netfilter, nous souhaitons saluer les personnes qui ont apporté leur aide. <itemize> <item>Ron Brinker <service%emcis.com> <item>Lennert Buytenhek <buytenh@gnu.org> <item>Esteve Camps <esteve@hades.udg.es> <item>Marco Davids <marco@sara.nl> <item>Stephan "Kobold" Gehring <Stephan.Gehring@bechtle.de> <item>Nadeem Hasan <nhasan@usa.net> <item>Koos van den Hout <koos@kzdoos.xs4all.nl> <item>Philippe Latu <philippe.latu%linux-france.org> <item>Jason Lunz <j@cc.gatech.edu> <item>Alexey Mahotkin <alexm@formulabez.ru> <item>Pawel Krawczyk <kravietz%alfa.ceti.pl> <item>Wim van der Most <item>Stephan Mueller <smueller@chronox.de> <item>Ram Narula <ram@princess1.net> <item>Jorge Novo <jnovo@educanet.net> <item>Patrik <ph@kurd.nu> <item>Jason Pyeron <jason%pyeron.com> <item>Rusty Russell (avec mes excuses pour avoir mal orthographié votre nom) <item>Jamal Hadi Salim <hadi%cyberus.ca> <item>Sheharyar Suleman Shaikh <sss23@drexel.edu> <item>Nick Silberstein <nhsilber%yahoo.com> <item>Konrads Smelkov <konrads@interbaltika.com> <item>Jason Tackaberry <tack@linux.com> <item>Charles Tassell <ctassell%isn.net> <item>Glen Turner <glen.turner%aarnet.edu.au> <item>Song Wang <wsong@ece.uci.edu> </itemize> </article>