logo
 Accueil  Articles  Cours  Guides  Formation  Téléchargement  Source
 
Contactmail
 Carnet de bord
 Notice légale
HOWTO du routage avancé et du contrôle de trafic sous Linux: Recettes de cuisine Page suivante Page précédente Table des matières

15. Recettes de cuisine

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.

15.1 Faire tourner plusieurs sites avec différentes SLA (autorisations)

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.

# ip address add 188.177.166.1 dev eth0
# ip address add 188.177.166.2 dev eth0



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 :

# tc qdisc add dev eth0 root handle 1: cbq bandwidth 10Mbit cell 8 avpkt 1000 \
  mpu 64



Nous créons ensuite les classes pour nos clients :

# 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



Nous ajoutons les filtres pour nos deux classes :

##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



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 ?

15.2 Protéger votre machine des inondations SYN

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 est nécessaire pour que ceci fonctionne avec le noyau 2.4.0.

#! /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



15.3 Limiter le débit ICMP pour empêcher les dénis de service

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.

La limitation de débit peut faire encore mieux, comme vu plus haut. Pour vous rafraîchir la mémoire, revoici notre diagramme ASCII :

[Internet] ---<E3, T3, n'importe quoi>--- [routeur Linux] --- [Bureau+FAI]
                                         eth1          eth0



Nous allons d'abord configurer les parties pré-requises :

# 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



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 :

# 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



Cela limite le débit à 100 Kbits sur la classe. Maintenant, nous avons besoin d'un filtre pour assigner le trafic ICMP à cette classe :

# tc filter add dev eth0 parent 10:0 protocol ip prio 100 u32 match ip
  protocol 1 0xFF flowid 10:100



15.4 Donner la priorité au trafic interactif

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 :

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.


L'utilisation la plus commune est de configurer les connexions telnet et ftp à "Délai Minimum" et les données FTP à "Débit Maximum". Cela serait fait comme suit, sur mon routeur :

# 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



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 :

# 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



15.5 Cache web transparent utilisant netfilter, iproutes2, ipchains et 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.

La passerelle le fait.

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.

MAIS

Ceci amènerait une charge supplémentaire sur le routeur et des routeurs commerciaux peuvent même ne pas supporter ceci.

Utiliser un commutateur Couche 4.

Les commutateurs Couche 4 peuvent manipuler ceci sans aucun problème.

MAIS

Le coût pour un tel équipement est en général très élevé. Typiquement, un commutateur couche 4 coûte normalement plus cher qu'un serveur classique + un bon serveur linux.

Utiliser le serveur cache comme passerelle réseau

Vous pouvez forcer TOUT le trafic à travers le serveur cache

MAIS

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.

Routeur Linux+NetFilter.

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.

|----------------|
| 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.

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.

(Tous les serveurs sur mon réseau avaient 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.)

Silom
-----
-configurer squid et ipchains 



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 redirigé localement vers le port 3128. Ceci peut être fait en utilisant ipchains comme suit :

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



Ou, avec netfilter:

silom# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128



(note: vous pouvez avoir également d'autres entrées)

Pour plus d'informations sur la configuration du serveur Squid, se référer à la page FAQ Squid sur http://squid.nlanr.net).

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).

Naret
-----
- configurer squid et ipchains 
- désactiver les messages icmp REDIRECT (si besoin)



  1. "Marquer" les paquets à destination du port 80 avec la valeur 2
     
    naret# iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 80 \
     -j MARK --set-mark 2
    
    
  2. Configurer iproute2 de sorte qu'il route les paquets avec la marque 2 vers silom
    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
    
    

    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 :

    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
    
    




La configuration est terminée, vérifions-la.

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 appartiens à l'une des lignes ci-dessus. Dans ce cas,
c'est la ligne avec 10.0.0.0/24)

|------|
|-FAIT-|
|------|




Schéma du trafic après l'implémentation


|---------------------------------------|
|Schéma du trafic après l'implémentation|
|---------------------------------------|

