Controlo de Tráfego no Linux (tc): um Guia Prático
12 min de leitura - 5 de junho de 2026

Controlar a largura de banda, priorizar o tráfego e moldar o tráfego de entrada e saída no Linux com o tc. Configurações funcionais de HTB, IFB, DSCP e fq_codel para servidores reais.
Controlo de Tráfego no 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 aborda os conceitos fundamentais, uma configuração funcional do HTB, o shaping de entrada com IFB, a priorização baseada em DSCP e como depurar o sistema quando algo falhar.
Como funciona o tc
Cada tc configuração é composta por quatro componentes:
- qdisc (disciplina de enfileiramento). O agendador associado a uma interface de rede. É ele que determina como os pacotes são colocados na fila e retirados da mesma.
- Classe. Uma subdivisão dentro de um qdisc com classes. Pense nela como uma faixa de rodagem com o seu próprio limite de velocidade.
- Filtro. Inspeciona os cabeçalhos dos pacotes (endereços IP, portas, marcas) e atribui cada pacote a uma classe.
- Ação. O que acontece a um pacote quando este corresponde a um critério: encaminhar, descartar, redirecionar.
Estes elementos 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 colocados na fila de um qdisc folha para transmissão.
Para qualquer coisa mais complexa do que a correspondência baseada em portas, marque os pacotes com o iptables ou o nftables na tabela mangle e, em seguida, utilize o fw filtro tc para classificar por marca. Tem uma escalabilidade muito superior à de encadeamento de regras u32 para cada tipo de tráfego.
Saída vs. entrada
A direção é importante. O kernel pode armazenar em buffer e atrasar os pacotes de saída, o que permite uma verdadeira regulação do tráfego. Os pacotes de entrada já atravessaram a rede quando os vemos, pelo que só é possível controlá-los (descartá-los acima de um limiar) a menos que os redirecionemos primeiro para um dispositivo IFB.
| Funcionalidade | Saída | Entrada |
|---|---|---|
| Direção | Saída | Entrada |
| Regulação | Nativo | Requer IFB |
| Controlo de tráfego | Compatível | Compatível |
| Utilização típica | QoS, partilha de largura de banda, regulação de tráfego | 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 garantir uma largura de banda mínima por serviço, com a capacidade de utilizar a capacidade não utilizada de outras classes.
- TBF (Token Bucket Filter). Sem classes. Utilize-o quando precisar apenas de limitar toda uma interface a uma única taxa.
- fq_codel (Fair Queuing Controlled Delay). Combina a equidade por fluxo com a gestão ativa de filas para eliminar o «bufferbloat». Tem sido o qdisc predefinido na maioria das distribuições Linux desde o systemd 217 e vem predefinido 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. Necessitará de direitos de root ou do sudo.
Verifique primeiro o nome correto da interface. Indicar o nome errado da interface é a razão mais comum para uma configuração não ter qualquer efeito:
ip link showVerifique o que já se encontra na interface, incluindo os contadores em tempo real:
tc -s qdisc show dev eth0Limpe qualquer qdisc de 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 o TSO e o GSO, agrupa os pacotes de forma a interferir com o shaping. Desative-os na interface sujeita a shaping:
sudo ethtool -K eth0 tso off gso offDefina fq_codel como qdisc predefinido a nível do sistema para novas interfaces:
sysctl -w net.core.default_qdisc=fq_codelPara servidores com elevado tráfego, 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 um equipamento remoto via SSH: abra uma segunda sessão e tenha tc qdisc del dev eth0 root pronto para colar. Uma regra de filtragem incorreta pode bloquear o acesso instantaneamente.
Regulação do 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 é redirecionada para quem precisar, por ordem de prioridade. Aqui está uma configuração funcional de três níveis 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 a taxa 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 prioridade na largura de banda não utilizada:
# 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 que envolva estado, marque no iptables e faça corresponder a 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:20Regulação do 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 do 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. Aplica a tua árvore HTB a ela exatamente como farias 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 1Priorização do 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 terem de procurar portas em todo o conjunto de regras. Ao fazer a correspondência do 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 do DSCP dos 2 bits do ECN.
Um mapeamento predefinido 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 estes atingirem os seus tc filtros:
iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 46Em seguida, compare a etiqueta 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 contadores. Pacotes perdidos significam que a fila está saturada; valores acima do limite significam que atingiu o teto da classe e que 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 em JSON, se estiver a canalizar os dados 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 | Confirme 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 contra-medida e verifique o número 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 |
| Latência elevada no tráfego prioritário | Sem qdisc «leaf» ou burst demasiado 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 assim que um utilizador inicia uma transferência de grandes dimensões. Se precisar de largura de banda bruta e da liberdade para a moldar como quiser, dê uma vista de olhos aos servidores dedicados da FDC.

Tutorial do iperf3: Testar a velocidade da rede no Linux e no Windows
Instale o iperf3, execute testes de largura de banda e ajuste os buffers TCP para obter resultados precisos no Linux e no Windows. Abrange testes UDP, bidirecionais e de 10 GbE+.
10 min de leitura - 7 de maio de 2026
Perfis otimizados para a otimização da carga de trabalho de servidores Linux
16 min de leitura - 9 de junho de 2026