Linux Traffic Control (tc): praktyczny przewodnik
12 min czytania - 5 czerwca 2026

Kontroluj przepustowość, ustalaj priorytety ruchu oraz kształtuj ruch przychodzący i wychodzący w systemie Linux za pomocą tc. Działająca konfiguracja HTB, IFB, DSCP i fq_codel dla rzeczywistych serwerów.
Kontrola ruchu w systemie Linux (tc): praktyczny przewodnik
Polecenie tc pozwala na bezpośrednią kontrolę nad sposobem, w jaki serwer obsługuje ruch sieciowy. Możesz ograniczyć przepustowość dla poszczególnych usług, zapewnić responsywność sesji interaktywnych, takich jak SSH, w przypadku gwałtownego wzrostu transferu masowego oraz kształtować przepływ zarówno wychodzący, jak i przychodzący za pomocą jednego narzędzia. Niniejszy przewodnik obejmuje podstawowe pojęcia, działającą konfigurację HTB, kształtowanie ruchu przychodzącego za pomocą IFB, ustalanie priorytetów oparte na DSCP oraz sposoby debugowania w przypadku awarii.
Jak działa tc
Każda tc konfiguracja składa się z czterech ruchomych elementów:
- qdisc (dyscyplina kolejkowania). Harmonogram przypisany do interfejsu sieciowego. Decyduje o tym, w jaki sposób pakiety są umieszczane w kolejce i z niej usuwane.
- Klasa. Podział wewnątrz qdisc z podziałem na klasy. Pomyśl o tym jak o pasie ruchu z własnym ograniczeniem prędkości.
- Filtr. Sprawdza nagłówki pakietów (adresy IP, porty, oznaczenia) i przypisuje każdy pakiet do klasy.
- Akcja. Co dzieje się z pakietem po dopasowaniu: przekazanie, odrzucenie, przekierowanie.
Tworzą one drzewo. Pakiety wchodzą do qdiscu korzeniowego, trafiają do filtrów, są sortowane do klas przez major:minor identyfikatora i trafiają do kolejki w qdisc liścia w celu transmisji.
W przypadku operacji bardziej złożonych niż dopasowanie oparte na porcie, należy oznaczyć pakiety za pomocą iptables lub nftables w tabeli mangle, a następnie użyć fw filtru w tc w celu klasyfikacji według oznaczenia. Skaluje się to znacznie lepiej niż łańcuchowanie surowych u32 dla każdego typu ruchu.
Ruch wychodzący a ruch przychodzący
Kierunek ma znaczenie. Jądro może buforować i opóźniać pakiety wychodzące, co umożliwia rzeczywiste kształtowanie ruchu. Pakiety przychodzące przeszły już przez łącze, zanim je zobaczysz, więc możesz je jedynie kontrolować (odrzucać powyżej progu), chyba że najpierw przekierujesz je do urządzenia IFB.
| Funkcja | Wyjście | Wchodzące |
|---|---|---|
| Kierunek | Wychodzące | Przychodzące |
| Kształtowanie | Natywny | Wymaga IFB |
| Policing | Obsługiwane | Obsługiwane |
| Typowe zastosowanie | QoS, współdzielenie przepustowości, regulacja przepustowości | Ograniczanie przepustowości, podstawowa ochrona przed atakami DDoS |
Qdisc, z których faktycznie będziesz korzystać
- HTB (Hierarchical Token Bucket). Klasowe. Używaj go, gdy chcesz zagwarantować minimalną przepustowość dla każdej usługi z możliwością pożyczenia niewykorzystanej przepustowości z innych klas.
- TBF (Token Bucket Filter). Bezklasowy. Używaj go, gdy chcesz po prostu ograniczyć cały interfejs do jednej prędkości.
- fq_codel (Fair Queuing Controlled Delay). Łączy sprawiedliwość przepływu z aktywnym zarządzaniem kolejką, aby wyeliminować bufferbloat. Jest to domyślny qdisc w większości dystrybucji Linuksa od wersji systemd 217 i jest dostarczany jako domyślny w RHEL 9. Zawsze dołączaj go jako qdisc liściowy pod klasami HTB, w przeciwnym razie pojedynczy chciwy przepływ może zająć całą klasę.
Konfiguracja tc na serwerze z systemem Linux
tc jest dostarczany wraz z pakietem iproute2. W systemach Debian i Ubuntu należy go zainstalować za pomocą apt-get install iproute2. W systemie RHEL i jego pochodnych yum install iproute. Potrzebne będą uprawnienia roota lub sudo.
Najpierw sprawdź poprawną nazwę interfejsu. Błędne nazwanie interfejsu jest najczęstszą przyczyną, dla której konfiguracja po cichu nie działa:
ip link showSprawdź, co już znajduje się na interfejsie, w tym aktualne liczniki:
tc -s qdisc show dev eth0Przed zastosowaniem nowej konfiguracji usuń wszelkie istniejące qdisc typu root, aby uniknąć RTNETLINK answers: File exists błędów:
tc qdisc del dev eth0 root 2>/dev/null || trueJeśli aktualizujesz istniejącą regułę, a nie zaczynasz od zera, użyj replace zamiast add , aby uzyskać atomową zamianę.
Odciążanie sprzętowe, takie jak TSO i GSO, grupuje pakiety w sposób, który zakłóca kształtowanie ruchu. Wyłącz je na interfejsie, na którym stosowane jest kształtowanie:
sudo ethtool -K eth0 tso off gso offUstaw fq_codel jako domyślny qdisc dla nowych interfejsów w całym systemie:
sysctl -w net.core.default_qdisc=fq_codelW przypadku obciążonych serwerów połącz to z algorytmem kontroli przeciążenia BBR (jądro 4.9+). BBR utrzymuje wysoką przepustowość bez wydłużania kolejek:
sysctl -w net.ipv4.tcp_congestion_control=bbrJednym z bezpiecznych nawyków podczas konfiguracji zdalnego urządzenia przez SSH jest: otwarcie drugiej sesji i przygotowanie tc qdisc del dev eth0 root gotowy do wklejenia. Zła reguła filtrująca może natychmiast zablokować dostęp.
Kształtowanie ruchu wychodzącego za pomocą HTB
HTB pozwala przypisać każdej usłudze gwarantowaną wartość minimalną (rate) oraz limit maksymalny (ceil). Niewykorzystana przepustowość trafia do tego, kto jej potrzebuje, w kolejności według priorytetów. Oto działająca konfiguracja trójwarstwowa dla łącza uplink o przepustowości 1 Gb/s.
Utwórz główny qdisc HTB. default 30 wysyła każdy niesklasyfikowany pakiet do klasy 1:30 zamiast pozwolić mu ominąć twoje reguły:
tc qdisc add dev eth0 root handle 1: htb default 30Ogranicz całkowitą przepustowość do 900 Mb/s. Zawsze kształtuj przepustowość nieco poniżej rzeczywistej przepustowości łącza, w przeciwnym razie kolejka utworzy się na routerze lub modemie upstream, nad którym nie masz kontroli:
tc class add dev eth0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbitZdefiniuj poziomy usług. Niższe prio wartości otrzymują niewykorzystaną przepustowość jako pierwsze:
# 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 3Dołącz fq_codel jako qdisc liścia w każdej klasie, aby pojedynczy strumień nie mógł zdominować swojej klasy:
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_codelTeraz sklasyfikuj ruch. W przypadku prostego dopasowywania portów u32 jest najszybsze:
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
match ip dport 443 0xffff flowid 1:10W przypadku wszystkiego, co jest stanowe, oznacz w iptables i dopasuj oznaczenie do 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:20Kształtowanie ruchu przychodzącego za pomocą IFB
Nie można natywnie kształtować ruchu przychodzącego, ponieważ w momencie dotarcia pakietu wykorzystał on już przepustowość. Rozwiązaniem jest przekierowanie ruchu przychodzącego do wirtualnego interfejsu Intermediate Functional Block (IFB), gdzie jądro traktuje go jako ruch wychodzący i pozwala na zastosowanie klasowych qdisców.
Załaduj moduł i uruchom interfejs:
modprobe ifb numifbs=1
ip link set dev ifb0 upDodaj qdisc ruchu przychodzącego do interfejsu fizycznego i przekieruj wszystko do 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 ifb0Od tego momentu ifb0 zachowuje się jak każdy inny interfejs. Zastosuj do niego drzewo HTB dokładnie tak, jak w przypadku ruchu wychodzącego:
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 1Priorytetyzacja ruchu za pomocą DSCP
DSCP (Differentiated Services Code Point) oznacza pakiety 6-bitową wartością w bajcie TOS, dzięki czemu tc filtry mogą klasyfikować na podstawie tagu, zamiast przeszukiwać porty w całym zestawie reguł. Podczas dopasowywania DSCP w tc, przesuń wartość w lewo o 2 bity. DSCP EF (46) staje się 0xb8. Maska 0xfc izoluje 6 bitów DSCP od 2 bitów ECN.
Rozsądne domyślne przyporządkowanie dla obciążeń serwerowych:
| Typ ruchu | DSCP | TOS (szesnastkowo) | Przykłady |
|---|---|---|---|
| Interaktywny | EF | 0xb8 | SSH, DNS, VoIP |
| Biznes | AF41 | 0x88 | HTTP, HTTPS, API |
| Hurtowe | CS1 | 0x20 | Kopie zapasowe, FTP, aktualizacje pakietów |
| Najlepsze starania | CS0 | 0x00 | Wszystko inne |
Oznacz pakiety wychodzące w iptables, zanim trafią do twoich tc filtry:
iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 46Następnie dopasuj tag w tc i przekieruj go do odpowiedniej klasy 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:30Monitorowanie i rozwiązywanie problemów
Trzy polecenia, z których będziesz korzystać na co dzień:
tc -s qdisc show dev eth0
tc -s class show dev eth0
tc -s filter show dev eth0Obserwuj dropped i overlimits liczników. Utracone pakiety oznaczają, że kolejka jest przepełniona; przekroczenie limitów oznacza, że osiągnąłeś pułap klasy i jądro musiało opóźnić lub odrzucić ruch. Aby uzyskać widok na żywo:
watch -n 1 'tc -s class show dev eth0'Dodaj -d dla parametrów wewnętrznych (target, interval, quantum) oraz -j dla wyjścia JSON, jeśli przekierowujesz dane do stosu metrycznego. Połącz to z ss -tin , aby zobaczyć szacunki RTT i retransmisje na warstwie TCP.
Większość awarii mieści się w krótkiej liście:
| Objaw | Prawdopodobna przyczyna | Rozwiązanie |
|---|---|---|
RTNETLINK answers: File exists | Dyskretny mechanizm root już skonfigurowany | tc qdisc del dev eth0 root pierwsze |
| Reguły mają zastosowanie, ale ruch nie jest ograniczany | Nieprawidłowy interfejs lub TSO/GSO nadal włączone | Potwierdź za pomocą ip link show, wyłącz odciążanie za pomocą ethtool -K |
| Filtr nigdy nie pasuje | Nieprawidłowa składnia portu/adresu IP lub wyrównanie maski | Dodaj działanie przeciwdziałające i sprawdź liczbę trafień w tc -s filter show |
| Zasady znikają po ponownym uruchomieniu | Konfiguracja znajduje się wyłącznie w pamięci | Zapakuj w skrypt i wywołaj z systemd lub dyspozytora NetworkManager |
| Duże opóźnienia w ruchu priorytetowym | Brak qdisc typu leaf lub zbyt niski limit burst | Dołącz fq_codel do klas liściowych, podnieś burst |
Jeśli kiedykolwiek zablokujesz się przez błędną konfigurację, reset jest prosty:
tc qdisc del dev eth0 roottc nie da się wyczarować przepustowości, której nie masz, ale w przypadku dobrze skonfigurowanego łącza uplink stanowi to różnicę między przewidywalną wydajnością a serwerem, który się załamuje w momencie, gdy jeden z użytkowników rozpocznie duży transfer. Jeśli potrzebujesz surowej przepustowości i swobody kształtowania jej tak, jak chcesz, zapoznaj się z serwerami dedykowanymi FDC.

Linux Traffic Control (tc): praktyczny przewodnik
Kontroluj przepustowość, ustalaj priorytety ruchu oraz kształtuj ruch przychodzący i wychodzący w systemie Linux za pomocą tc. Działająca konfiguracja HTB, IFB, DSCP i fq_codel dla rzeczywistych serwerów.
12 min czytania - 5 czerwca 2026
Dlaczego ważne jest posiadanie wydajnego i niezmierzonego serwera VPS?
7 min czytania - 9 maja 2025

Masz pytania lub potrzebujesz niestandardowego rozwiązania?
Elastyczne opcje
Globalny zasięg
Natychmiastowe wdrożenie
Elastyczne opcje
Globalny zasięg
Natychmiastowe wdrożenie