#server-performance

Control de tráfico en Linux (tc): una guía práctica

12 min de lectura - 5 de junio de 2026

hero section cover

Controla el ancho de banda, prioriza el tráfico y modula el tráfico de entrada y salida en Linux con tc. Configuraciones funcionales de HTB, IFB, DSCP y fq_codel para servidores reales.

Control de tráfico en Linux (tc): una guía práctica

El tc te permite controlar directamente cómo gestiona tu servidor el tráfico de red. Puedes limitar el ancho de banda por servicio, garantizar que las sesiones interactivas como SSH sigan respondiendo cuando se produzcan picos de transferencias masivas y regular tanto el tráfico saliente como el entrante desde una única herramienta. Esta guía abarca los conceptos básicos, una configuración funcional de HTB, la regulación del tráfico entrante 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 (direcciones 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 o redirigir.

Estos elementos forman un árbol. Los paquetes entran por el qdisc raíz, pasan por los filtros, se clasifican en clases mediante un major:minor identificador y acaban en la cola de 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 clasificarlos según la 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 núcleo puede almacenar en búfer y retrasar los paquetes salientes, lo que es lo que permite una regulación real. Los paquetes entrantes ya han atravesado la red en el momento en que los ves, por lo que solo puedes controlarlos (descartarlos por superar un umbral) a menos que los redirijas primero a un dispositivo IFB.

CaracterísticaSalidaEntrada
DirecciónSalidaEntrante
RegulaciónNativoRequiere IFB
ControlCompatibleCompatible
Uso típicoQoS, reparto de ancho de banda, control de ritmoLimitació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. Asigna siempre este qdisc como qdisc «hoja» bajo clases HTB; de lo contrario, un solo flujo «glotón» 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 sus derivados, yum install iproute. Necesitarás privilegios de root o sudo.

Averigua primero el nombre correcto de la interfaz. Indicar un nombre incorrecto para la interfaz es la razón más habitual por la que una configuración no produce ningún efecto de forma silenciosa:

ip link show

Comprueba qué hay ya en la interfaz, incluidos los contadores en tiempo real:

tc -s qdisc show dev eth0

Elimina 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 || true

Si estás actualizando una regla existente en lugar de empezar desde cero, utiliza replace en lugar de add para realizar un intercambio atómico.

La descarga de hardware, como TSO y GSO, agrupa los paquetes de forma que interfiere con el shaping. Desactívalas en la interfaz sometida a shaping:

sudo ethtool -K eth0 tso off gso off

Establece fq_codel como qdisc predeterminado para todo el sistema en las nuevas interfaces:

sysctl -w net.core.default_qdisc=fq_codel

En el caso de servidores con mucha actividad, combínalo 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=bbr

Un 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 pegarlo. Una regla de filtrado errónea puede bloquearte el acceso al instante.

Regulación del tráfico saliente con HTB

HTB 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 30

Limita 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 origen que no controlas:

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

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

Añade fq_codel como qdisc de hoja en cada clase para que un único 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_codel

Ahora clasifica el tráfico. Para una coincidencia de puertos sencilla, 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:10

Para cualquier cosa que requiera 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:20

Regulación del tráfico entrante con IFB

No es posible modelar el tráfico de entrada de forma nativa, ya que, para cuando llega un paquete, ya ha consumido tu ancho de banda. La solución consiste en redirigir el tráfico de entrada a una interfaz virtual de Bloque Funcional Intermedio (IFB), donde el núcleo lo trata como tráfico de salida y te permite aplicar qdiscs basados en clases.

Carga el módulo y activa la interfaz:

modprobe ifb numifbs=1
ip link set dev ifb0 up

Añade un qdisc de entrada a la interfaz física y redirige 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 ifb0

A 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 1

Priorizació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 tener que buscar puertos en todo el conjunto de reglas. Al comparar el DSCP en tc, desplaza el valor 2 bits hacia la izquierda. DSCP EF (46) pasa a ser 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áficoDSCPTOS hexEjemplos
InteractivoEF0xb8SSH, DNS, VoIP
EmpresarialAF410x88HTTP, HTTPS, API
MasivoCS10x20Copias de seguridad, FTP, actualizaciones de paquetes
Mejor esfuerzoCS00x00Todo 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 46

A continuación, compara la etiqueta en tc y redirígelo a la clase HTB adecuada:

# 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

Supervisió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 eth0

Observa el dropped y overlimits . Los paquetes perdidos indican que la cola está saturada; los valores por encima de los límites indican que se ha alcanzado el techo de una clase y que el núcleo 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 obtener la salida en 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 clasificar en una breve lista:

SíntomaCausa probableSolución
RTNETLINK answers: File existsEl qdisc raíz ya está configuradotc qdisc del dev eth0 root primero
Las reglas se aplican, pero el tráfico no se limitaInterfaz incorrecta, o TSO/GSO sigue activadoConfirmar con ip link show, desactiva las descargas con ethtool -K
El filtro nunca coincideSintaxis incorrecta del puerto o la IP, o alineación de la máscaraAñade una acción de contramedida y comprueba el recuento de coincidencias en tc -s filter show
Las reglas desaparecen tras el reinicioLa configuración reside únicamente en memoriaIncorpóralo en un script y llámalo desde systemd o un distribuidor de NetworkManager
Alta latencia en el tráfico prioritarioNo hay qdisc de hoja, o el burst es demasiado bajoAdjuntar 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 root

tc 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 cuanto un cliente inicia una transferencia de gran volumen. Si necesitas el ancho de banda bruto y la libertad para modelarlo como quieras, echa un vistazo a los servidores dedicados de FDC.

Blog

Destacados de la semana

Más artículos
Tutorial de iperf3: Comprobar la velocidad de red en Linux y Windows
#bandwidth#server-performance

Tutorial de iperf3: Comprobar la velocidad de red en Linux y Windows

Instala iperf3, realiza pruebas de ancho de banda y ajusta los búferes TCP para obtener resultados precisos en Linux y Windows. Abarca pruebas UDP, bidireccionales y de 10 GbE o más.

10 min de lectura - 7 de mayo de 2026

Más artículos