#server-performance

Управління трафіком у Linux (tc): практичний посібник

12 хв читання - 5 червня 2026 р.

hero section cover

Керування пропускною здатністю, встановлення пріоритетів трафіку та регулювання вхідного та вихідного трафіку в Linux за допомогою tc. Працюючі конфігурації HTB, IFB, DSCP та fq_codel для реальних серверів.

Управління трафіком у Linux (tc): практичний посібник

Команда tc дозволяє безпосередньо керувати тим, як сервер обробляє мережевий трафік. Ви можете обмежувати пропускну здатність для кожної служби, забезпечувати оперативність інтерактивних сеансів (наприклад, SSH) під час пікових навантажень від масових передач даних, а також регулювати як вихідні, так і вхідні потоки за допомогою одного інструменту. У цьому посібнику висвітлено основні концепції, налаштування HTB, що працює, регулювання вхідного трафіку за допомогою IFB, визначення пріоритетів на основі DSCP, а також способи усунення несправностей у разі, якщо щось не працює.


 

Як працює tc

Кожна tc конфігурація складається з чотирьох рухомих частин:

  • qdisc (дисципліна черги). Планувальник, прив’язаний до мережевого інтерфейсу. Він визначає, як пакети ставляться в чергу та вилучаються з неї.
  • Клас. Підрозділ у qdisc із класами. Уявіть це як смугу руху з власним обмеженням швидкості.
  • Фільтр. Перевіряє заголовки пакетів (IP-адреси, порти, мітки) і привласнює кожному пакету клас.
  • Дія. Що відбувається з пакетом після відповідності критеріям: пересилання, відкидання, перенаправлення.

Ці елементи утворюють дерево. Пакети надходять у кореневий qdisc, проходять через фільтри, сортуються за класами за допомогою major:minor ідентифікатора, і в кінцевому підсумку потрапляють у чергу на кінцевому qdisc для передачі.

Для будь-чого складнішого, ніж зіставлення на основі портів, позначте пакети за допомогою iptables або nftables у таблиці mangle, а потім використовуйте fw фільтр у tc для класифікації за міткою. Це масштабується набагато краще, ніж ланцюгове застосування необроблених u32 правил для кожного типу трафіку.

Вихідний трафік проти вхідного

Напрямок має значення. Ядро може буферизувати та затримувати вихідні пакети, що й забезпечує справжнє формування трафіку. Вхідні пакети вже пройшли по каналу до того, як ви їх побачите, тому ви можете лише контролювати їх (відкидати, якщо перевищено поріг), якщо тільки ви спочатку не перенаправите їх на пристрій IFB.

ФункціяВихіднийВхід
НапрямокВихідніВхідний
ФормуванняВбудованийПотрібен IFB
КонтрольПідтримуєтьсяПідтримується
Типове використанняQoS, розподіл пропускної здатності, регулювання швидкостіОбмеження швидкості, базове запобігання DDoS-атакам

Qdisc, які ви насправді будете використовувати

  • HTB (Hierarchical Token Bucket). Класовий. Використовуйте його, коли вам потрібна гарантована мінімальна пропускна здатність для кожної служби з можливістю запозичення невикористаної пропускної здатності з інших класів.
  • TBF (Token Bucket Filter). Безкласовий. Використовуйте його, коли вам просто потрібно обмежити пропускну здатність всього інтерфейсу єдиною швидкістю.
  • fq_codel (Fair Queuing Controlled Delay). Поєднує справедливий розподіл за потоками з активним управлінням чергами для усунення «буферного роздуття». Це qdisc за замовчуванням у більшості дистрибутивів Linux починаючи з systemd 217 і входить до складу RHEL 9 за замовчуванням. Завжди підключайте його як кінцевий qdisc під класами HTB, інакше один «жадібний» потік може заблокувати весь клас.

Налаштування tc на сервері під Linux

tc поставляється разом із пакетом iproute2. У Debian та Ubuntu його слід встановити за допомогою команди apt-get install iproute2. У RHEL та похідних дистрибутивах yum install iproute. Вам знадобиться права root або sudo.

