Kontrola ruchu w systemie Linux (tc): praktyczny przewodnik
12 min czytania - 5 czerwca 2026

Kontrola przepustowości, ustalanie priorytetów ruchu oraz kształtowanie ruchu przychodzącego i wychodzącego w systemie Linux za pomocą narzędzia tc. Działające konfiguracje HTB, IFB, DSCP i fq_codel dla serwerów Real.
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żna ograniczyć przepustowość dla poszczególnych usług, zapewnić płynność sesji interaktywnych, takich jak SSH, nawet podczas gwałtownych wzrostów transferu danych, a także kształtować zarówno ruch 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 na podstawie DSCP oraz sposoby debugowania w przypadku wystąpienia problemów.
Jak działa tc
Każda tc konfiguracja składa się z czterech elementów:
- qdisc (dyscyplina kolejkowania). Harmonogram przypisany do interfejsu sieciowego. Decyduje on o tym, w jaki sposób pakiety są umieszczane w kolejce i z niej pobierane.
- Klasa. Podział wewnątrz qdisc z podziałem na klasy. Można to porównać do pasa ruchu z własnym ograniczeniem prędkości.
- Filtr. Sprawdza nagłówki pakietów (adresy IP, porty, oznaczenia) i przypisuje każdy pakiet do odpowiedniej klasy.
- Akcja. Co dzieje się z pakietem po dopasowaniu: przekazanie, odrzucenie, przekierowanie.
Elementy te tworzą drzewo. Pakiety wchodzą do qdiscu korzeniowego, trafiają do filtrów, są sortowane do klas przez major:minor identyfikatora, a na koniec trafiają do kolejki w qdiscu liściowym 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 reguł 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 monitorować (odrzucać powyżej progu), chyba że najpierw przekierujesz je do urządzenia IFB.
| Funkcja | Ruch wychodzący | Ruch przychodzący |
|---|---|---|
| Kierunek | Wychodzące | Przychodzące |
| Kształtowanie | Natywny | Wymaga IFB |
| Kontrola | Obsługiwane | Obsługiwane |
| Typowe zastosowanie | QoS, podział przepustowości, regulacja przepustowości | Ograniczanie przepustowości, podstawowa ochrona przed atakami DDoS |
Qdiscy, z których faktycznie będziesz korzystać
- HTB (Hierarchical Token Bucket). Klasowy. 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ć przepustowość całego interfejsu do jednej wartości.
- fq_codel (Fair Queuing Controlled Delay). Łączy sprawiedliwość na poziomie poszczególnych przepływów z aktywnym zarządzaniem kolejkami, aby wyeliminować zjawisko „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 należy go dołączać jako qdisc końcowy pod klasami HTB, w przeciwnym razie pojedynczy „chciwy” przepływ może zmonopolizować całą klasę.
Konfiguracja programu tc na serwerze z systemem Linux
tc jest dostarczany wraz z pakietem iproute2. W systemach Debian i Ubuntu należy go zainstalować za pomocą polecenia apt-get install iproute2. W systemie RHEL i jego pochodnych yum install iproute. Potrzebne będą uprawnienia roota lub sudo.
Najpierw sprawdź prawidłową nazwę interfejsu. Błędne nazwanie interfejsu jest najczęstszą przyczyną, dla której konfiguracja nie przynosi żadnych efektów:
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 zapewnić atomową zamianę.
Odciążanie sprzętowe, takie jak TSO i GSO, grupuje pakiety w sposób, który zakłóca kształtowanie ruchu. Należy je wyłączyć na interfejsie, na którym stosowane jest kształtowanie ruchu:
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=bbrJedna z zasad bezpieczeństwa podczas konfigurowania zdalnego urządzenia przez SSH: otwórz drugą sesję i przygotuj 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, zgodnie z kolejnością priorytetów. Oto działająca konfiguracja trójwarstwowa dla łącza w górę o przepustowości 1 Gbps.
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 Mbps. 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ą w pierwszej kolejności niewykorzystaną przepustowość:
# 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 typu „leaf” do każdej klasy, aby pojedynczy strumień nie 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 wszelkich operacji stanowych należy oznaczyć w iptables i dopasować 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 dyskretów klasowych.
Załaduj moduł i uruchom interfejs:
modprobe ifb numifbs=1
ip link set dev ifb0 upDodaj qdisc przychodzący do interfejsu fizycznego i przekieruj cały ruch 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 znacznika, zamiast przeszukiwać porty w całym zestawie reguł. Podczas dopasowywania DSCP w tc, przesuń wartość o 2 bity w lewo. DSCP EF (46) staje się 0xb8. Maska 0xfc oddziela 6 bitów DSCP od 2 bitów ECN.
Rozsądne domyślne mapowanie dla obciążeń serwerowych:
| Typ ruchu | DSCP | TOS (szesnastkowo) | Przykłady |
|---|---|---|---|
| Interaktywny | EF | 0xb8 | SSH, DNS, VoIP |
| Biznes | AF41 | 0x88 | HTTP, HTTPS, interfejsy API |
| Hurtowo | CS1 | 0x20 | Kopie zapasowe, FTP, aktualizacje pakietów |
| Najlepsze możliwe | 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 ten tag w tc i przekieruj je 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 liczniki. Utracone pakiety oznaczają, że kolejka jest przepełniona; przekroczenie limitów oznacza, że osiągnąłeś pułap klasy, a jądro musiało opóźnić lub odrzucić ruch. Aby uzyskać podgląd 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 metryk. Połącz to z ss -tin , aby zobaczyć szacunki RTT i retransmisje na warstwie TCP.
Większość awarii można zaklasyfikować do kilku typów:
| Objaw | Prawdopodobna przyczyna | Rozwiązanie |
|---|---|---|
RTNETLINK answers: File exists | Dyskretny mechanizm root qdisc jest już skonfigurowany | tc qdisc del dev eth0 root pierwsza |
| Reguły mają zastosowanie, ale ruch nie jest ograniczany | Niewłaściwy interfejs lub TSO/GSO nadal włączone | Sprawdź za pomocą ip link show, wyłącz odciążanie za pomocą ethtool -K |
| Filtr nigdy nie pasuje | Nieprawidłowa składnia adresu portu/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 to w skrypt i wywołaj z systemd lub dyspozytora NetworkManager |
| Duże opóźnienia w ruchu o wysokim priorytecie | Brak qdisc typu „leaf” lub zbyt niski limit burst | Przypisz fq_codel do klas typu „leaf”, zwiększ burst |
Jeśli kiedykolwiek zablokujesz sobie dostęp 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 danych. Jeśli potrzebujesz surowej przepustowości i swobody kształtowania jej tak, jak chcesz, zapoznaj się z ofertą serwerów dedykowanych FDC.

Samouczek dotyczący programu iperf3: Testowanie prędkości sieci w systemach Linux i Windows
Zainstaluj iperf3, przeprowadź testy przepustowości i dostosuj bufory TCP, aby uzyskać dokładne wyniki w systemach Linux i Windows. Obejmuje testy UDP, dwukierunkowe oraz testy 10GbE+.
10 min czytania - 7 maja 2026
Dostosowane profile do optymalizacji obciążenia serwerów z systemem Linux
16 min czytania - 9 czerwca 2026

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