Linux Traffic Control (tc): практическое руководство
12 мин чтения - 5 июня 2026 г.

Контролируйте пропускную способность, устанавливайте приоритеты трафика, формируйте входящий и исходящий трафик в Linux с помощью tc. Рабочие конфигурации HTB, IFB, DSCP и fq_codel для реальных серверов.
Управление трафиком в Linux (tc): практическое руководство
Команда tc позволяет напрямую контролировать, как ваш сервер обрабатывает сетевой трафик. Вы можете ограничить пропускную способность для каждого сервиса, обеспечить отзывчивость интерактивных сессий, таких как SSH, при всплесках массовых передач данных, а также формировать как исходящие, так и входящие потоки с помощью одного инструмента. В этом руководстве рассматриваются основные концепции, рабочая настройка HTB, формирование входящего трафика с помощью IFB, приоритезация на основе DSCP, а также способы отладки в случае сбоев.
Как работает tc
Каждая tc конфигурация состоит из четырех компонентов:
- qdisc (дисциплина очереди). Планировщик, привязанный к сетевому интерфейсу. Он определяет, как пакеты помещаются в очередь и извлекаются из нее.
- Class. Подразделение внутри qdisc с классами. Представьте себе это как полосу движения со своим собственным ограничением скорости.
- Filter. Проверяет заголовки пакетов (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.
Разумное сопоставление по умолчанию для серверных рабочих нагрузок:
| Тип трафика | DSCP | TOS (шестнадцатеричный) | Примеры |
|---|---|---|---|
| Интерактивный | EF | 0xb8 | SSH, DNS, VoIP |
| Бизнес | AF41 | 0x88 | HTTP, HTTPS, API |
| Массовая рассылка | CS1 | 0x20 | Резервное копирование, FTP, обновления пакетов |
| По возможности | CS0 | 0x00 | Все остальное |
Помечайте исходящие пакеты в 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 | Root 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 roottc невозможно создать пропускную способность, которой у вас нет, но на хорошо обеспеченном восходящем канале это определяет разницу между предсказуемой производительностью и сервером, который выходит из строя в тот момент, когда один из клиентов начинает крупную передачу данных. Если вам нужна исходная пропускная способность и свобода формировать ее так, как вам нравится, обратите внимание на выделенные серверы FDC.

Linux Traffic Control (tc): практическое руководство
Контролируйте пропускную способность, устанавливайте приоритеты трафика, формируйте входящий и исходящий трафик в Linux с помощью tc. Рабочие конфигурации HTB, IFB, DSCP и fq_codel для реальных серверов.
12 мин чтения - 5 июня 2026 г.
Почему важно иметь мощный и не тарифицируемый VPS
7 мин чтения - 9 мая 2025 г.

У вас есть вопросы или вам нужно индивидуальное решение?
Гибкие варианты
Глобальный охват
Мгновенное развертывание
Гибкие варианты
Глобальный охват
Мгновенное развертывание