Спочатку визначте правильну назву інтерфейсу. Помилкова назва інтерфейсу — найпоширеніша причина, через яку конфігурація мовчки не дає жодного ефекту:

ip link show

Перевірте, що вже є на інтерфейсі, включаючи поточні лічильники:

tc -s qdisc show dev eth0

Перед застосуванням нової конфігурації видаліть усі існуючі root qdisc, щоб уникнути RTNETLINK answers: File exists помилок:

tc qdisc del dev eth0 root 2>/dev/null || true

Якщо ви оновлюєте існуюче правило, а не створюєте його з нуля, використовуйте replace замість add для атомарного обміну.

Апаратне розвантаження, таке як TSO та GSO, об'єднує пакети у пакети таким чином, що це заважає формуванню трафіку. Вимкніть їх на інтерфейсі, для якого здійснюється формування трафіку:

sudo ethtool -K eth0 tso off gso off

Встановіть fq_codel як загальносистемний qdisc за замовчуванням для нових інтерфейсів:

sysctl -w net.core.default_qdisc=fq_codel

Для завантажених серверів поєднуйте це з алгоритмом контролю перевантаження BBR (ядро 4.9+). BBR підтримує високу пропускну здатність без збільшення черг:

sysctl -w net.ipv4.tcp_congestion_control=bbr

Один з заходів безпеки під час налаштування віддаленого комп’ютера через SSH: відкрийте другу сесію та тримайте tc qdisc del dev eth0 root готовий текст для вставки. Неправильне правило фільтрації може миттєво заблокувати вам доступ.

Регулювання вихідного трафіку за допомогою HTB

HTB дозволяє встановити для кожної послуги гарантований мінімум (rate) та максимальний обсяг (ceil). Невикористана пропускна здатність розподіляється між тими, хто її потребує, у порядку пріоритетності. Ось робоча трирівнева конфігурація для висхідного каналу 1 Гбіт/с.

Створіть кореневий qdisc HTB. Команда default 30 надсилає будь-який некласифікований пакет до класу 1:30 , а не дозволяє йому обійти ваші правила:

tc qdisc add dev eth0 root handle 1: htb default 30

Обмежте загальну пропускну здатність на рівні 900 Мбіт/с. Завжди встановлюйте значення трохи нижче фактичної пропускної здатності каналу, інакше черга утвориться на маршрутизаторі або модемі на вході, які ви не контролюєте:

tc class add dev eth0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbit

Визначте рівні обслуговування. Нижчі prio значення отримують невикористану пропускну здатність у першу чергу:

# 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 3

Додайте fq_codel як кінцевий qdisc до кожного класу, щоб жоден потік не міг домінувати у своєму рівні:

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_codel

Тепер класифікуйте трафік. Для простого зіставлення портів u32 найшвидше:

tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
  match ip dport 443 0xffff flowid 1:10

Для будь-чого, що залежить від стану, позначте в iptables і зіставте позначку з 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:20

Регулювання вхідного трафіку за допомогою IFB

Неможливо формувати вхідний трафік на рівні ядра, оскільки на момент прибуття пакета він уже використав вашу пропускну здатність. Обхідним рішенням є перенаправлення вхідного трафіку на віртуальний інтерфейс проміжного функціонального блоку (IFB), де ядро розглядає його як вихідний трафік і дозволяє застосовувати qdiscs з класами.

Завантажте модуль і ввімкніть інтерфейс:

modprobe ifb numifbs=1
ip link set dev ifb0 up

Додайте qdisc для вхідного трафіку до фізичного інтерфейсу та перенаправте весь трафік на 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

З цього моменту ifb0 поводиться як будь-який інший інтерфейс. Застосуйте до нього своє дерево HTB точно так само, як ви б це зробили для вихідного трафіку:

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 1

Встановлення пріоритетів трафіку за допомогою DSCP

