Linux Traffic Control (tc): una guía práctica
12 min de lectura - 5 de junio de 2026

Controle el ancho de banda, priorice el tráfico y configure la entrada y salida en Linux con tc. Configuración de HTB, IFB, DSCP y fq_codel para servidores reales.
Control de tráfico en Linux (tc): una guía práctica
El comando tc te permite controlar directamente cómo gestiona tu servidor el tráfico de red. Puedes limitar el ancho de banda por servicio, mantener la capacidad de respuesta de sesiones interactivas como SSH cuando se producen picos de transferencias masivas y modelar los flujos de salida y de entrada desde una única herramienta. Esta guía abarca los conceptos básicos, una configuración funcional de HTB, el modelado de entrada con IFB, la priorización basada en DSCP y cómo depurarla cuando algo falla.
Cómo funciona tc
Cada tc configuración se compone de cuatro elementos:
- qdisc (disciplina de colas). El programador asociado a una interfaz de red. Decide cómo se colocan y se retiran los paquetes de la cola.
- Clase. Una subdivisión dentro de un qdisc con clases. Piensa en ello como un carril con su propio límite de velocidad.
- Filtro. Inspecciona las cabeceras de los paquetes (IP, puertos, marcas) y asigna cada paquete a una clase.
- Acción. Lo que ocurre con un paquete una vez que cumple los criterios: reenviar, descartar, redirigir.
Estos elementos forman un árbol. Los paquetes entran en el qdisc raíz, pasan por los filtros, se clasifican en clases mediante un major:minor identificador y terminan en cola en un qdisc de hoja para su transmisión.
Para cualquier cosa más compleja que la coincidencia basada en puertos, marca los paquetes con iptables o nftables en la tabla mangle y, a continuación, utiliza el fw filtro de tc para clasificar por marca. Se adapta mucho mejor que encadenar reglas sin procesar u32 para cada tipo de tráfico.
Salida frente a entrada
La dirección importa. El kernel puede almacenar en búfer y retrasar los paquetes salientes, lo que es lo que permite el shaping real. Los paquetes entrantes ya han cruzado el cable en el momento en que los ves, por lo que solo puedes controlarlos (descartarlos por encima de un umbral) a menos que los redirijas primero a un dispositivo IFB.
| Característica | Salida | Entrada |
|---|---|---|
| Dirección | Salida | Entrante |
| Modelado | Nativo | Requiere IFB |
| Control | Compatible | Compatible |
| Uso típico | QoS, reparto de ancho de banda, control de velocidad | Limitación de velocidad, mitigación básica de DDoS |
Los qdiscs que realmente utilizarás
- HTB (Hierarchical Token Bucket). Con clases. Úsalo cuando quieras garantizar un ancho de banda mínimo por servicio con la posibilidad de tomar prestada la capacidad no utilizada de otras clases.
- TBF (Token Bucket Filter). Sin clases. Úsalo cuando solo necesites limitar toda una interfaz a una única velocidad.
- fq_codel (Fair Queuing Controlled Delay). Combina la equidad por flujo con la gestión activa de colas para eliminar el bufferbloat. Ha sido el qdisc predeterminado en la mayoría de las distribuciones de Linux desde systemd 217 y viene por defecto en RHEL 9. Adjúntalo siempre como un qdisc hoja bajo clases HTB; de lo contrario, un solo flujo codicioso puede acaparar toda una clase.
Configuración de tc en un servidor Linux
tc se incluye con el paquete iproute2. En Debian y Ubuntu, instálalo con apt-get install iproute2. En RHEL y derivados, yum install iproute. Necesitarás privilegios de root o sudo.
Averigua primero el nombre correcto de la interfaz. Ponerle un nombre incorrecto a la interfaz es la razón más común por la que una configuración no hace nada sin avisar:
ip link showComprueba lo que ya hay en la interfaz, incluidos los contadores en tiempo real:
tc -s qdisc show dev eth0Borra cualquier qdisc de raíz existente antes de aplicar una nueva configuración, para evitar RTNETLINK answers: File exists errores:
tc qdisc del dev eth0 root 2>/dev/null || trueSi estás actualizando una regla existente en lugar de empezar desde cero, utiliza replace en lugar de add para un intercambio atómico.
La descarga de hardware, como TSO y GSO, agrupa los paquetes de formas que interfieren con el shaping. Desactívalas en la interfaz con shaping:
sudo ethtool -K eth0 tso off gso offEstablece fq_codel como qdisc predeterminado para todo el sistema en las nuevas interfaces:
sysctl -w net.core.default_qdisc=fq_codelPara servidores con mucha actividad, combínelo con el algoritmo de control de congestión BBR (kernel 4.9+). BBR mantiene un alto rendimiento sin que crezcan las colas:
sysctl -w net.ipv4.tcp_congestion_control=bbrUn hábito de seguridad si estás configurando un equipo remoto a través de SSH: abre una segunda sesión y ten tc qdisc del dev eth0 root listo para pegar. Una regla de filtrado incorrecta puede bloquearte al instante.
Modelado del tráfico saliente con HTB
HTB te permite asignar a cada servicio un mínimo garantizado (rate) y un límite máximo (ceil). El ancho de banda no utilizado se destina a quien lo necesite, por orden de prioridad. A continuación se muestra una configuración funcional de tres niveles para un enlace ascendente de 1 Gbps.
Crea el qdisc HTB raíz. El default 30 envía cualquier paquete no clasificado a la clase 1:30 en lugar de permitir que eluda tus reglas:
tc qdisc add dev eth0 root handle 1: htb default 30Limita el rendimiento total a 900 Mbps. Ajusta siempre el ancho de banda ligeramente por debajo de la capacidad real del enlace; de lo contrario, se formará una cola en un router o módem de upstream que no controlas:
tc class add dev eth0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbitDefine los niveles de servicio. Los prio obtienen primero el ancho de banda no utilizado:
# 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 3Añade fq_codel como qdisc de hoja en cada clase para que un solo flujo no pueda dominar su nivel:
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_codelAhora clasifica el tráfico. Para una simple coincidencia de puertos, u32 es lo más rápido:
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
match ip dport 443 0xffff flowid 1:10Para cualquier cosa con estado, marca en iptables y haz coincidir la marca con 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:20Modelado del tráfico entrante con IFB
No se puede modelar el tráfico entrante de forma nativa porque, para cuando llega un paquete, ya ha consumido su ancho de banda. La solución consiste en redirigir el tráfico entrante a una interfaz virtual de bloque funcional intermedio (IFB), donde el núcleo lo trata como tráfico saliente y permite aplicar qdiscs con clases.
Cargue el módulo y active la interfaz:
modprobe ifb numifbs=1
ip link set dev ifb0 upAñada un qdisc de entrada a la interfaz física y redirija todo a 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 de aquí, ifb0 se comporta como cualquier otra interfaz. Aplícale tu árbol HTB exactamente igual que lo harías en el tráfico de salida:
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 1Priorización del tráfico con DSCP
El DSCP (Differentiated Services Code Point) etiqueta los paquetes con un valor de 6 bits en el byte TOS, por lo que tus tc filtros puedan clasificar por etiqueta en lugar de buscar puertos en el conjunto de reglas. Al hacer coincidir el DSCP en tc, desplaza el valor 2 bits a la izquierda. DSCP EF (46) se convierte en 0xb8. La máscara 0xfc aisla los 6 bits de DSCP de los 2 bits de ECN.
Una asignación predeterminada razonable para cargas de trabajo de servidor:
| Tipo de tráfico | DSCP | TOS hex | Ejemplos |
|---|---|---|---|
| Interactivo | EF | 0xb8 | SSH, DNS, VoIP |
| Negocios | AF41 | 0x88 | HTTP, HTTPS, API |
| Masivo | CS1 | 0x20 | Copias de seguridad, FTP, actualizaciones de paquetes |
| Mejor esfuerzo | CS0 | 0x00 | Todo lo demás |
Etiqueta los paquetes salientes en iptables antes de que lleguen a tus tc filtros:
iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 46A continuación, compara la etiqueta en tc y redirígelo a la clase HTB correcta:
# 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:30Supervisión y resolución de problemas
Los tres comandos que utilizarás constantemente:
tc -s qdisc show dev eth0
tc -s class show dev eth0
tc -s filter show dev eth0Observa el dropped y overlimits . Los paquetes perdidos indican que la cola está saturada; los valores por encima del límite significan que has alcanzado el techo de la clase y el kernel ha tenido que retrasar o descartar tráfico. Para una vista en tiempo real:
watch -n 1 'tc -s class show dev eth0'Añade -d para los parámetros internos (target, interval, quantum) y -j para la salida JSON si estás canalizando los datos a una pila de métricas. Combínalo con ss -tin para ver estimaciones de RTT y retransmisiones en la capa TCP.
La mayoría de los fallos se pueden resumir en una breve lista:
| Síntoma | Causa probable | Solución |
|---|---|---|
RTNETLINK answers: File exists | Qdisc raíz ya configurado | tc qdisc del dev eth0 root primero |
| Las reglas se aplican, pero el tráfico no está limitado | Interfaz incorrecta, o TSO/GSO aún activado | Confirmar con ip link show, desactivar descargas con ethtool -K |
| El filtro nunca coincide | Sintaxis incorrecta del puerto/IP o alineación de la máscara | Añade una acción de contador y comprueba el recuento de aciertos en tc -s filter show |
| Las reglas desaparecen tras el reinicio | La configuración reside solo en memoria | Envuélvelo en un script y llámalo desde systemd o un distribuidor de NetworkManager |
| Alta latencia en el tráfico prioritario | No hay qdisc de hoja, o el burst es demasiado bajo | Adjuntar fq_codel a clases leaf, aumentar burst |
Si alguna vez te quedas bloqueado por una configuración errónea, el restablecimiento es sencillo:
tc qdisc del dev eth0 roottc no se puede generar ancho de banda que no se tiene, pero en un enlace ascendente bien aprovisionado marca la diferencia entre un rendimiento predecible y un servidor que se colapsa en el momento en que un cliente inicia una transferencia de gran tamaño. Si necesitas el ancho de banda bruto y la libertad de configurarlo como quieras, echa un vistazo a los servidores dedicados de FDC.

Linux Traffic Control (tc): una guía práctica
Controle el ancho de banda, priorice el tráfico y configure la entrada y salida en Linux con tc. Configuración de HTB, IFB, DSCP y fq_codel para servidores reales.
12 min de lectura - 5 de junio de 2026
Por qué es importante tener un VPS potente y sin contador
7 min de lectura - 9 de mayo de 2025