INTERNET
/\
||
\/
-----------------routeur donmuang---------------------
/\                                      /\         ||
||                                      ||         ||
||                                      \/         ||
naret                                  silom       ||
*trafic à destination du port 80=====>(cache)      ||
/\                                      ||         ||
||                                      \/         \/
\\===================================kaosarn, RAS, etc.



Noter que le réseau est asymétrique car il y a un saut supplémentaire sur le chemin sortant.

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



15.6 Circonvenir aux problèmes de la découverte du MTU de chemin en configurant un MTU par routes

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 entraîner 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 connexion.

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 rejeter le paquet. L'hôte émetteur prend acte de cette indication en envoyant des paquets plus petits et, par itération, peut trouver la taille optimum du paquet pour une connexion à 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équence, 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'aie pas de preuves de ceci, deux sites avec qui j'avais l'habitude d'avoir des problèmes faisaient 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.

Solution

Quand vous rencontrez des sites qui présentent ce problème, vous pouvez désactiver la découverte du MTU de chemin en le configurant manuellement. Koos van den Hout a peu près écrit :

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'une touche intervient dans un délai raisonnable.

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 de 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 recevais 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 :

ip route add default via 10.0.0.1 mtu 296



(10.0.0.1 étant ma passerelle par défaut, l'adresse interne de mon routeur masquant)



En général, il est possible 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 :

ip route add 195.96.96.0/24 via 10.0.0.1 mtu 1000



15.7 Circonvenir aux problèmes de la découverte du MTU de chemin en imposant le MSS (pour les utilisateurs de l'ADSL, du câble, de PPPoE & PPtP)

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 possibilité 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 :

# iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS  --clamp-mss-to-pmtu



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 :

# iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 128



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.

15.8 Le Conditionneur de Trafic Ultime : Faible temps de latence, Téléchargement vers l'amont et l'aval rapide

Note : Ce script a récemment été mis à niveau et il ne marchait avant qu'avec les clients Linux de votre réseau ! Vous devriez donc le mettre à jour si vous avez des machines Windows ou des Macs dans votre réseau qui n'était pas capables de télécharger plus rapidement pendant que d'autres étaient en train de télécharger vers l'amont.

J'ai essayé de créer le Saint Graal :

Maintenir à tout moment un faible temps de latence pour le trafic interactif

Ceci signifie que la récupération ou la transmission de fichiers ne doivent pas perturber SSH ou même telnet. Ceci est la chose la plus importante, car même un temps de latence de 200ms est important pour pouvoir travailler confortablement.

Autoriser le 'surf' à des vitesses résonnables pendant que l'on télécharge vers l'amont ou vers l'aval

Même si http est une trafic de masse, les autres trafics ne doivent pas trop le noyer.

être sûr que le téléchargement vers l'amont ne va pas faire du tort aux téléchargements vers l'aval et aux autres éléments autour

Le principal phénomène observé est la forte réduction de la vitesse de téléchargement vers l'aval quand il y a du trafic montant.

Il s'avère que tout ceci est possible, au prix d'une minuscule réduction de la bande passante. La présence de grandes files d'attente sur les dispositifs d'accès domestiques, comme le câble ou les modems DSL, explique pourquoi les téléchargements vers l'amont, vers l'aval et ssh se pénalisent mutuellement.

La prochaine partie explique en profondeur ce qui provoque les retards, et comment nous pouvons les corriger. Vous pouvez sans danger la passer et aller directement au script si vous vous fichez de la façon dont la magie opère.

Pourquoi cela ne marche t-il pas bien par défaut ?

Les FAI savent que leurs performances ne sont seulement jugées que sur la vitesse à laquelle les personnes peuvent télécharger vers l'aval. En plus de la bande passante disponible, la vitesse de téléchargement est lourdement influencée par la perte des paquets, qui géne sérieusement les performances de TCP/IP. Les grandes files d'attente peuvent aider à prévenir la perte des paquets, et augmenter les téléchargements. Les FAI configurent donc de grandes files d'attente.

Ces grandes files d'attente endommagent cependant l'interactivité. Une frappe doit d'abord parcourir la file d'attente du flux montant, ce qui peut prendre plusieurs secondes, et aller jusqu'au hôte distant. Elle est alors traitée, conduisant à un paquet de retour qui doit traverser la file d'attente du flux descendant, localisée chez votre FAI, avant qu'elle n'apparaise sur l'écran.

Cet HOWTO nous enseigne plusieurs manières pour modifier et traiter la file d'attente mais, malheusement, toutes les files d'attente ne nous sont pas accessibles. Les files d'attente du FAI sont sans limites et la file d'attente du flux montant réside probablement dans votre modem câble ou votre périphérique DSL. Il se peut que vous soyiez capable ou non de le configurer. La plupart du temps, ce ne sera pas le cas.

Et après ? Etant donné que nous ne pouvons pas contrôler ces files d'attente, elles doivent disparaître et être transférée sur notre routeur Linux. Heureusement, ceci est possible.

Limiter la vitesse de téléchargement vers l'amont (upload)

En limitant notre vitesse de téléchargement vers l'amont à une vitesse légèrement plus faible que la vitesse réelle disponible, il n'y a pas de files d'attente mises en place dans notre modem. La file d'attente est maintenant transférée vers Linux.

Limiter la vitesse de téléchargement vers l'aval (download)

Ceci est légèrement plus rusé dans la mesure où nous ne pouvons pas vraiment influencer la vitesse à laquelle Internet nous envoie les données. Nous pouvons cependant rejetter les paquets qui arrivent trop vite, ce qui provoque le ralentissement de TCP/IP jusqu'au débit désiré. Parceque que nous ne voulons pas supprimer inutilement du trafic, nous configurons une vitesse de rafale ('burst') plus grande.



Maintenant que nous avons fait ceci, nous avons éliminé totalement la file d'attente du flux descendant (sauf pour de courtes rafales de données), et obtenu la possibilité de gérer la file d'attente du flux montant avec toute la puissance Linux.

Il nous reste à nous assurer que le trafic interactif se retrouve au début de la file d'attente du flux montant. Pour être sûr que le flux montant ne va pas pénaliser le flux descendant, nous déplaçons également les paquets ACK au début de la file d'attente. C'est ce qui provoque normalement un énorme ralentissement quand du trafic de masse est généré dans les deux sens. Les paquets ACK du trafic descendant rentrent en concurrence avec le trafic montant et sont donc ralentis.

Si nous avons fait tout ceci, nous obtenons les mesures suivantes en utilisant l'excellente connexion ADSL de xs4all, en Hollande :

Temps de latence de base :
round-trip min/avg/max = 14.4/17.1/21.7 ms

Sans le conditionneur de trafic, lors d'un télechargement vers l'aval :
round-trip min/avg/max = 560.9/573.6/586.4 ms

Sans le conditionneur de trafic, lors d'un télechargement vers l'amont :
round-trip min/avg/max = 2041.4/2332.1/2427.6 ms

Avec le conditionneur, lors d'un télechargement vers l'amont à 220kbit/s :
With conditioner, during 220kbit/s upload:
round-trip min/avg/max = 15.7/51.8/79.9 ms

Avec le conditionneur, lors d'un télechargement vers l'aval à 850kbit/s :
round-trip min/avg/max = 20.4/46.9/74.0 ms

Lors d'un téléchargement vers l'amont, les téléchargement vers l'aval s'effectue à environ
80 % de la vitesse maximale disponible et 90% pour les téléchargements vers
l'amont. Le temps de latence augmente alors jusqu'à 850 ms ; je n'ai pas encore
déterminé la raison de ce phénomène.


Ce que vous pouvez attendre de ce script dépend largement de votre vitesse de lien réelle. Quand vous téléchargez vers l'amont à pleine vitesse, il y aura toujours un paquet devant votre frappe de clavier. Ceci est la limite basse de votre temps de latence. Pour la calculer, divisez votre MTU par la vitesse du flux montant. Les valeurs classiques seront un peu plus élevées que ca. Diminuez votre MTU pour un meilleur effet !

Voici deux versions de ce script, une avec l'excellent HTB de Devik, et l'autre avec CBQ qui est présent dans chaque noyau Linux, contrairement à HTB. Les deux ont été testés et marchent correctement.

Le script (CBQ)

Marche avec tous les noyaux. A l'intérieur du gestionnaire de mise en file d'attente CBQ, nous plaçons deux SFQ pour être sûr que de multiples flux de masse ne vont pas mutuellement se pénaliser.

Le trafic descendant est réglementé en utilisant un filtre tc contenant un Token Bucket Filter.

Vous pourriez amélioré ce script en ajoutant 'bounded' aux lignes qui démarrent avec 'tc class add .. classid 1:20'. Si vous avez diminué votre MTU, diminuez aussi les nombres allot & avpkt !

#!/bin/bash 

# La configuration ultime pour votre connexion Internet domestique
# 
# Configurez les valeurs suivantes avec des valeurs légèrement inférieures que 
# vos vitesses de flux montant et descendant. Exprimé en kilobits.
DOWNLINK=800
UPLINK=220
DEV=ppp0

# Nettoie les gestionnaires de sortie et d'entrés, cache les erreurs
tc qdisc del dev $DEV root    2> /dev/null > /dev/null
tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null

###### Flux montant (uplink)

# installe CBQ à la racine

tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 10mbit 

# Le trafic est mis en forme à une vitesse de $UPLINK. Ceci évite
# d'énormes files d'attente dans votre modem DSL qui pénalisent le temps de
# latence.
# Classe principale

tc class add dev $DEV parent 1: classid 1:1 cbq rate ${UPLINK}kbit \
allot 1500 prio 5 bounded isolated 

# classe de priorité supérieure 1:10:

tc class add dev $DEV parent 1:1 classid 1:10 cbq rate ${UPLINK}kbit \
   allot 1600 prio 1 avpkt 1000

# la classe par défaut et pour le trafic de masse 1:20. Reçoit légèrement
# moins que le trafic et a une priorité plus faible :
# bulk and default class 1:20 - gets slightly less traffic, 
#  and a lower priority:

tc class add dev $DEV parent 1:1 classid 1:20 cbq rate $[9*$UPLINK/10]kbit \
   allot 1600 prio 2 avpkt 1000

# Les deux sont gérées par SFQ :
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10

# Démarrage des filtres
# le bit Délai Minimum du champ TOS (ssh, PAS scp) est dirigé vers
# 1:10 :
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \
      match ip tos 0x10 0xff  flowid 1:10
# ICMP (ip protocol 1) est dirigé vers la classe interactive 1:10 de telle
# sorte que nous pouvons réaliser des mesures et impressionner nos
# amis :
tc filter add dev $DEV parent 1:0 protocol ip prio 11 u32 \
        match ip protocol 1 0xff flowid 1:10

# Pour accélérer les téléchargements vers l'aval lors de la présence d'un
# flux montant, les paquets ACK sont placés dans la classe
# interactive :

tc filter add dev $DEV parent 1: protocol ip prio 12 u32 \
   match ip protocol 6 0xff \
   match u8 0x05 0x0f at 0 \
   match u16 0x0000 0xffc0 at 2 \
   match u8 0x10 0xff at 33 \
   flowid 1:10

# Le reste est considéré 'non-interactif' cad 'de masse' et fini dans 1:20

tc filter add dev $DEV parent 1: protocol ip prio 13 u32 \
   match ip dst 0.0.0.0/0 flowid 1:20

########## Flux descendant (downlink) #############
# Ralentir le flux descendant à une valeur légèrement plus faible que votre
# vitesse rélle de manière à éviter la mise en file d'attente chez notre
# FAI. Faites des tests pour voir la vitesse maximum à laquelle vous pouvez
# le configurer. Les FAI ont tendance à avoir *d'énormes* files d'attente
# pour s'assurer de la rapidité des gros téléchargements.
#
# attache la réglementation d'entrée (ingress policer) :

tc qdisc add dev $DEV handle ffff: ingress

# Filtre *tout* (0.0.0.0/0), rejette tout ce qui arrive trop
# rapidement :

tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \
   0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1
Si vous voulez que ce script soit exécuté par ppp à la connexion, copiez-le dans /etc/ppp/ip-up.d.

Si les deux dernières lignes conduisent à une erreur, mettez à jour l'outil tc avec la dernière version !

Le script (HTB)

Le script suivant nous permet d'atteindre tous nos buts en utilisant la merveilleuse file d'attente HTB. Voir la chapitre correspondant. Cela vaut la peine de mettre à jour votre noyau !

#!/bin/bash

# La configuration ultime pour votre connexion Internet domestique
# 
# Configurez les valeurs suivantes avec des valeurs légèrement inférieures que 
# vos vitesses de flux montant et descendant. Exprimé en kilobits.
DOWNLINK=800
UPLINK=220
DEV=ppp0

#Nettoie les gestionnaires de sortie et d'entrés, cache les erreurs
tc qdisc del dev $DEV root    2> /dev/null > /dev/null
tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null

###### Flux montant (uplink)

# installe HTB à la racine, le trafic ira par défaut vers 1:20 :

tc qdisc add dev $DEV root handle 1: htb default 20

# Le trafic est mis en forme à une vitesse de $UPLINK. Ceci évite
# d'énormes files d'attente dans votre modem DSL qui pénalisent le temps de
# latence.

tc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK}kbit burst 6k

# la classe de haute priorité 1:10 :

tc class add dev $DEV parent 1:1 classid 1:10 htb rate ${UPLINK}kbit \
   burst 6k prio 1

# bulk & default class 1:20 - gets slightly less traffic, 
# and a lower priority:

tc class add dev $DEV parent 1:1 classid 1:20 htb rate $[9*$UPLINK/10]kbit \
   burst 6k prio 2

# Les deux sont gérées par SFQ :
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10

# le bit Délai Minimum du champ TOS (ssh, PAS scp) est dirigé vers
# 1:10 :
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \
      match ip tos 0x10 0xff  flowid 1:10

# ICMP (ip protocol 1) est dirigé vers la classe interactive 1:10 de telle
# sorte que nous pouvons réaliser des mesures et impressionner nos
# amis :
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \
        match ip protocol 1 0xff flowid 1:10

# Pour accélérer les téléchargements vers l'aval lors de la présence d'un
# flux montant, les paquets ACK sont placés dans la classe
# interactive :

tc filter add dev $DEV parent 1: protocol ip prio 10 u32 \
   match ip protocol 6 0xff \
   match u8 0x05 0x0f at 0 \
   match u16 0x0000 0xffc0 at 2 \
   match u8 0x10 0xff at 33 \
   flowid 1:10

# Le reste est considéré 'non-interactif' cad 'de masse' et fini dans 1:20


########## Flux descendant (downlink) #############
# Ralentir le flux descendant à une valeur légèrement plus faible que votre
# vitesse rélle de manière à éviter la mise en file d'attente chez notre
# FAI. Faites des tests pour voir la vitesse maximum à laquelle vous pouvez
# le configurer. Les FAI ont tendance à avoir *d'énormes* files d'attente
# pour s'assurer de la rapidité des gros téléchargements.
#
# attache la réglementation d'entrée (ingress policer) :

tc qdisc add dev $DEV handle ffff: ingress

# Filtre *tout* (0.0.0.0/0), rejette tout ce qui arrive trop
# rapidement :

tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \
   0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1
Si vous voulez que ce script soit exécuté par ppp à la connexion, copiez-le dans /etc/ppp/ip-up.d.

Si les deux dernières lignes conduisent à une erreur, mettez à jour l'outil tc avec la dernière version !


Page suivante Page précédente Table des matières
Dernière modification le : 4 March 2002 12:04
php logo    debian logo