Controlo de tráfego Linux (tc): um guia prático
12 min de leitura - 5 de junho de 2026

Controlar a largura de banda, dar prioridade ao tráfego e modelar a entrada e saída no Linux com o tc. Configuração funcional de HTB, IFB, DSCP e fq_codel para servidores reais.
Controlo de Tráfego Linux (tc): um Guia Prático
O comando tc permite-lhe controlar diretamente a forma como o seu servidor gere o tráfego de rede. Pode limitar a largura de banda por serviço, manter sessões interativas como o SSH responsivas quando ocorrem picos de transferências em massa e moldar os fluxos de saída e de entrada a partir de uma única ferramenta. Este guia abrange os conceitos fundamentais, uma configuração HTB funcional, modelagem de entrada com IFB, priorização baseada em DSCP e como depurar quando algo falhar.
Como funciona o tc
Cada tc configuração é composta por quatro partes móveis:
- qdisc (disciplina de enfileiramento). O agendador associado a uma interface de rede. Decide como os pacotes são enfileirados e retirados da fila.
- Class. Uma subdivisão dentro de um qdisc com classes. Pense nisso como uma faixa com o seu próprio limite de velocidade.
- Filtro. Inspeciona os cabeçalhos dos pacotes (IPs, portas, marcas) e atribui cada pacote a uma classe.
- Ação. O que acontece a um pacote quando este corresponde: encaminhar, descartar, redirecionar.
Estes formam uma árvore. Os pacotes entram no qdisc raiz, passam pelos filtros, são classificados em classes por um major:minor identificador e acabam por ser enfileirados num qdisc folha para transmissão.
Para qualquer coisa mais complexa do que a correspondência baseada em porta, marque os pacotes com iptables ou nftables na tabela mangle e, em seguida, utilize o fw filtro no tc para classificar por marca. Escala muito melhor do que encadeamento de regras u32 para cada tipo de tráfego.
Saída vs. entrada
A direção importa. O kernel pode armazenar em buffer e atrasar pacotes de saída, o que é o que permite o shaping real. Os pacotes de entrada já atravessaram a rede quando os vê, pelo que só pode controlá-los (descartar acima de um limiar) a menos que os redirecione primeiro para um dispositivo IFB.
| Funcionalidade | Saída | Entrada |
|---|---|---|
| Direção | Saída | Entrada |
| Modelagem | Nativo | Requer IFB |
| Controlo | Suportado | Suportado |
| Utilização típica | QoS, partilha de largura de banda, regulação | Limitação de taxa, mitigação básica de DDoS |
Os qdiscs que irá realmente utilizar
- HTB (Hierarchical Token Bucket). Com classes. Utilize-o quando pretender largura de banda mínima garantida por serviço, com a capacidade de utilizar capacidade não utilizada de outras classes.
- TBF (Token Bucket Filter). Sem classes. Use-o quando precisar apenas de limitar toda uma interface a uma única taxa.
- fq_codel (Fair Queuing Controlled Delay). Combina equidade por fluxo com gestão ativa de filas para eliminar o bufferbloat. Tem sido o qdisc padrão na maioria das distribuições Linux desde o systemd 217 e vem como padrão no RHEL 9. Anexe-o sempre como um qdisc folha sob classes HTB; caso contrário, um único fluxo ganancioso pode monopolizar uma classe inteira.
Configurar o tc num servidor Linux
tc vem incluído no pacote iproute2. No Debian e no Ubuntu, instale-o com apt-get install iproute2. No RHEL e derivados, yum install iproute. Vai precisar de direitos de root ou sudo.
Obtenha primeiro o nome correto da interface. Nomear incorretamente a interface é a razão mais comum para uma configuração não produzir qualquer efeito:
ip link showVerifique o que já está na interface, incluindo contadores em tempo real:
tc -s qdisc show dev eth0Limpe qualquer qdisc raiz existente antes de aplicar uma nova configuração, para evitar RTNETLINK answers: File exists erros:
tc qdisc del dev eth0 root 2>/dev/null || trueSe estiver a atualizar uma regra existente em vez de começar do zero, utilize replace em vez de add para uma troca atómica.
O descarregamento de hardware, como TSO e GSO, agrupa pacotes de formas que interferem com o shaping. Desative-os na interface com shaping:
sudo ethtool -K eth0 tso off gso offDefina fq_codel como o qdisc padrão em todo o sistema para novas interfaces:
sysctl -w net.core.default_qdisc=fq_codelPara servidores ocupados, combine-o com o algoritmo de controlo de congestionamento BBR (kernel 4.9+). O BBR mantém a taxa de transferência elevada sem aumentar as filas:
sysctl -w net.ipv4.tcp_congestion_control=bbrUm hábito de segurança se estiver a configurar uma máquina remota via SSH: abra uma segunda sessão e tenha tc qdisc del dev eth0 root pronto para colar. Uma regra de filtro incorreta pode bloquear o acesso instantaneamente.
Modelar o tráfego de saída com HTB
O HTB permite atribuir a cada serviço um mínimo garantido (rate) e um limite máximo (ceil). A largura de banda não utilizada é direcionada para quem precisar, por ordem de prioridade. Aqui está uma configuração funcional de três camadas para um uplink de 1 Gbps.
Crie o qdisc HTB raiz. O default 30 envia qualquer pacote não classificado para a classe 1:30 em vez de o deixar contornar as suas regras:
tc qdisc add dev eth0 root handle 1: htb default 30Limite a taxa de transferência total a 900 Mbps. Defina sempre um valor ligeiramente abaixo da capacidade real da ligação; caso contrário, forma-se uma fila num router ou modem a montante que não controla:
tc class add dev eth0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbitDefina os níveis de serviço. Os prio obtêm a largura de banda não utilizada em primeiro lugar:
# 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 3Anexe fq_codel como qdisc de folha em cada classe para que um único fluxo não domine o seu nível:
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_codelAgora, classifique o tráfego. Para uma correspondência simples de portas, u32 é o mais rápido:
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
match ip dport 443 0xffff flowid 1:10Para qualquer coisa com estado, marque no iptables e faça a correspondência da marca com 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:20Modelar o tráfego de entrada com IFB
Não é possível moldar o tráfego de entrada de forma nativa, porque quando um pacote chega já utilizou a sua largura de banda. A solução alternativa consiste em redirecionar o tráfego de entrada para uma interface virtual de Bloco Funcional Intermédio (IFB), onde o kernel o trata como tráfego de saída e permite aplicar qdiscs com classes.
Carregue o módulo e ative a interface:
modprobe ifb numifbs=1
ip link set dev ifb0 upAdicione um qdisc de entrada à interface física e redirecione tudo para 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 ifb0A partir daqui, ifb0 comporta-se como qualquer outra interface. Aplique a sua árvore HTB a ela exatamente como faria na saída:
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 1Priorizar o tráfego com DSCP
O DSCP (Differentiated Services Code Point) marca os pacotes com um valor de 6 bits no byte TOS, pelo que os seus tc filtros possam classificar por etiqueta, em vez de procurarem portas em todo o conjunto de regras. Ao corresponder o DSCP em tc, desloque o valor 2 bits para a esquerda. O DSCP EF (46) passa a ser 0xb8. A máscara 0xfc isola os 6 bits DSCP dos 2 bits ECN.
Um mapeamento padrão sensato para cargas de trabalho de servidor:
| Tipo de tráfego | DSCP | TOS hex | Exemplos |
|---|---|---|---|
| Interativo | EF | 0xb8 | SSH, DNS, VoIP |
| Negócios | AF41 | 0x88 | HTTP, HTTPS, APIs |
| Em massa | CS1 | 0x20 | Cópias de segurança, FTP, atualizações de pacotes |
| Melhor esforço | CS0 | 0x00 | Tudo o resto |
Marque os pacotes de saída no iptables antes de atingirem os seus tc filtros:
iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 46Em seguida, compare a tag no tc e encaminhe-o para a classe HTB correta:
# 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:30Monitorização e resolução de problemas
Os três comandos que irá utilizar constantemente:
tc -s qdisc show dev eth0
tc -s class show dev eth0
tc -s filter show dev eth0Observe o dropped e overlimits . Pacotes perdidos significam que a fila está saturada; valores acima do limite significam que atingiu o limite da classe e o kernel teve de atrasar ou descartar tráfego. Para uma visualização em tempo real:
watch -n 1 'tc -s class show dev eth0'Adicione -d para parâmetros internos (alvo, intervalo, quantum) e -j para saída JSON se estiver a canalizar para uma pilha de métricas. Combine-o com ss -tin para ver estimativas de RTT e retransmissões na camada TCP.
A maioria das falhas enquadra-se numa lista curta:
| Sintoma | Causa provável | Solução |
|---|---|---|
RTNETLINK answers: File exists | qdisc raiz já configurado | tc qdisc del dev eth0 root primeiro |
| As regras aplicam-se, mas o tráfego não é limitado | Interface errada ou TSO/GSO ainda ativado | Confirmar com ip link show, desative os offloads com ethtool -K |
| O filtro nunca corresponde | Sintaxe incorreta da porta/IP ou alinhamento da máscara | Adicione uma ação de contagem e verifique a contagem de ocorrências em tc -s filter show |
| Regras desaparecidas após o reinício | A configuração reside apenas na memória | Incorpore num script e chame a partir do systemd ou de um despachante do NetworkManager |
| Alta latência no tráfego prioritário | Sem qdisc de folha ou burst muito baixo | Ligar fq_codel às classes leaf, aumente burst |
Se alguma vez ficar bloqueado devido a uma configuração incorreta, a redefinição é simples:
tc qdisc del dev eth0 roottc não é possível criar largura de banda que não se tem, mas numa ligação ascendente bem provisionada isso faz a diferença entre um desempenho previsível e um servidor que entra em colapso no momento em que um utilizador inicia uma transferência de grandes dimensões. Se precisar de largura de banda bruta e da liberdade de a moldar como quiser, dê uma vista de olhos aos servidores dedicados da FDC.

Controlo de tráfego Linux (tc): um guia prático
Controlar a largura de banda, dar prioridade ao tráfego e modelar a entrada e saída no Linux com o tc. Configuração funcional de HTB, IFB, DSCP e fq_codel para servidores reais.
12 min de leitura - 5 de junho de 2026
Porque é que é importante ter um VPS potente e ilimitado
7 min de leitura - 9 de maio de 2025