QoS Gestion de la bande passante sous Linux
QoS/Gestion de la bande passante sous Linux
Introduction
Dans cet article, je vais vous expliquer les différentes étapes pour mettre en place la QoS et gérer votre bande passante sous Linux.
Pourquoi faire de la QoS ? Retenez que sans la QoS, vous ne pouvez pas gérer correctement les flux qui transitent sur votre réseau. Vous aurez par exemple des problèmes à écouter un flux audio en streaming sachant qu'en même temps, vous êtes en train de faire du ftp. Dans la première partie de cet article, je vais vous montrer comment prioriser les divers flux de votre réseau.
Pourquoi gérer la BP de mon réseau ? Une personne qui fait du ftp sur une ligne ADSL de bureau peut monopoliser à elle seule toute la bande passante en sortie de votre réseau. Ce cas ne se limite pas aux réseaux ADSL et peut être aussi constaté sur des réseaux à très haut débit (lignes de type T1/T2). Linux peut apporter une solution efficace face à ce genre de problème en vous offrant la possibilité de gérer intelligemment votre bande passante. Ce sera le sujet de la deuxième partie de ce présent document.
Actuellement, sachez que vous pouvez faire de la QoS et de la gestion de bande passante sous les noyaux 2.2 et 2.4. Néamoins, pour une question de facilité, je vous recommande un noyau 2.4 pour effectuer ce qui suit.
QoS via iptables
Pour faire de la QoS, nous allons modifier la valeur du champs TOS se situant dans l'en tête IP grâce à iptables. Le champ TOS est sur 4 bits :
HEXA | BINAIRE | DECIMAL | SIGNIFICATION |
0x10 | 1000 | 8 | Minimize Delay |
0x08 | 0100 | 4 | Maximize throughput |
0x04 | 0010 | 2 | Maximize reliability |
0x02 | 0001 | 1 | Minimize monetary cost |
0x00 | 0000 | Normal |
- Minimize-Delay : Améliore la réactivité des connexions en réduisant le délai (ssh, telnet, ftp contrôle, tftp, flux DNS UDP)
- Maximize-Throughput : Améliore le débit au prix d'une possible détérioration de l'interactivité de la session. Les temps de latence ne sont pas importants (ftp-data,www, transfert de zone DNS)
- Maximum-Reliability : Certitude que les données arrivent sans perte - Améliore la fiabilité (snmp, smtp)
- Minimize monetary cost : minimise le délai, meilleure rentabilité (nntp, icmp)
L'intérêt de la QoS sous Linux est très souvent associé à la priorisation de flux interactifs via iptables. Par exemple, vous ne souhaitez pas que votre session ssh soit interrompue à cause d'un utilisateur qui est en train de monopoliser la bande passante de votre réseau en downloadant une bande annonce sur internet (Il s'agit d'un cas de figure bien plus répandu qu'on ne le pense !). Nous allons ici à titre d'exemple optimiser les trafics courants avec iptables, à savoir le ftp et ssh :
iptables -A PREROUTING -t mangle -p tcp --sport ssh -j TOS --set-tos Minimize-Delay
iptables -A PREROUTING -t mangle -p tcp --sport ftp -j TOS --set-tos Minimize-Delay
# On donne un maximum de débit aux transferts ftp, peu importe la latence
iptables -A PREROUTING -t mangle -p tcp --sport ftp-data -j TOS --set-tos Maximize-Throughput
A vous d'adapter ce script suivant les services de votre réseau que vous souhaitez prioriser.
Gestion de la bande passante sous Linux
Nous abordons la deuxième partie du document. Linux utilise deux unités du contrôle de trafic pour la gestion de la bande passante :
- Les filtres qui placent le trafic dans les files d'attentes (fwmark, u32)
- Les files d'attentes qui décident des flux prioritaires (CBQ, HTB, RED, TBF, SFQ...)
Gardez en vue que le protocole TCP/IP n'a pas d'aptitude à connaître les performances d'un réseau. Il commence à envoyer des paquets, de plus en plus rapidement et quand des paquets commencent à se perdre, il ralentit. La plupart des files d'attentes fonctionnent selon le modèle suivant : elles recoivent des paquets, les positionnent en file d'attente jusqu'à un certain point, et ensuite, éliminent tout paquet qui arrive dans le cas où la file d'attente est pleine. Si on travaille en UDP, les paquets ne sont plus retransmis, si c'est du TCP, l'émetteur renverra les paquets perdus. Le débit s'en trouve alors ralenti.
Compilation du noyau
Nous allons compiler le noyau afin que celui-ci sache gérer notre BP ( = Bande Passante). Si vous avez une distribution récente, il se peut que vous n'ayez pas besoin de le compiler. Lancez un "make xconfig" sous le X dans le répertoire /usr/src/linux. Si cela ne marche pas, installez les sources du noyau (le rpm est du type kernel-src-*.rpm)
Les options
Dans la partie "Networking Options" -> "QoS and fair queuing" :
Option Noyau | Sélection à la Compilation | Définition |
QoS & fair queuing | oui | |
Netfilter | module | Network Packet Filtering |
CBQ packet scheduler | module | (Classed Based Queue) - file d'attente basée sur des classes. C'est ce type de file d'attente qui sera implémentée dans la suite du présent document |
HTB packet scheduler | module | (Hierarchical Token buckets) implémenté dans la suite du présent document - Si vous ne l'avez pas, j'explique plus bas comment avoir cette file d'attente en patchant votre noyau |
CSZ packet scheduler | module | (Clark-Shenker-Zhang) - Les flux ne sont pas limités à leur bande passante. Fournit un service garanti |
The simplest PRIO pseudoscheduler | module | |
RED queue | module | (Random Early Detect) - Anticipe les problèmes de congestion. RED élimine les paquets pour indiquer à TCP/IP de ralentir - Pour de gros débits |
SFQ queue | module | (Stochastic Fair Queuing) - Limitation basée sur le taux de transfert utilisé - Consomme peu de CPU/Mem. Rapide, peu précis. Efficace sur de gros débits - Offre un traitement sensiblement équitable de chaque classe |
TBF queue | module | Consomme peu de CPU. Limitation basée sur le taux de transfert à utiliser - Non basé sur les classes |
Ingress QDisc | module | (Queuing discipline) - Indispensable lorsque l'on souhaite utiliser les files d'attente |
QoS support | oui | |
Rate estimator | oui | |
Packet classifier API | oui | |
TC Index classifier | module | |
Routing table based classifier | module | |
Firewall based classifier | module | |
U32 classifier | module | |
Special RSVP classifier | module | |
Special RSVP classifier for IPv6 | module |
Les files d'attentes les plus importantes sont CBQ et HTB (la suite du document se base sur ces deux files d'attente). Vous n'êtes pas obligés de mettre en module les autres files d'attentes (CSZ, RED, SFQ, TBF, TEQL), cependant, cela reste toujours intéressant de les laisser en tant que module au cas où vous en auriez besoin plus tard.
Terminer la compilation
Compilez le noyau par :
- make dep
- make clean
- make bzImage
- make modules
- make modules_install
Ensuite :
Allez prendre un café
Toujours pas fini ? Retournez prendre un café... :)
cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz
cp /usr/src/linux/arch/i386/boot/System.map /boot
Modifiez /etc/lilo.conf pour prendre en compte le nouveau noyau et lancez la commande "lilo".
Assurez-vous enfin que votre station Linux comporte la commande "tc" (un "which tc" vous permettra de voir si "tc" est installé). Si vous ne l'avez pas, elle fait partie du package iproute2 (les sources sont ici et le rpm peut être téléchargé là)
Désormais, votre noyau linux implémente la gestion de bande passante. Il ne reste plus qu'à écrire un script propre à votre config, ce qui est décrit dans la suite du document.
Scripts de gestion de bande passante CBQ.init, HTB.init et wshaper.htb
Si vous souhaitez partager votre bande passante sans trop vous compliquer la vie, sachez que des scripts ont été créés afin d'optimiser votre bande passante. Dans la suite du document, je vais vous expliquer comment les mettre en place. Lisez bien la définition de chacun de ces scripts, de manière à définir celui qui vous convient le mieux.
CBQ.init : file d'attente CBQ
- convient à de petits débits
- nécessite de connaître la taille moyenne des paquets et la vitesse maximale de la connexion
- utilise le temps d'inactivité de la connexion pour calculer une approximation du débit utilisé.
HTB.init : file d'attente HTB
- convient à des gros débits
- consomme peu de ressources
- ne fait pas d'approximation en ce qui concerne le calcul du débit
- nécessite de connaitre le débit maximal de votre connexion.
Wondershaper : file d'attente HTB
- maintient une bonne réactivité pour le traffic interactif (ssh, telnet...)
- surfer sans souci lors de gros downloads
- s'assure que l'upload ne défavorise pas le download et inversement.
Remarque : Sachez que souvent, on préconise l'utilisation de files d'attentes de type HTB plutot que CBQ. Cependant, si votre distribution n'est pas très récente, il y aura pas mal de choses à réaliser pour implémenter les files d'attentes HTB sur votre station (j'explique neanmoins la démarche à suivre si vous êtes dans ce cas).
CBQ.init
Récupérez le script à l'adresse suivante :
https://sourceforge.net/projects/cbqinit
Faites un "chmod u+x CBQ.init*" afin de le rendre executable.
Copiez le script dans le répertoire /usr/bin : "cp CBQ.init-[VERSION] /usr/bin"
Créez le répertoire /etc/sysconfig/cbq qui contiendra les options de gestion de BP sur lequelles se basera le script : "mkdir /etc/sysconfig/cbq" - Si vous souhaitez placer vos fichiers de configurations CBQ ailleurs, modifiez la variable $CBQ_PATH dans le script CBQ.init afin de renseigner le nouveau chemin.
Exemples de fichiers de configurations pour le script CBQ.init :
Les fichiers de configuration doivent respecter une syntaxe précise de type cbq-CLASS_ID.name où CLASS_ID est compris en hexa entre 0002 et FFFF (pour en savoir plus, éditez le script, c'est expliqué en détail).
Exemple 1 : $CBQ_PATH/cbq-1280.My_first_shaper - vous avez 2 interfaces (eth0=LAN et eth1=INTERNET) sur votre machine et souhaitez limiter le trafic INTERNET -> LAN à 16 Ko/s
DEVICE=eth0,10Mbit,1Mbit # 10 Mbits -> debit max de votre interface eth0
RATE=128Kbit # Exprimez les valeurs en Kbit ou Mbit selon les débits spécifiés
WEIGHT=10Kbit # WEIGHT = RATE / 10
PRIO=5 # Va de 1 à 8 , 1 etant le + prioritaire (la valeur 5 est recommandée et suffisante pour prioriser un trafic spécifique)
RULE=192.168.1.0/24
Exemple 2 : $CBQ_PATH/cbq-1280.My_second_shaper - vous avez 1 interface sur votre machine (eth0-192.168.1.5) et souhaitez limiter le trafic MACHINE -> INTERNET à 16 Ko/s
DEVICE=eth0,10Mbit,1Mbit # La limite du trafic s'effectue sur l'interface 10 Mbits/s eth0
RATE=128Kbit
WEIGHT=10Kbit
PRIO=5
RULE=192.168.1.5, # Attention à la ',' cela permet de specifier qu'il s'agit d'une d'adresse source ! Ici, la limitation de BP s'applique uniquement à la machine 192.168.1.5
Exemple 3 : $CBQ_PATH/cbq-1280.My_third_shaper - vous souhaitez limiter le trafic de votre serveur web (192.168.1.50) à 8 Ko/s
DEVICE=eth0,10Mbit,1Mbit # 10 Mbits -> débit max de l'interface de votre serveur web
RATE=64Kbit # Exprimez les valeurs en Kbit ou Mbit selon les débits spécifiés
WEIGHT=6Kbit # WEIGHT = RATE / 10
PRIO=5 # Va de 1 à 8 , 1 étant le + prioritaire (la valeur 5 est recommandée et suffisante pour prioriser un trafic spécifique)
RULE=192.128.1.50:80,
Exemple 4 : $CBQ_PATH/cbq-1280.My_fourth_shaper - vous souhaitez limiter le trafic des gens qui download sur votre serveur ftp (192.168.1.50) à 10 Ko/s
DEVICE=eth0,10Mbit,1Mbit # 10 Mbits -> débit max de l'interface de votre serveur ftp
RATE=80Kbit # Exprimez les valeurs en Kbit ou Mbit selon les débits spécifiés
WEIGHT=8Kbit # WEIGHT = RATE / 10
PRIO=5 # Va de 1 à 8 , 1 étant le + prioritaire (la valeur 5 est recommandée et suffisante pour prioriser un trafic spécifique)
RULE=192.128.1.50:20/0xfffe # limitation de BP appliquée sur port 20/21
Exemple 5 : $CBQ_PATH/cbq-1280.My_fifth_shaper - vous souhaitez que le trafic LAN -> INTERNET soit limité à 50 Ko/s (400 Kbits/s), et que le trafic INTERNET -> LAN soit limité à 10Ko/s (80 Kbits/s), remplissez CBQ.init de la manière suivante :
######################## {{ LAN -> INTERNET }} ####################################
DEVICE=eth1,10Mbit,1Mbit
RATE=400Kbit
WEIGHT=40Kbit # WEIGHT = RATE / 10
PRIO=5
BOUNDED=yes # Pour ne pas aller prendre de la BP aux classes parents
ISOLATED=NO # Permet de léguer de la BP aux classes filles si il en reste
RULE=192.168.0.0/24 # Le partage de BP concerne le trafic à destination du reseau 192.168.0.0
############################################################ ############
######################## {{ INTERNET -> LAN }} ####################################
DEVICE=eth0,100Mbit,10Mbit #
RATE=80Kbit # On souhaite limiter le trafic entrant à 10 Ko/s (adaptez selon le débit de votre ligne)
WEIGHT=8Kbit # WEIGHT = RATE / 10
PRIO=5
BOUNDED=yes
ISOLATED=NO
RULE=80,192.168.1.10 # Tout le traffic HTTP INTERNET -> 192.168.1.10 limité à 10 Ko/s
#################################### ####################################
Il ne reste plus qu'à lancer le script CBQ.init à chaque démarrage ; pour cela éditez le /etc/rc.d/rc.local et ajoutez la ligne "CBQ.init-[version] start" où [version] désigne la version de votre script CBQ.
Si vous souhaitez obtenir des statistiques CBQ, lancez la commande "CBQ.init-[VERSION] stats". Le script vous sortira des informations qui peuvent s'avérer utile.
Voilà, vous êtes désormais un gourou des files d'attentes CBQ :). Passons maintenant à la gestion de la BP avec file d'attentes HTB.
HTB.init
Récupérez le script HTB.init à l'adresse suivante :http://sourceforge.net/projects/htbinit
Notes pour noyau < 2.4.18-3 : pour utiliser des files d'attentes HTB, sachez que vous devez patcher votre noyau si il est inférieur à la version 2.4.18-3 (tapez "uname -a" pour vérifier la version de votre distribution) :
http://luxik.cdi.cz/~devik/qos/htb/v2/htb2_2.4.17.diff pour les noyaux 2.4
http://luxik.cdi.cz/~devik/qos/htb/v2/htb2_2.2.17.diff pour les noyaux 2.2
Pour appliquer le patch lancez la commande suivante dans le répertoire /usr/src/linux : "patch -pl -i htb2_2.4.17.diff"
Dans /usr/src/linux tapez : "make xconfig"
Dans la partie "Networking Options" -> "QoS and fair Queuing", sélectionnez HTB packet scheduler en module
Recompilez le noyau : "make dep && make clean && make bzImage && make modules && make modules_install"
Mettez en place le nouveau noyau qui prend en charge HTB :
cp /usr/src/linux/arch/i386/bzImage /boot/vmlinuz
cp /usr/src/linux/arch/i386/boot/System.map /boot
Vous devez aussi mettre à jour la commande "tc" : http://luxik.cdi.cz/~devik/qos/htb/v2/tc.gz
Faites un "chmod u+x HTB.init-[VERSION]" afin de le rendre exécutable.
Copiez le script dans le répertoire /usr/bin : "cp HTB.init-[VERSION] /usr/bin"
Créez le répertoire /etc/sysconfig/htb qui contiendra les fichiers de gestion de BP sur lequelles se basera le script : "mkdir /etc/sysconfig/htb" - Si vous souhaitez placer vos fichiers de configurations HTB ailleurs, modifiez la variable $HTB_PATH dans le script HTB.init afin de renseigner le nouveau chemin.
Exemples de fichiers de configurations HTB.init :
Il n'existe pas un mais plusieurs fichiers de configurations pour HTB.init. Les fichiers doivent obligatoirement avoir une syntaxe précise. Par exemple :
eth0-2 -> classe root ID 2, device eth0
eth0-2:3 -> classe fille ID 3, ayant comme parent 2, device eth0
eth0-2:3:4 -> classe fille ID 4, ayant comme parent 3, device eth0
eth1-2.root -> classe root ID 2, device eth1
Remarque : Une autre notation en cas d'erreur lors de la creation de ce type de fichiers : eth0-2\:3 -> Vous placez un "\" avant le ":"
Cela peut paraître un peu confu comme syntaxe, cependant, je vais vous donner des exemples. Editez le script si vous souhaitez néanmoins en savoir plus à ce sujet.
Avec ce type de files d'attentes, vous ne pouvez realiser un contrôle de flux qu'en sortie de vos interfaces réseaux. Dans le cas d'une station qui fait du routage, configurez les débits sur les sorties des deux interfaces (voir exemple 2).
Exemple 1 :
Imaginons que vous ayez une bande passante sur votre station de 5 Mbits/s (~600Ko/s). Vous souhaitez :
5Mbits/s pour le HTTP,
3Mbits/s pour le SMTP
1Kbit/s pour le trafic divers (qui vous importent peu)
Dans le cas où il y a de la bande passante de libre, vous souhaitez la partager entre le SMTP et trafics divers.
SMTP pourra utiliser tout le temps au moins 3Mbits/s et pourra monter jusqu'à 5 Mbits/s si il y a de la BP de libre.
Le trafic divers pourra utiliser tout le temps au moins 1Kbit/s et pourra monter jusqu'à 5Mbits/s si il y a de la BP de libre.
Allez dans le répertoire /etc/sysconfig/htb ($HTB_PATH) et placez-y les lignes suivantes pour chaque fichier :
fichier eth0
DEFAULT=30 # ID class default - Le trafic non répertorié utilisera la class ID 30
fichier eth0-2.root
RATE=5Mbit # Bande passante allouée a la classe root (ici 5Mbits)
BURST=15k
fichier eth0-2:10.www
RATE=5Mbit
BURST=15k
LEAF=sfq # Type de file d'attente utilisée par cette classe (ici sfq)
RULE=*:80, # Voir les exemples du script CBQ.init - La syntaxe "RULE" est identique
fichier eth0-2:20.smtp
RATE=3Mbit
CEIL=5Mbit # La bande passante max de cette classe peut aller jusqu'a 5 Mbits/s uniquement si il y a de la BP de libre.
BURST=15k
LEAF=sfq
RULE=*:25
fichier eth0-2:30.dfl
RATE=1Kbit
CEIL=5Mbit
BURST=15k
LEAF=sfq
Exemple 2 :
On traite ici le cas d'une personne ayant une connexion ADSL de type 512/128. Sa connexion se fait via une machine-routeur possédant deux interfaces (eth0 et eth1). Elle souhaite limiter l'upload à 90 Kbits/s (11,3 Ko/s) et donner la priorité aux services HTTP, SSH, TELNET, POP3, SMTP et DNS. Une priorité plus petite sera attribuée à tout autre trafic. Côté, download on garde la même idée, cependant, la limite sera fixée à 450 Kbits/s (57 Ko/s).
Allez dans le répertoire /etc/sysconfig/htb ($HTB_PATH) et placez-y les lignes suivantes pour chaque fichier :
fichier eth1 (Tous fichier de type eth1* -> trafic sortant de l'interface eth1)
DEFAULT=30
R2Q=1
fichier eth1-2.root
#Classe root pour trafic sortant
RATE=90Kbit
fichier eth1-2\:10.high
# Classe pour trafic sortant de haute priorité
RATE=30Kbit
CEIL=prate
LEAF=sfq
#HTTP
RULE=*:80
#SSH
RULE=*:22
#TELNET
RULE=*:23
#SMTP
RULE=*:25
#DNS
RULE=*:53
#POP3
RULE=*:110
fichier eth1-2\:20.normal
# Classe pour trafic sortant normal
RATE=30kbit
CEIL=prate
LEAF=sfq
#IRC
RULE=*:6667
fichier eth1-2\:30.low
# Classe pour trafic sortant peu important
RATE=20Kbit
CEIL=prate
LEAF=sfq
#EMULE
RULE=*:3000
RULE=*:3000,
RULE=*:3010
RULE=*:3010,
RULE=*:4662 RULE=*:4662,
fichier eth0 (Tous fichier de type eth0* -> trafic sortant de l'interface eth0)
DEFAULT=30
R2Q=10
fichier eth0-2\:10.high
# Classe pour trafic sortant de haute priorité
RATE=150 Kbit
CEIL=prate
LEAF=sfq
#HTTP
RULE=*:80,
#SSH
RULE=*:22,
#TELNET
RULE=*:23,
#SMTP
RULE=*:25,
#DNS
RULE=*:53,
#POP3
RULE=*:110,
fichier eth0-2\:20.normal
# Classe pour trafic sortant normal
RATE=30kbit
CEIL=prate
LEAF=sfq
#IRC
RULE=*:6667,
fichier eth0-2\:30.low
# Classe pour trafic sortant peu important
RATE=150Kbit
CEIL=prate
LEAF=sfq
#EMULE
RULE=*:3000,
RULE=*:3010,
RULE=*:4662,
RULE=*:3000
RULE=*:3010
RULE=*:4662
RULE=*:4662
RULE=*:4662,
Il ne reste plus qu'à lancer le script HTB.init à chaque démarrage ; pour cela éditez le /etc/rc.d/rc.local et ajoutez la ligne "HTB.init-[version] start" où [VERSION] désigne la version de votre script HTB.
Si vous souhaitez obtenir des statistiques HTB, lancez la commande "HTB.init-[VERSION] stats". Le script vous sortira des informations qui peuvent s'avérer utile.
wondershaper
Récupérez wondershaper à l'adresse suivante :
Editez le script wshaper et indiquez les débits ; par exemple pour une ligne ADSL 512/128 :
DOWNLINK= 500
UPLINK= 100
DEV=ppp0
Désormais, votre machine avec ce script :
- maintient une bonne réactivité pour le trafic interactif (ssh, telnet...)
- vous pouvez surfer sans soucis lors de gros downloads
- l'upload ne défavorise pas le download et inversement.
J'ai trouvé sur internet un script dérivé de Wondershaper, il peut s'avérer intéressant de le mettre en oeuvre si vous avez une connexion de type ADSL. En revanche, ce script fait appel à de nombreuses files d'attentes : CBQ, RED, IMQ, HTB et SFQ (Assurez-vous au préalable que votre noyau les prend toutes en compte).
#
# mon_limiteur - Limiteur et classificateur de trafic pour modem Cable ou ADSL.
# Inspiré de WonderShaper (www.lartc.org)
#
# Écrit par Dan Singletary (7/8/02)
#
# Remarque - ce script suppose que le noyau a été patché avec les files
# HTB et IMQ disponibles ici (les noyaux à venir ne demanderont
# pas forcément l'application d'un correctif):
# http://luxik.cdi.cz/~devik/qos/htb/
# http://luxik.cdi.cz/~patrick/imq/
#
# Options de configuration pour mon_limiteur:
# DEV - correspond au périphérique ethX connecté au modem
# RATEUP - à positionner à une valeur inférieure à la bande
# passante montante de la ligne.
# Pour ma ligne ADSL en 1500/128, RATEUP=90 convient au rythme
# montant de 128 kbps. À vous d'ajuster.
# RATEDN - à positionner en dessous de la bande passante descendante de
# la ligne.
#
#
# Principe d'utilisation d'imq pour limiter le trafic entrant:
#
# Il est impossible de limiter directement le rythme auquel les
# données vous sont envoyées depuis l'Internet. Afin de limiter le
# trafic entrant, on s'appuie sur les mécanismes anti-congestion de
# TCP. Ceci signifie que SEUL LE TRAFIC TCP PEUT SE LIMITER. Le
# trafic hors TCP est placé dans une queue prioritaire car le jeter
# ne conduit vraisemblablement qu'à une retransmission ultérieure
# qui accroît la bande passante consommée.
# On limite le trafic TCP en jetant les paquets lorsqu'ils débordent
# de la file HTB qui les limitera à un certain rythme (RATEDN)
# légèrement inférieur à la capacité réelle de la ligne. Jeter ces
# paquets revient à en singer la perte par la file d'émission du
# côté du FAI. Ceci a l'avantage d'éviter la congestion de la file
# d'émission chez le FAI puisque TCP ralentira avant qu'elle ne
# se remplisse. L'usage d'une stratégie de mise en attente basée sur
# la classification des paquets par priorité permet de ne PAS jeter
# certains types de paquets (ssh, telnet, etc). Les paquets ne sont
# retirés des files d'attente de faible priorité qu'une fois que
# chaque classe a atteint un seuil minimum (1/7 de la bande passante
# dans ce script).
#
# Résumé:
# * La perte d'un paquet TCP diminue le rythme de réception de la
# connexion associée via les mécanismes de contrôle de congestion.
# * Jeter des paquets TCP n'apporte rien. S'ils sont importants, ils
# seront retransmis.
# * Limiter le rythme des connexions TCP entrantes en dessous de la
# capacité de la ligne DEVRAIT éviter la mise en attente des paquets
# du côté du FAI (DSLAM, concentrateur de cables, etc). L'expérience
# indique que ces files contiennent 4 secondes de trafic à 1500 kbps,
# soit 6 Mb de données. À ce niveau, l'absence de mise en attente
# diminue la latence.
#
# Avertissements:
# * Est-ce que la limitation de bande passante diminue l'efficacité de
# transferts TCP massifs ?
# - Apparemment non. L'augmentation de priorité des paquets
# d'acquittement maximise le débit en évitant de perdre de la bande
# passante à retransmettre des paquets déjà reçus.
#
# NOTE: La configuration ci-dessous fonctionne avec ma connexion ADSL
# 1.5M/128K via Pacific Bell Internet (SBC Global Services)
DEV=eth0
RATEUP=90
RATEDN=700 # Nettement inférieur à la capacité de la ligne de 1500.
# On n'a donc pas à limiter le trafic entrant jusqu'à ce
# qu'une meilleure réalisation telle que la modification
# de fenêtre TCP soit disponible.
#
# Fin des options de configuration
#
if [ "$1" = "status" ]
then
echo "[qdisc]"
tc -s qdisc show dev $DEV
tc -s qdisc show dev imq0
echo "[class]"
tc -s class show dev $DEV
tc -s class show dev imq0
echo "[filter]"
tc -s filter show dev $DEV
tc -s filter show dev imq0
echo "[iptables]"
iptables -t mangle -L MONLIMITEUR-OUT -v -x 2> /dev/null
iptables -t mangle -L MONLIMITEUR-IN -v -x 2> /dev/null
exit
fi
# Remise à zéro
tc qdisc del dev $DEV root 2> /dev/null > /dev/null
tc qdisc del dev imq0 root 2> /dev/null > /dev/null
iptables -t mangle -D POSTROUTING -o $DEV -j MONLIMITEUR-OUT 2> /dev/null > /dev/null
iptables -t mangle -F MONLIMITEUR-OUT 2> /dev/null > /dev/null
iptables -t mangle -X MONLIMITEUR-OUT 2> /dev/null > /dev/null
iptables -t mangle -D PREROUTING -i $DEV -j MONLIMITEUR-IN 2> /dev/null > /dev/null
iptables -t mangle -F MONLIMITEUR-IN 2> /dev/null > /dev/null
iptables -t mangle -X MONLIMITEUR-IN 2> /dev/null > /dev/null
ip link set imq0 down 2> /dev/null > /dev/null
rmmod imq 2> /dev/null > /dev/null
if [ "$1" = "stop" ]
then
echo "Limitation de débit désactivée sur $DEV."
exit
fi
###########################################################
#
# Limitation de trafic sortant (limite supérieure à RATEUP)
# positionnement de la taille de la file d'émission pour obtenir
# une latence d'environ 2 secondes pour les paquets de la file
# de faible priorité.
ip link set dev $DEV qlen 30
# modification de MTU du périphérique sortant.
# - Diminuer la MTU abaisse la latence mais dégrade le débit en raison de
# la surcharge IP et TCP.
ip link set dev $DEV mtu 1000
# ajout de la stratégie HTB
tc qdisc add dev $DEV root handle 1: htb default 26
# ajout de la classe de limitation principale
tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit
# ajout des classes filles:
# - chaque classe dispose AU MOINS de son quota de bande passante. Aucune
# classe n'est donc étouffée par les autres. Chaque classe peut également
# consommer toute la bande passante si aucune autre classe ne l'emploie.
tc class add dev $DEV parent 1:1 classid 1:20 htb rate $[$RATEUP/7]kbit \
ceil ${RATEUP}kbit prio 0
tc class add dev $DEV parent 1:1 classid 1:21 htb rate $[$RATEUP/7]kbit \
ceil ${RATEUP}kbit prio 1
tc class add dev $DEV parent 1:1 classid 1:22 htb rate $[$RATEUP/7]kbit \
ceil ${RATEUP}kbit prio 2
tc class add dev $DEV parent 1:1 classid 1:23 htb rate $[$RATEUP/7]kbit \
ceil ${RATEUP}kbit prio 3
tc class add dev $DEV parent 1:1 classid 1:24 htb rate $[$RATEUP/7]kbit \
ceil ${RATEUP}kbit prio 4
tc class add dev $DEV parent 1:1 classid 1:25 htb rate $[$RATEUP/7]kbit \
ceil ${RATEUP}kbit prio 5
tc class add dev $DEV parent 1:1 classid 1:26 htb rate $[$RATEUP/7]kbit \
ceil ${RATEUP}kbit prio 6
# ajout de la stratégie aux classes filles
# - SFQ offre un traitement sensiblement équitable de chaque classe.
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev $DEV parent 1:21 handle 21: sfq perturb 10
tc qdisc add dev $DEV parent 1:22 handle 22: sfq perturb 10
tc qdisc add dev $DEV parent 1:23 handle 23: sfq perturb 10
tc qdisc add dev $DEV parent 1:24 handle 24: sfq perturb 10
tc qdisc add dev $DEV parent 1:25 handle 25: sfq perturb 10
tc qdisc add dev $DEV parent 1:26 handle 26: sfq perturb 10
# répartition du trafic en classe via fwmark
# - le trafic est réparti en classes de priorité suivant l'indicateur
# fwmark des paquets (ceux-ci sont positionnés avec iptables un peu plus
# loin). La classe de priorité par défaut a été mise à 1:26 de telle sorte
# que les paquets qui ne sont pas marqués se retrouvent dans la classe de
# priorité la plus faible.
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 24 fw flowid 1:24
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 25 fw flowid 1:25
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 26 fw flowid 1:26
# ajout de MONLIMITEUR-OUT à la table de modification des paquets d'iptables
# - ceci déclare la table employée pour filtrer et classer les paquets
iptables -t mangle -N MONLIMITEUR-OUT
iptables -t mangle -I POSTROUTING -o $DEV -j MONLIMITEUR-OUT
# ajout de fwmark pour classer les différents types de trafic
# - fwmark est positionné de 20 à 26 suivant la classe. 20 correspond à la
# priorité la plus forte.
# Trafic sur les ports bas
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --sport 0:1024 -j MARK --set-mark 23
# Trafic sur les ports bas
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport 0:1024 -j MARK --set-mark 23
# Port ftp-data, faible priorité
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport 20 -j MARK --set-mark 26
# Messagerie Immédiate AOL
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport 5190 -j MARK --set-mark 23
# ICMP (ping) - forte priorité (impressionnez vos amis)
iptables -t mangle -A MONLIMITEUR-OUT -p icmp -j MARK --set-mark 20
# DNS (petits paquets)
iptables -t mangle -A MONLIMITEUR-OUT -p udp -j MARK --set-mark 21
# shell sécurisé
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport ssh -j MARK --set-mark 22
# shell sécurisé
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --sport ssh -j MARK --set-mark 22
# telnet (hum ...)
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport telnet -j MARK --set-mark 22
# telnet (hum ...)
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --sport telnet -j MARK --set-mark 22
# IPSec - la surcharge n'est pas connue ...
iptables -t mangle -A MONLIMITEUR-OUT -p ipv6-crypt -j MARK --set-mark 24
# Serveur WWW local
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --sport http -j MARK --set-mark 25
# Petits paquets (des ACK probablement)
iptables -t mangle -A MONLIMITEUR-OUT -p tcp -m length --length :64 -j MARK --set-mark 21
# Répétition - on marque les paquets restants à 26 (faible priorité)
iptables -t mangle -A MONLIMITEUR-OUT -m mark --mark 0 -j MARK --set-mark 26
# Fin de la limitation sortante
#
####################################################
echo "Limitation de trafic sortant activé sur $DEV. Débit: ${RATEUP}kbit/sec."
# Décommenter la ligne suivante pour n'avoir que la limitation de trafic montant.
# exit
#################################################### #
# Limitation du trafic entrant (débit maximal de RATEDN)
# on force le chargement du module imq
modprobe imq numdevs=1
ip link set imq0 up
# ajout de la stratégie de mise en file d'attente
# - par défaut une classe 1:21 à faible priorité
tc qdisc add dev imq0 handle 1: root htb default 21
# ajout de la classe de limitation principale
tc class add dev imq0 parent 1: classid 1:1 htb rate ${RATEDN}kbit
# ajout des classes filles
# - trafic TCP en 21, le reste en 20
#
tc class add dev imq0 parent 1:1 classid 1:20 htb rate $[$RATEDN/2]kbit \
ceil ${RATEDN}kbit prio 0
tc class add dev imq0 parent 1:1 classid 1:21 htb rate $[$RATEDN/2]kbit \
ceil ${RATEDN}kbit prio 1
# ajout de la stratégie de limitation aux classes filles
# - voir les remarques ci-dessus sur SFQ.
tc qdisc add dev imq0 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev imq0 parent 1:21 handle 21: red limit 1000000 \
min 5000 max 100000 avpkt 1000 burst 50
# répartition du trafic en classe via fwmark
# - le trafic est réparti en classes de priorité suivant l'indicateur
# fwmark des paquets (ceux-ci sont positionnés avec iptables un peu plus
# loin). La classe de priorité par défaut à été mise à 1:26 de telle sorte
# que les paquets qui ne sont pas marqués se retrouvent dans la classe de
# priorité la plus faible.
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
# ajout de MONLIMITEUR-IN à la table de modification des paquets d'iptables
iptables -t mangle -N MONLIMITEUR-IN
iptables -t mangle -I PREROUTING -i $DEV -j MONLIMITEUR-IN
# ajout de fwmark pour classer les différents types de trafic
# - fwmark est positionné de 20 à 21 suivant la classe. 20 correspond à la
# priorité la plus forte.
# Forte priorité pour les paquets non TCP
iptables -t mangle -A MONLIMITEUR-IN -p ! tcp -j MARK --set-mark 20
# Les petits paquets TCP sont probablement des ACK
iptables -t mangle -A MONLIMITEUR-IN -p tcp -m length --length :64 -j MARK --set-mark 20
# shell sécurisé
iptables -t mangle -A MONLIMITEUR-IN -p tcp --dport ssh -j MARK --set-mark 20
# shell sécurisé
iptables -t mangle -A MONLIMITEUR-IN -p tcp --sport ssh -j MARK --set-mark 20
# telnet (hum ...)
iptables -t mangle -A MONLIMITEUR-IN -p tcp --dport telnet -j MARK --set-mark 20
# telnet (hum ...)
iptables -t mangle -A MONLIMITEUR-IN -p tcp --sport telnet -j MARK --set-mark 20
# Répétition - les paquets sans marque sont positionnés à 21 (faible priorité)
iptables -t mangle -A MONLIMITEUR-IN -m mark --mark 0 -j MARK --set-mark 21
# on envoie les paquets précédents à l'interface imq0.
iptables -t mangle -A MONLIMITEUR-IN -j IMQ
# Fin de la limitation de trafic entrant.
#
####################################################
echo "Limitation de trafic entrant activée sur $DEV. Débit: ${RATEDN}kbit/sec."
Script de visualisation des files d'attentes
Le script suivant visualise les files d'attentes :
echo 'Qdisc'
tc -s qdisc show dev eth0
echo 'Classes'
tc -s class show dev eth0
echo 'Filter'
tc -s filter show dev eth0
Conclusion
J'ai essayé à travers cet article de vous ammener un maximum de renseignements, cependant, je n'ai pas la prétention d'en faire un document référence (il y a l'excellent HOWTO QoS pour cela). Toutes les remarques sont les bienvenues, il serait intéressant de faire évoluer ce présent document avec les commentaires que vous y apporterez. Si vous avez des scripts HTB.init, ou CBQ.init perso, n'hesitez pas à me les envoyer, je les rajouterai dans cet article.
Pour me contacter : guitarparts@fr.st
Copyright
Copyright © 25/05/2003, Julien Lecubin
Ce document est publié sous licence Creative Commons Attribution, Partage à l'identique, Contexte non commercial 2.0 : http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ |