Linux Traffic Control (tc): een praktische gids
12 min lezen - 5 juni 2026

Beheer bandbreedte, geef prioriteit aan verkeer en beheer inkomend en uitgaand verkeer op Linux met tc. Werkende HTB-, IFB-, DSCP- en fq_codel-configuraties voor echte servers.
Linux Traffic Control (tc): een praktische gids
Met het tc commando geeft je directe controle over hoe je server het netwerkverkeer afhandelt. U kunt de bandbreedte per dienst beperken, interactieve sessies zoals SSH responsief houden wanneer er pieken in bulkoverdracht optreden, en zowel uitgaande als inkomende datastromen regelen vanuit één enkele tool. Deze gids behandelt de kernconcepten, een werkende HTB-configuratie, ingangsherstructurering met IFB, op DSCP gebaseerde prioritering, en hoe u fouten kunt opsporen wanneer er iets misgaat.
Hoe tc werkt
Elke tc configuratie bestaat uit vier onderdelen:
- qdisc (queuing discipline). De scheduler die aan een netwerkinterface is gekoppeld. Deze bepaalt hoe pakketten in de wachtrij worden geplaatst en eruit worden gehaald.
- Class. Een onderverdeling binnen een classful qdisc. Zie het als een rijstrook met een eigen snelheidslimiet.
- Filter. Controleert pakketheaders (IP-adressen, poorten, markeringen) en wijst elk pakket aan een klasse toe.
- Actie. Wat er met een pakket gebeurt zodra het aan de criteria voldoet: doorsturen, verwijderen, omleiden.
Deze vormen een boomstructuur. Pakketten komen binnen bij de root-qdisc, passeren filters, worden door een major:minor handle en komen uiteindelijk in de wachtrij van een leaf-qdisc terecht voor verzending.
Voor alles wat complexer is dan op poorten gebaseerde matching, markeer je pakketten met iptables of nftables in de mangle-tabel, en gebruik je vervolgens het fw filter in tc om op markering te classificeren. Dit schaalt veel beter dan het koppelen van ruwe u32 regels aan elkaar te koppelen voor elk type verkeer.
Uitgaand versus inkomend
De richting is van belang. De kernel kan uitgaande pakketten in de buffer opslaan en vertragen, wat echte shaping mogelijk maakt. Inkomende pakketten zijn al via de verbinding binnengekomen tegen de tijd dat je ze ziet, dus je kunt ze alleen controleren (weggooien boven een drempelwaarde) tenzij je ze eerst omleidt naar een IFB-apparaat.
| Functie | Uitgaand | Ingang |
|---|---|---|
| Richting | Uitgaand | Inkomend |
| Shaping | Native | Vereist IFB |
| Policing | Ondersteund | Ondersteund |
| Typisch gebruik | QoS, bandbreedteverdeling, pacing | Snelheidsbeperking, basisbescherming tegen DDoS-aanvallen |
De qdiscs die u daadwerkelijk zult gebruiken
- HTB (Hierarchical Token Bucket). Met klassen. Gebruik deze als je gegarandeerde minimale bandbreedte per service wilt, met de mogelijkheid om ongebruikte capaciteit van andere klassen te lenen.
- TBF (Token Bucket Filter). Klassevrij. Gebruik dit wanneer je gewoon een hele interface op één snelheid wilt begrenzen.
- fq_codel (Fair Queuing Controlled Delay). Combineert eerlijkheid per datastroom met actief wachtrijbeheer om bufferbloat te voorkomen. Dit is sinds systemd 217 de standaard qdisc in de meeste Linux-distributies en wordt standaard meegeleverd met RHEL 9. Koppel deze altijd als een leaf-qdisc onder HTB-klassen, anders kan één enkele gulzige datastroom een hele klasse in beslag nemen.
tc instellen op een Linux-server
tc wordt meegeleverd met het iproute2-pakket. Op Debian en Ubuntu installeer je het met apt-get install iproute2. Op RHEL en afgeleide distributies yum install iproute. Je hebt root-rechten of sudo nodig.
Zorg eerst dat je de juiste interfacenaam hebt. Een verkeerde naam voor de interface is de meest voorkomende reden waarom een configuratie stilletjes niets doet:
ip link showControleer wat er al op de interface staat, inclusief de actuele tellers:
tc -s qdisc show dev eth0Verwijder eventuele bestaande root-qdiscs voordat je een nieuwe configuratie toepast, om RTNETLINK answers: File exists fouten te voorkomen:
tc qdisc del dev eth0 root 2>/dev/null || trueAls je een bestaande regel bijwerkt in plaats van helemaal opnieuw te beginnen, gebruik dan replace in plaats van add voor een atomaire omwisseling.
Hardware-offloading zoals TSO en GSO bundelt pakketten op een manier die shaping verstoort. Schakel deze functies uit op de interface waarop shaping wordt toegepast:
sudo ethtool -K eth0 tso off gso offStel fq_codel in als de systeembrede standaard-qdisc voor nieuwe interfaces:
sysctl -w net.core.default_qdisc=fq_codelCombineer dit bij drukke servers met het BBR-congestiebeheersingsalgoritme (kernel 4.9+). BBR houdt de doorvoer hoog zonder dat de wachtrijen groeien:
sysctl -w net.ipv4.tcp_congestion_control=bbrEen veilige gewoonte als je een externe machine via SSH configureert: open een tweede sessie en zorg dat tc qdisc del dev eth0 root klaar om te plakken. Een verkeerde filterregel kan je onmiddellijk buitensluiten.
Uitgaand verkeer vormgeven met HTB
Met HTB kunt u elke dienst een gegarandeerd minimum (rate) en een maximum (ceil). Ongebruikte bandbreedte gaat naar degene die deze nodig heeft, in volgorde van prioriteit. Hier volgt een werkende opzet met drie niveaus voor een uplink van 1 Gbps.
Maak de root-HTB-qdisc aan. De default 30 stuurt elk niet-geclassificeerd pakket naar klasse 1:30 in plaats van het je regels te laten omzeilen:
tc qdisc add dev eth0 root handle 1: htb default 30Beperk de totale doorvoer tot 900 Mbps. Stel de shaping altijd iets lager in dan de werkelijke linkcapaciteit, anders ontstaat er een wachtrij op een upstream-router of -modem waarover je geen controle hebt:
tc class add dev eth0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbitDefinieer de serviceniveaus. Lagere prio waarden krijgen als eerste ongebruikte bandbreedte:
# 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 3Voeg fq_codel als leaf-qdisc aan elke klasse, zodat één enkele stroom zijn niveau niet kan domineren:
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_codelClassificeer nu het verkeer. Voor eenvoudige poortmatching u32 is dit het snelst:
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
match ip dport 443 0xffff flowid 1:10Voor alles wat stateful is, markeer je in iptables en koppel je de markering aan 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:20Inkomend verkeer vormgeven met IFB
Je kunt inkomend verkeer niet standaard vormgeven, omdat het pakket op het moment dat het aankomt al je bandbreedte heeft gebruikt. De oplossing is om inkomend verkeer om te leiden naar een virtuele interface van het Intermediate Functional Block (IFB), waar de kernel het behandelt als uitgaand verkeer en je classful qdiscs kunt toepassen.
Laad de module en schakel de interface in:
modprobe ifb numifbs=1
ip link set dev ifb0 upVoeg een ingangs-qdisc toe aan de fysieke interface en leid alles om naar 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 ifb0Vanaf hier ifb0 gedraagt de interface zich net als elke andere interface. Pas je HTB-boom erop toe, precies zoals je dat bij uitgaand verkeer zou doen:
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 1Verkeer prioriteren met DSCP
DSCP (Differentiated Services Code Point) markeert pakketten met een waarde van 6 bits in de TOS-byte, zodat uw tc filters op tag kunnen classificeren in plaats van poorten door de regelset te moeten doorzoeken. Bij het matchen van DSCP in tc, verschuif je de waarde 2 bits naar links. DSCP EF (46) wordt 0xb8. Het masker 0xfc scheidt de 6 DSCP-bits van de 2 ECN-bits.
Een verstandige standaardtoewijzing voor serverworkloads:
| Verkeerstype | DSCP | TOS hex | Voorbeelden |
|---|---|---|---|
| Interactief | EF | 0xb8 | SSH, DNS, VoIP |
| Zakelijk | AF41 | 0x88 | HTTP, HTTPS, API's |
| Bulk | CS1 | 0x20 | Back-ups, FTP, pakketupdates |
| Best effort | CS0 | 0x00 | Al het overige |
Markeer uitgaande pakketten in iptables voordat ze je tc filters:
iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 46Koppel vervolgens de tag in tc en routeer het naar de juiste HTB-klasse:
# 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:30Monitoring en probleemoplossing
De drie commando’s die je voortdurend zult gebruiken:
tc -s qdisc show dev eth0
tc -s class show dev eth0
tc -s filter show dev eth0Houd de dropped en overlimits tellers in de gaten. Verloren pakketten betekenen dat de wachtrij verzadigd is; overschrijdingen van limieten betekenen dat je het plafond van een klasse hebt bereikt en dat de kernel het verkeer moest vertragen of afwerpen. Voor een live overzicht:
watch -n 1 'tc -s class show dev eth0'Voeg -d voor interne parameters (target, interval, quantum) en -j voor JSON-uitvoer als je de gegevens doorstuurt naar een metrics-stack. Combineer dit met ss -tin om RTT-schattingen en hertransmissies op de TCP-laag te bekijken.
De meeste storingen vallen onder een beperkt aantal oorzaken:
| Symptoom | Waarschijnlijke oorzaak | Oplossing |
|---|---|---|
RTNETLINK answers: File exists | Root-qdisc is al geconfigureerd | tc qdisc del dev eth0 root eerst |
| Regels zijn van toepassing, maar het verkeer wordt niet beperkt | Verkeerde interface, of TSO/GSO is nog steeds ingeschakeld | Controleer met ip link show, schakel offloads uit met ethtool -K |
| Filter komt nooit overeen | Onjuiste poort-/IP-syntaxis of maskerafstemming | Voeg een tegenmaatregel toe en controleer het aantal treffers in tc -s filter show |
| Regels verdwenen na herstart | De configuratie staat alleen in het geheugen | Verpak het in een script en roep het aan vanuit systemd of een NetworkManager-dispatcher |
| Hoge latentie bij prioritair verkeer | Geen leaf-qdisc, of burst te laag | Koppel fq_codel aan leaf-klassen, verhoog burst |
Als je jezelf ooit buitensluit door een verkeerde configuratie, is het resetten eenvoudig:
tc qdisc del dev eth0 roottc je kunt geen bandbreedte creëren die je niet hebt, maar op een goed uitgeruste uplink maakt het het verschil tussen voorspelbare prestaties en een server die instort zodra één tenant een grote overdracht start. Als je de ruwe bandbreedte nodig hebt en de vrijheid om deze naar eigen inzicht te vormgeven, kijk dan eens naar de dedicated servers van FDC.

iperf3-handleiding: Netwerksnelheid testen op Linux en Windows
Installeer iperf3, voer bandbreedtetests uit en stem de TCP-buffers af voor nauwkeurige resultaten op Linux en Windows. Behandelt UDP-, bidirectionele en 10GbE+-tests
10 min lezen - 7 mei 2026
Afgestemde profielen voor het optimaliseren van de werklast op Linux-servers
16 min lezen - 9 juni 2026

Hebt u vragen of wilt u een oplossing op maat?
Flexibele opties
Wereldwijd bereik
Directe inzet
Flexibele opties
Wereldwijd bereik
Directe inzet