Linux Traffic Control (tc) : un guide pratique
12 min de lecture - 5 juin 2026

Contrôlez la bande passante, priorisez le trafic et façonnez les entrées et sorties sur Linux avec tc. Configuration HTB, IFB, DSCP et fq_codel pour de vrais serveurs.
Contrôle du trafic sous Linux (tc) : un guide pratique
La commande tc vous permet de contrôler directement la manière dont votre serveur gère le trafic réseau. Vous pouvez limiter la bande passante par service, maintenir la réactivité des sessions interactives comme SSH en cas de pics de transferts en masse, et réguler les flux sortants et entrants à partir d’un seul outil. Ce guide couvre les concepts fondamentaux, une configuration HTB fonctionnelle, la régulation des flux entrants avec IFB, la priorisation basée sur le DSCP, et comment déboguer le système en cas de dysfonctionnement.
Comment fonctionne tc
Chaque tc configuration est composée de quatre éléments mobiles :
- qdisc (discipline de mise en file d'attente). Le planificateur associé à une interface réseau. Il détermine comment les paquets sont mis en file d'attente et retirés de celle-ci.
- Class. Une subdivision au sein d'un qdisc avec classes. Considérez-la comme une voie avec sa propre limitation de vitesse.
- Filtre. Il inspecte les en-têtes des paquets (adresses IP, ports, marques) et attribue chaque paquet à une classe.
- Action. Ce qui arrive à un paquet une fois qu'il correspond : transfert, rejet, redirection.
Ces éléments forment une arborescence. Les paquets entrent au niveau du qdisc racine, passent par les filtres, sont triés en classes par un major:minor identifiant, puis finissent mis en file d'attente au niveau d'un qdisc feuille en vue de leur transmission.
Pour tout ce qui est plus complexe qu’une correspondance basée sur le port, marquez les paquets avec iptables ou nftables dans la table mangle, puis utilisez le fw filtre de tc pour classer par marque. Cela s'adapte bien mieux que d'enchaîner des règles brutes u32 pour chaque type de trafic.
Sortie vs entrée
Le sens du trafic a son importance. Le noyau peut mettre en mémoire tampon et retarder les paquets sortants, ce qui permet un véritable lissage. Les paquets entrants ont déjà traversé le réseau au moment où vous les voyez, vous ne pouvez donc que les contrôler (les rejeter au-delà d’un seuil) à moins de les rediriger d’abord vers un périphérique IFB.
| Fonctionnalité | Sortie | Entrée |
|---|---|---|
| Direction | Sortant | Entrant |
| Mise en forme | Natif | Nécessite IFB |
| Contrôle | Prise en charge | Prise en charge |
| Utilisation typique | QoS, partage de bande passante, régulation | Limitation de débit, atténuation de base des attaques DDoS |
Les qdiscs que vous utiliserez réellement
- HTB (Hierarchical Token Bucket). Avec classes. À utiliser lorsque vous souhaitez garantir une bande passante minimale par service tout en pouvant emprunter de la capacité inutilisée à d'autres classes.
- TBF (Token Bucket Filter). Sans classes. À utiliser lorsque vous avez simplement besoin de limiter l'ensemble d'une interface à un débit unique.
- fq_codel (Fair Queuing Controlled Delay). Combine l'équité par flux avec la gestion active des files d'attente pour éliminer le bufferbloat. C'est le qdisc par défaut dans la plupart des distributions Linux depuis systemd 217 et il est fourni par défaut sur RHEL 9. Attachez-le toujours en tant que qdisc feuille sous les classes HTB, sinon un seul flux gourmand peut monopoliser toute une classe.
Configuration de tc sur un serveur Linux
tc est fourni avec le paquet iproute2. Sous Debian et Ubuntu, installez-le avec apt-get install iproute2. Sur RHEL et ses dérivés, yum install iproute. Vous aurez besoin des droits root ou sudo.
Commencez par vérifier le nom correct de l'interface. Une erreur dans le nom de l'interface est la raison la plus courante pour laquelle une configuration ne produit aucun résultat :
ip link showVérifiez ce qui se trouve déjà sur l'interface, y compris les compteurs en temps réel :
tc -s qdisc show dev eth0Effacez tout qdisc root existant avant d'appliquer une nouvelle configuration, afin d'éviter RTNETLINK answers: File exists des erreurs :
tc qdisc del dev eth0 root 2>/dev/null || trueSi vous mettez à jour une règle existante plutôt que de partir de zéro, utilisez replace au lieu de add pour un échange atomique.
Les fonctions de déchargement matériel telles que TSO et GSO regroupent les paquets d'une manière qui interfère avec la mise en forme. Désactivez-les sur l'interface mise en forme :
sudo ethtool -K eth0 tso off gso offDéfinissez fq_codel comme qdisc par défaut à l'échelle du système pour les nouvelles interfaces :
sysctl -w net.core.default_qdisc=fq_codelPour les serveurs très sollicités, associez-le à l'algorithme de contrôle de congestion BBR (noyau 4.9+). Le BBR maintient un débit élevé sans allonger les files d'attente :
sysctl -w net.ipv4.tcp_congestion_control=bbrUne bonne habitude de sécurité si vous configurez une machine distante via SSH : ouvrez une deuxième session et préparez tc qdisc del dev eth0 root prêt à être collé. Une mauvaise règle de filtrage peut vous bloquer l'accès instantanément.
Modulation du trafic sortant avec HTB
HTB vous permet d'attribuer à chaque service un minimum garanti (rate) et un plafond (ceil). La bande passante inutilisée est attribuée à ceux qui en ont besoin, par ordre de priorité. Voici une configuration à trois niveaux fonctionnelle pour une liaison montante de 1 Gbps.
Créez le qdisc HTB racine. Le default 30 envoie tout paquet non classé vers la classe 1:30 plutôt que de le laisser contourner vos règles :
tc qdisc add dev eth0 root handle 1: htb default 30Limitez le débit total à 900 Mbps. Réglez toujours la mise en forme légèrement en dessous de la capacité réelle de la liaison, sinon une file d'attente se forme sur un routeur ou un modem en amont que vous ne contrôlez pas :
tc class add dev eth0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbitDéfinissez les niveaux de service. Les prio obtiennent en priorité la bande passante inutilisée :
# High priority: web and API traffic
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 500mbit ceil 900mbit prio 1
# Medium priority: database replication
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 300mbit ceil 900mbit prio 2
# Low priority: bulk and backup traffic
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 100mbit ceil 900mbit prio 3Ajoutez fq_codel comme qdisc de feuille sur chaque classe afin qu'un seul flux ne puisse pas dominer son niveau :
tc qdisc add dev eth0 parent 1:10 handle 10: fq_codel
tc qdisc add dev eth0 parent 1:20 handle 20: fq_codel
tc qdisc add dev eth0 parent 1:30 handle 30: fq_codelClassifiez maintenant le trafic. Pour une simple correspondance de port, u32 est la méthode la plus rapide :
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
match ip dport 443 0xffff flowid 1:10Pour tout ce qui est avec état, marquez dans iptables et faites correspondre la marque avec fw:
iptables -t mangle -A OUTPUT -p tcp --dport 5432 -j MARK --set-mark 2
tc filter add dev eth0 protocol ip parent 1:0 prio 2 handle 2 fw flowid 1:20Modulation du trafic entrant avec IFB
Il n'est pas possible de réguler le trafic entrant de manière native, car au moment où un paquet arrive, il a déjà utilisé votre bande passante. La solution consiste à rediriger le trafic entrant vers une interface virtuelle de bloc fonctionnel intermédiaire (IFB), où le noyau le traite comme du trafic sortant et vous permet d'appliquer des qdiscs par classe.
Chargez le module et activez l'interface :
modprobe ifb numifbs=1
ip link set dev ifb0 upAjoutez un qdisc d'entrée à l'interface physique et redirigez tout vers ifb0:
tc qdisc add dev eth0 ingress handle ffff:
tc filter add dev eth0 parent ffff: protocol all u32 \
match u32 0 0 action mirred egress redirect dev ifb0À partir de là, ifb0 se comporte comme n'importe quelle autre interface. Appliquez-y votre arbre HTB exactement comme vous le feriez sur le trafic sortant :
tc qdisc add dev ifb0 root handle 1: htb default 30
tc class add dev ifb0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbit
tc class add dev ifb0 parent 1:1 classid 1:10 htb rate 500mbit ceil 900mbit prio 1Priorisation du trafic avec le DSCP
Le DSCP (Differentiated Services Code Point) marque les paquets avec une valeur de 6 bits dans l'octet TOS, ce qui permet à vos tc filtres peuvent classer par balise plutôt que de rechercher des ports dans l'ensemble de règles. Lors de la correspondance DSCP dans tc, décaler la valeur de 2 bits vers la gauche. DSCP EF (46) devient 0xb8. Le masque 0xfc isole les 6 bits DSCP des 2 bits ECN.
Un mappage par défaut judicieux pour les charges de travail des serveurs :
| Type de trafic | DSCP | TOS hex | Exemples |
|---|---|---|---|
| Interactif | EF | 0xb8 | SSH, DNS, VoIP |
| Entreprise | AF41 | 0x88 | HTTP, HTTPS, API |
| En masse | CS1 | 0x20 | Sauvegardes, FTP, mises à jour de paquets |
| Au mieux | CS0 | 0x00 | Tout le reste |
Marquez les paquets sortants dans iptables avant qu'ils n'atteignent vos tc filtres :
iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 46Puis faites correspondre la balise dans tc et acheminez-le vers la bonne classe HTB :
# EF (SSH, VoIP) goes to the high-priority class
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
match ip tos 0xb8 0xfc flowid 1:10
# AF41 (web traffic) goes to the medium class
tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 \
match ip tos 0x88 0xfc flowid 1:20
# CS1 (bulk) goes to the low-priority class
tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 \
match ip tos 0x20 0xfc flowid 1:30Surveillance et dépannage
Les trois commandes que vous utiliserez constamment :
tc -s qdisc show dev eth0
tc -s class show dev eth0
tc -s filter show dev eth0Surveillez le dropped et overlimits . Les paquets perdus indiquent que la file d'attente est saturée ; les dépassements de limite signifient que vous avez atteint le plafond de la classe et que le noyau a dû retarder ou rejeter du trafic. Pour une vue en temps réel :
watch -n 1 'tc -s class show dev eth0'Ajoutez -d pour les paramètres internes (target, interval, quantum) et -j pour une sortie JSON si vous redirigez vers une pile de métriques. Associez-le à ss -tin pour voir les estimations de RTT et les retransmissions au niveau de la couche TCP.
La plupart des défaillances se résument à une courte liste :
| Symptôme | Cause probable | Solution |
|---|---|---|
RTNETLINK answers: File exists | Qdisc racine déjà configuré | tc qdisc del dev eth0 root premier |
| Les règles s'appliquent mais le trafic n'est pas limité | Interface incorrecte, ou TSO/GSO toujours activé | Vérifier avec ip link show, désactivez les déchargements avec ethtool -K |
| Le filtre ne correspond jamais | Syntaxe du port/de l'IP ou alignement du masque incorrect | Ajoutez une action de contre-mesure et vérifiez le nombre de résultats dans tc -s filter show |
| Règles supprimées après le redémarrage | La configuration réside uniquement en mémoire | Intégrer dans un script et appeler depuis systemd ou un dispatcher NetworkManager |
| Latence élevée sur le trafic prioritaire | Pas de qdisc leaf, ou burst trop faible | Associer fq_codel aux classes leaf, augmenter burst |
Si jamais vous vous retrouvez bloqué à cause d'une mauvaise configuration, la réinitialisation est simple :
tc qdisc del dev eth0 roottc on ne peut pas créer de la bande passante que l'on n'a pas, mais sur une liaison montante bien provisionnée, cela fait la différence entre des performances prévisibles et un serveur qui s'effondre dès qu'un client lance un transfert volumineux. Si vous avez besoin de la bande passante brute et de la liberté de la modeler comme bon vous semble, jetez un œil aux serveurs dédiés de FDC.

Linux Traffic Control (tc) : un guide pratique
Contrôlez la bande passante, priorisez le trafic et façonnez les entrées et sorties sur Linux avec tc. Configuration HTB, IFB, DSCP et fq_codel pour de vrais serveurs.
12 min de lecture - 5 juin 2026
Pourquoi il est important d'avoir un VPS puissant et sans compteur
7 min de lecture - 9 mai 2025