DSCP (Differentiated Services Code Point) позначає пакети 6-бітним значенням у байті TOS, тому ваші tc фільтри можуть класифікувати за тегом, а не перебираючи порти у наборі правил. При зіставленні DSCP у tc, змістіть значення вліво на 2 біти. DSCP EF (46) стає 0xb8. Маска 0xfc відокремлює 6 бітів DSCP від 2 бітів ECN.

Доцільне стандартне зіставлення для серверних навантажень:

Тип трафікуDSCPTOS (шестнадцятковий)Приклади
ІнтерактивнийEF0xb8SSH, DNS, VoIP
БізнесAF410x88HTTP, HTTPS, API
МасовийCS10x20Резервне копіювання, FTP, оновлення пакетів
«Best effort»CS00x00Все інше

Позначте вихідні пакети в iptables, перш ніж вони потраплять у ваші tc фільтри:

iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 46

Потім зіставте мітку в tc і маршрутизуйте його до відповідного класу 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:30

Моніторинг та усунення несправностей

Три команди, якими ви будете постійно користуватися:

tc -s qdisc show dev eth0
tc -s class show dev eth0
tc -s filter show dev eth0

Слідкуйте за dropped та overlimits лічильники. Втрачені пакети означають, що черга переповнена; перевищення лімітів означає, що ви досягли верхньої межі класу, і ядро було змушене затримати або скинути трафік. Для перегляду в режимі реального часу:

watch -n 1 'tc -s class show dev eth0'

Додайте -d для внутрішніх параметрів (target, interval, quantum) та -j для виведення у форматі JSON, якщо ви використовуєте конвеєр у стек метрик. Поєднайте це з ss -tin , щоб бачити оцінки RTT та повторні передачі на рівні TCP.

Більшість збоїв можна звести до короткого переліку:

СимптомЙмовірна причинаВиправлення
RTNETLINK answers: File existsКореневий qdisc вже налаштованийtc qdisc del dev eth0 root Спочатку
Правила застосовуються, але трафік не обмежуєтьсяНеправильний інтерфейс або TSO/GSO все ще увімкненіПеревірте за допомогою ip link show, вимкніть розвантаження за допомогою ethtool -K
Фільтр ніколи не збігаєтьсяНеправильний синтаксис порту/IP-адреси або вирівнювання маскиДодайте контрдію та перевірте кількість збігів у tc -s filter show
Правила зникають після перезавантаженняКонфігурація зберігається лише в пам'ятіОберніть у скрипт і викликайте з systemd або диспетчера NetworkManager
Висока затримка пріоритетного трафікуВідсутність qdisc типу «leaf» або занадто низький рівень спалахуПриєднати fq_codel до класів leaf, підвищити burst

Якщо ви коли-небудь заблокуєте себе через неправильну конфігурацію, скинути налаштування просто:

tc qdisc del dev eth0 root

tc неможливо створити пропускну здатність, якої у вас немає, але на добре забезпеченому каналі зв'язку це робить різницю між передбачуваною продуктивністю та сервером, який виходить з ладу в той момент, коли один користувач починає велику передачу даних. Якщо вам потрібна необроблена пропускна здатність і свобода формувати її як завгодно, зверніть увагу на виділені сервери FDC.

Блог

На цьому тижні

Більше статей
Посібник з використання iperf3: тестування швидкості мережі в Linux та Windows
#bandwidth#server-performance

Посібник з використання iperf3: тестування швидкості мережі в Linux та Windows

Встановіть iperf3, проведіть тести пропускної здатності та налаштуйте буфери TCP для отримання точних результатів у Linux та Windows. Охоплює тестування UDP, двонаправлене тестування та тестування 10GbE+

10 хв читання - 7 травня 2026 р.

Більше статей
background image

Маєте запитання або потребуєте індивідуального рішення?

icon

Гнучкі варіанти

icon

Глобальне охоплення

icon

Миттєве розгортання

icon

Гнучкі варіанти

icon

Глобальне охоплення

icon

Миттєве розгортання