Debian/Ubuntu Timeouts aleatorios: Rastrear la ruta de red con mtr y tcpdump (Caso #4)

¿Te fue útil?

Los timeouts aleatorios son el peor tipo de interrupción: demasiado pequeños para provocar un pico claro en el gráfico, demasiado frecuentes para ignorarlos y con la sincronización perfecta para afectar a quien está de guardia y a quien hace una demostración. Tus sistemas de monitorización dicen “latencia elevada”, tu aplicación dice “upstream timed out” y tus usuarios dicen “está roto”, con la seguridad de quien nunca ha tenido que perseguir un paquete a través de tres redes y un balanceador.

Este caso trata de hacer lo aburrido pero fiable: rastrear la ruta con mtr, capturar la verdad con tcpdump y luego arreglar la causa real —no lo último que tocaste. Trataremos Debian/Ubuntu como la sala de operaciones y la red como el paciente que “se olvida” de mencionar que además fuma.

Guion de diagnóstico rápido

Cuando los timeouts son “aleatorios”, el patrón real suele estar oculto por los promedios. Tu trabajo es forzar al sistema a mostrar sus cartas.
Este es el orden que encuentra rápidamente los cuellos de botella, sin perder un día discutiendo con los paneles.

1) Confirma el alcance en 5 minutos

  • ¿Un host o muchos? Si es una VM, piensa en la NIC del host, el driver, el MTU, el firewall local/conntrack. Si es todo un nivel de servicio, piensa en la ruta, el LB, el DNS y el upstream.
  • ¿Un destino o muchos? Si solo es un upstream, céntrate en esa ruta. Si son muchos, sospecha de la pila de red local, el resolvedor o el egress.
  • ¿TCP, UDP o ambos? Cuando es solo TCP suele oler a MSS/MTU, firewall stateful, conntrack o tormentas de retransmisiones. UDP solo apunta a DNS, QUIC o límites por tasa.

2) Reproduce desde la máquina que hace timeouts

  • Ejecuta una sonda a nivel de aplicación (curl con tiempos) y una sonda a nivel de paquetes (tcpdump) al mismo tiempo.
  • Recoge una captura pequeña (30–60 segundos) durante una ventana de fallo. No “captures todo el día” a menos que te guste explicar el uso de disco.

3) Rastrear la ruta con mtr, pero usa el protocolo correcto

  • Usa mtr -T (TCP) al puerto real que usa tu app cuando ICMP está filtrado o depriorizado.
  • Compara desde dos puntos: el host fallando y un par saludable en la misma subred/VPC.

4) Identifica en cuál de estos cubos estás

  • Pérdida en el último salto (destino): problema real o limitación por tasa en el destino.
  • Pérdida que empieza a mitad de camino y persiste: pérdida real en tránsito o congestión.
  • Pérdida solo en un salto intermedio: normalmente limitación de ICMP; ignora a menos que latencia/pérdida también aparezcan río abajo.
  • Sin pérdida, pero picos de latencia: bufferbloat, cola, problemas de interrupciones en CPU o retransmisiones ocultas por ICMP.
  • Parece limpio, pero la app hace timeout: agujero PMTU, enrutamiento asimétrico, drops por conntrack o rarezas DNS/Happy Eyeballs.

5) Haz el cambio más pequeño que pruebe causalidad

  • Reduce MSS, ajusta MTU, cambia el resolvedor, fija la interfaz, cambia la preferencia de ruta o deshabilita offload (temporalmente) para probar una hipótesis.
  • No despliegues una “refactorización de red” para arreglar un timeout. Eso no es ingeniería; es arte performativo.

Un modelo mental práctico de los timeouts aleatorios

Un timeout no es una única falla. Es el síntoma final de algo que tarda demasiado: un SYN sin respuesta, una consulta DNS atascada, una petición retransmitiéndose, un ACK retrasado detrás de una cola congestionada, un descubrimiento PMTU que nunca termina o un firewall stateful que silenciosamente descarta paquetes “raros” porque puede.

Los timeouts aleatorios suelen tener una de cuatro formas:

  1. Pérdida microscópica con reintentos: no la notas hasta que el tráfico sube o los timeouts se acortan.
  2. Colas en ráfaga: un enlace o NIC virtual se congestiona, los paquetes se quedan en buffers, la latencia se dispara y luego “se recupera”.
  3. Inconsistencia de ruta: ECMP, enrutamiento asimétrico o rutas inestables envían algunos flujos por un carril malo.
  4. Desajuste de protocolo: MTU/MSS, bugs de checksum/offload o comportamientos de firewall/conntrack que solo aparecen bajo ciertos tamaños o tasas de paquetes.

La clave es dejar de pensar en “la red” y empezar a pensar en flujos. Un flujo puede estar roto mientras otros parecen bien, especialmente cuando hay balanceadores, NAT o ECMP. Por eso capturas paquetes y buscas retransmisiones, resets y bloqueos.

Hechos y contexto que mejoran tu juicio

  • Traceroute es anterior a la mayoría de equipos SRE de producción. Se creó a finales de los 80 para depurar enrutamiento y alcanzabilidad usando el comportamiento de expiración del TTL.
  • mtr es básicamente “traceroute con memoria”. Muestrea continuamente y muestra tendencias—perfecto para problemas intermitentes.
  • ICMP suele tratarse como tráfico de segunda clase. Muchos routers limitan la tasa de respuestas ICMP, por lo que mtr basado en ICMP puede mostrar “pérdida” que no es pérdida real para TCP.
  • El descubrimiento de PMTU depende de ICMP “Fragmentation Needed”. Si esos ICMP están bloqueados, puedes tener un agujero PMTU: paquetes pequeños funcionan y los grandes se quedan colgados.
  • Las retransmisiones TCP son normales—hasta que no lo son. Unas pocas retransmisiones ocurren en redes sanas; retransmisiones sostenidas indican pérdida o reordenamiento severo.
  • conntrack de Linux tiene tablas finitas. Cuando las tablas se llenan, no obtienes un error bonito. Obtienes drops que parecen “aleatorios”.
  • ECMP puede hacer que la depuración parezca gaslighting. Dos sondas consecutivas pueden tomar rutas distintas; una ruta puede estar bien y la otra ser patológica.
  • Los offloads pueden confundir las capturas. GRO/TSO pueden hacer que tcpdump muestre segmentos gigantes que nunca salen por la interfaz así, a menos que lo tengas en cuenta.
  • Los timeouts DNS pueden disfrazarse de “timeouts de red”. Tu app puede reportar timeouts upstream cuando en realidad está atascada resolviendo nombres.

Tareas prácticas: comandos, salidas y decisiones

Estas son tareas de campo. Cada una incluye: un comando ejecutable, qué significa la salida y qué decides después.
Ejecútalas desde el host que experimenta timeouts. Si es posible, ejecuta el mismo conjunto desde un host “sano” en la misma red para comparar.

Task 1: Confirmar interfaz, IP y ruta por defecto

cr0x@server:~$ ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128
ens5             UP             10.20.4.17/24 fe80::5054:ff:fe12:3456/64
cr0x@server:~$ ip route show default
default via 10.20.4.1 dev ens5 proto dhcp src 10.20.4.17 metric 100

Significado: Sabes qué interfaz importa y por dónde sale el tráfico. Si tienes múltiples rutas por defecto, has encontrado una causa probable.
Decisión: Si el enrutamiento es ambiguo (múltiples defaults, policy routing), captura la selección de ruta con ip route get (Task 2) y busca enrutamiento asimétrico.

Task 2: Verificar la selección de ruta al destino fallido

cr0x@server:~$ ip route get 203.0.113.10
203.0.113.10 via 10.20.4.1 dev ens5 src 10.20.4.17 uid 1000
    cache

Significado: Confirma la interfaz de egress y el gateway para esa IP.
Decisión: Si esto varía entre ejecuciones, sospecha de policy routing, múltiples tablas o ECMP en tu borde. Si la IP origen es inesperada, corrige el enrutamiento basado en origen.

Task 3: Revisar contadores a nivel de enlace para drops y errores

cr0x@server:~$ ip -s link show dev ens5
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
    RX:  bytes packets errors dropped  missed   mcast
    987654321 1234567      0    1423       0   12345
    TX:  bytes packets errors dropped carrier collsns
    876543210 1122334      0       7       0       0

Significado: Drops a nivel de NIC pueden causar retransmisiones y timeouts. Los errores son peores.
Decisión: Si las caídas RX suben durante incidentes, sospecha congestión en el host, límites de ring buffer o problemas de NIC virtual. Pasa a Task 11 (estadísticas de interrupt/softnet) y Task 12 (qdisc/cola).

Task 4: Validar DNS rápidamente (porque miente silenciosamente)

cr0x@server:~$ resolvectl status
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Current DNS Server: 10.20.4.53
       DNS Servers: 10.20.4.53 10.20.4.54
cr0x@server:~$ getent ahostsv4 api.example.internal
10.60.8.21      STREAM api.example.internal
10.60.8.21      DGRAM
10.60.8.21      RAW

Significado: El resolvedor es systemd-resolved y tienes dos servidores DNS. El nombre se resuelve rápido.
Decisión: Si getent se cuelga o falla intermitentemente, arregla DNS antes de tocar la ruta de red. Si DNS está sólido, continúa.

Task 5: Tiempos a nivel de aplicación con curl (identifica qué fase se atasca)

cr0x@server:~$ curl -sS -o /dev/null -w 'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n' https://203.0.113.10:443/health
dns:0.000 connect:0.214 tls:0.000 ttfb:2.997 total:3.002

Significado: DNS es instantáneo, el connect TCP tardó 214ms y el tiempo hasta el primer byte es ~3s. Eso no es un connect timeout; es un stall en la respuesta del servidor o pérdida downstream después de la conexión.
Decisión: Captura paquetes durante esta petición exacta (Task 9) y ejecuta mtr basado en TCP al puerto 443 (Task 7).

Task 6: mtr con ICMP para obtener una primera forma

cr0x@server:~$ mtr -n -r -c 50 203.0.113.10
Start: 2025-12-30T10:14:02+0000
HOST: server                      Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 10.20.4.1                  0.0%    50    0.3   0.4   0.2   1.8   0.3
  2.|-- 10.20.0.1                  0.0%    50    0.5   0.6   0.4   2.0   0.3
  3.|-- 192.0.2.9                  6.0%    50    1.2   1.3   0.9  12.4   1.6
  4.|-- 198.51.100.14              0.0%    50    2.1   2.4   1.8  15.6   2.1
  5.|-- 203.0.113.10               2.0%    50    2.7   3.1   2.2  48.0   6.7

Significado: Aparece algo de pérdida en el salto 3 y en el destino. Pero la pérdida medida con ICMP puede ser por limitación de tasa.
Decisión: Repite con mtr TCP al puerto real (Task 7). Si TCP muestra la misma pérdida/picos, trata como real. Si no, deja de culpar al salto 3.

Task 7: mtr con SYN TCP al puerto real del servicio

cr0x@server:~$ mtr -n -T -P 443 -r -c 50 203.0.113.10
Start: 2025-12-30T10:15:31+0000
HOST: server                      Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 10.20.4.1                  0.0%    50    0.5   0.6   0.3   3.1   0.6
  2.|-- 10.20.0.1                  0.0%    50    0.7   0.8   0.5   4.8   0.8
  3.|-- 192.0.2.9                  0.0%    50    1.4   1.5   1.0   6.5   0.9
  4.|-- 198.51.100.14              0.0%    50    2.2   2.6   1.9  21.0   2.9
  5.|-- 203.0.113.10               4.0%    50    3.0   6.8   2.4  98.7  17.2

Significado: Ahora la pérdida aparece solo en el destino y la latencia media es fea con un peor caso desagradable. Eso es consistente con dolor real en la aplicación.
Decisión: Pasa de “sospecha de ruta” a “verdad del flujo”. Captura retransmisiones TCP y bloqueos (Task 9/10). También prueba MTU/PMTUD (Task 8).

Task 8: Comprobar MTU y comportamiento PMTUD (el clásico agujero)

cr0x@server:~$ ip link show dev ens5 | sed -n '1p'
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
cr0x@server:~$ ping -M do -s 1472 -c 3 203.0.113.10
PING 203.0.113.10 (203.0.113.10) 1472(1500) bytes of data.
1472 bytes from 203.0.113.10: icmp_seq=1 ttl=54 time=3.11 ms
1472 bytes from 203.0.113.10: icmp_seq=2 ttl=54 time=3.08 ms
1472 bytes from 203.0.113.10: icmp_seq=3 ttl=54 time=3.06 ms

--- 203.0.113.10 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms

Significado: El path de 1500 bytes funciona para ICMP. Eso no garantiza que PMTUD funcione para TCP, pero es una buena señal.
Decisión: Si esto falla con “Frag needed”, reduce el tamaño hasta que pase y compáralo con lo esperado. Si se queda colgado (sin respuestas), sospecha bloqueo de ICMP a mitad de camino y considera clamping de MSS (sección de Fixes).

Task 9: Capturar tráfico para un destino (tcpdump focalizado)

cr0x@server:~$ sudo tcpdump -i ens5 -nn -s 0 -w /tmp/case4_443.pcap 'host 203.0.113.10 and tcp port 443'
tcpdump: listening on ens5, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C
1458 packets captured
1492 packets received by filter
0 packets dropped by kernel

Significado: Tienes una captura limpia con cero drops del kernel. Eso importa: las pérdidas en la captura te hacen acusar a la red por tu propio problema de CPU.
Decisión: Si tcpdump reporta drops del kernel, reduce el alcance de la captura, aumenta buffers o arregla la congestión del host (Task 11). Luego analiza retransmisiones (Task 10).

Task 10: Detectar retransmisiones y resets (método rápido sin tshark)

cr0x@server:~$ sudo tcpdump -nn -tt -r /tmp/case4_443.pcap 'tcp[tcpflags] & (tcp-rst) != 0 or tcp[13] & 0x10 != 0' | head
1735553741.102134 IP 10.20.4.17.51322 > 203.0.113.10.443: Flags [S], seq 240112233, win 64240, options [mss 1460,sackOK,TS val 111 ecr 0,nop,wscale 7], length 0
1735553741.316902 IP 203.0.113.10.443 > 10.20.4.17.51322: Flags [S.], seq 99112233, ack 240112234, win 65535, options [mss 1380,sackOK,TS val 222 ecr 111,nop,wscale 8], length 0
1735553741.317001 IP 10.20.4.17.51322 > 203.0.113.10.443: Flags [.], ack 1, win 502, options [nop,nop,TS val 112 ecr 222], length 0

Significado: Buscas patrones: retransmisiones SYN, retransmisiones de datos, ACK duplicados y RSTs. El fragmento anterior muestra un handshake normal, y el servidor anuncia MSS 1380 (interesante).
Decisión: Si ves SYN repetidos sin SYN-ACK, es alcanzabilidad/filtrado. Si ves retransmisiones de datos y tormentas de ACK duplicados, es pérdida/cola. Si MSS es inesperadamente baja, investiga MTU o overhead de túnel.

Task 11: Revisar drops del softnet backlog (el host puede ser el cuello)

cr0x@server:~$ awk '{print "cpu"NR-1, "processed="$1, "dropped="$2, "time_squeeze="$3}' /proc/net/softnet_stat | head
cpu0 processed=12345678 dropped=12 time_squeeze=34
cpu1 processed=12233445 dropped=0 time_squeeze=0
cpu2 processed=11999887 dropped=0 time_squeeze=2
cpu3 processed=12111222 dropped=9 time_squeeze=17

Significado: Drops/time_squeeze indican que el kernel no puede seguir el ritmo del procesamiento de paquetes en algunas CPUs. Eso produce pérdida “aleatoria” desde la perspectiva de la app.
Decisión: Si esto se dispara durante incidentes, arregla el host: afinidad IRQ, tamaños de ring de NIC, qdisc o reduce la tasa de paquetes. No abras un ticket diciendo “internet inestable” todavía.

Task 12: Inspeccionar qdisc y pacing (bufferbloat y colas)

cr0x@server:~$ tc -s qdisc show dev ens5
qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms ecn
 Sent 876543210 bytes 1122334 pkt (dropped 7, overlimits 0 requeues 21)
 backlog 0b 0p requeues 21
  maxpacket 1514 drop_overlimit 0 new_flow_count 1234 ecn_mark 0
  new_flows_len 0 old_flows_len 0

Significado: fq_codel es generalmente bueno. Un pequeño número de drops está bien. Overlimits y backlog enorme indicarían colas.
Decisión: Si ves backlog/overlimits masivos, estás saturando el egress o haciendo shaping mal. Arregla límites de ancho de banda, políticas de shaping o congestión upstream.

Task 13: Revisar presión de conntrack (drops stateful parecen aleatorios)

cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_count = 24612
net.netfilter.nf_conntrack_max = 262144
cr0x@server:~$ sudo dmesg -T | tail -n 5
[Tue Dec 30 10:12:01 2025] TCP: request_sock_TCP: Possible SYN flooding on port 443. Sending cookies.  Check SNMP counters.
[Tue Dec 30 10:12:07 2025] nf_conntrack: table full, dropping packet

Significado: Si conntrack está lleno o cerca de llenarse, los paquetes se descartan y las conexiones se quedan en stall. El kernel te lo dice, silenciosamente, en dmesg.
Decisión: Si ves “table full”, o bien aumentas el tamaño de conntrack, reduces la ráfaga de conexiones o dejas de rastrear flujos que no necesitas (con cuidado). Si ves SYN cookies, investiga tormentas entrantes o backlog inapropiado.

Task 14: Validar rp_filter y riesgo de enrutamiento asimétrico

cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.ens5.rp_filter
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.ens5.rp_filter = 1

Significado: El filtrado estricto de ruta inversa puede descartar tráfico legítimo en configuraciones de enrutamiento asimétrico (común en hosts multi-homed, policy routing o algunos bordes cloud).
Decisión: Si tu ruta es asimétrica (verificada con tablas de enrutamiento y capturas), pon rp_filter en modo loose (2) en las interfaces afectadas, pero solo cuando entiendas el alcance del cambio.

Usar mtr sin engañarte a ti mismo

mtr es una linterna, no una transcripción judicial. Es excelente para mostrar dónde aparecen latencia y pérdida, pero también puede llevarte a acusar a un salto inocente que simplemente está limitando ICMP. El truco es interpretarlo como un operador, no como un turista.

Tres reglas para mtr que previenen malas decisiones

  1. La pérdida en un salto intermedio es irrelevante a menos que continúe río abajo.
    Si el salto 3 muestra 30% de pérdida pero el salto 4 y el destino muestran 0%, el salto 3 probablemente está depriorizando tus sondas.
  2. Ajusta el protocolo al problema.
    Si tu app usa TCP/443, usa mtr -T -P 443. ICMP te dice algo, pero no siempre lo que necesitas.
  3. Muestra lo suficiente para atrapar la parte “aleatoria”.
    10 sondas pueden parecer perfectas. 200 pueden mostrar un patrón de 3% de pérdida que arruina la latencia de cola.

Chiste #1: Traceroute es como el chisme de oficina—ocasionalmente preciso, siempre confiado y nunca te dice qué pasó dentro de la sala de reuniones.

Patrones de mtr que importan

  • Cambio escalonado en latencia: un salto que aumenta y se mantiene sugiere un enlace más lento, un límite de túnel o un segmento congestionado.
  • Pico del peor caso en destino: dolor en la latencia de cola, a menudo por colas o pérdida intermitente.
  • Pérdida solo en el destino: puede ser pérdida real de última milla, limitación por tasa en el destino o comportamiento de firewall en el extremo. Confirma con tcpdump.
  • Comportamiento alternante en saltos: puede indicar ECMP donde diferentes sondas toman rutas distintas. mtr puede mostrar una vista combinada.

tcpdump: capturar retransmisiones, MTU y bloqueos

tcpdump es donde las discusiones van a morir. No le importan la página de estado de tu proveedor cloud ni la confianza del equipo de red. Muestra lo que tu host envió, lo que recibió y lo que nunca regresó.

Cómo capturar sin perjudicar al paciente

  • Filtra mucho. Captura únicamente el host/puerto que necesitas. Disco y CPU son recursos de producción.
  • Captura ráfagas cortas. 30–60 segundos durante una ventana mala vence a 4 horas de “mayormente bien”.
  • Registra los drops del kernel. Si tcpdump deja caer paquetes, tu captura está incompleta y tus conclusiones son dudosas.

Tres firmas a nivel TCP de “timeouts aleatorios”

  1. Retransmisiones SYN: el intento de conexión no recibe SYN-ACK. A menudo firewall, ruta o sobrecarga upstream.
  2. Retransmisiones de datos y ACK duplicados: pérdida o reordenamiento. La pérdida es más común; el reordenamiento es más raro pero problemático.
  3. Bloqueos después de enviar segmentos grandes: problemas MTU/MSS/PMTUD, especialmente si peticiones pequeñas funcionan y las grandes se quedan colgadas.

Caso #4: la ruta parece “bien” hasta que no lo está

Este caso aparece en sistemas reales porque la red moderna está apilada capa sobre capa: overlay VPC, cifrado, balanceadores, gateways NAT, a veces un service mesh. La ruta puede ser “alcanzable” y aun así estar equivocada de una forma que solo afecta ciertos tamaños de paquete o flujos.

Los síntomas

  • Timeouts intermitentes a una API HTTPS upstream.
  • La mayoría de peticiones tienen éxito; algunas se quedan colgadas 2–10 segundos y luego fallan.
  • Ping ICMP parece limpio. mtr basado en ICMP muestra pérdida ocasional en un salto medio, lo que lanza a la gente a hilos improductivos en Slack.
  • mtr basado en TCP muestra latencia cola en el destino y algo de pérdida.

La ruta de investigación que funciona

Empieza en el host. Prueba si el host está descartando paquetes (softnet, drops de NIC). Luego prueba si el flujo está retransmitiéndose.
Finalmente, valida MTU/MSS y cualquier límite de túnel.

Una causa raíz plausible en este caso

La prueba contundente es el desajuste de MSS en el handshake: el servidor anuncia MSS 1380. Eso implica fuertemente que en algún punto del camino los paquetes mayores a aproximadamente 1420–1450 bytes son riesgosos (overhead de túnel, IPsec, GRE/VXLAN o un extremo del proveedor haciendo algo creativo).
Si PMTUD está bloqueado o es poco fiable, algunos flujos se quedarán colgados cuando intenten enviar registros TLS más grandes o respuestas HTTP.

A menudo verás esta combinación:

  • Las solicitudes pequeñas (health checks, JSON corto) funcionan.
  • Solicitudes que provocan respuestas más grandes o subidas fallan intermitentemente.
  • tcpdump muestra retransmisiones de segmentos de tamaño completo; el emisor reduce la velocidad y finalmente hace timeout.

Probarlo con una captura focalizada

En la captura, busca retransmisiones repetidas del mismo número de secuencia, especialmente cuando la longitud del segmento está cerca de tu MSS.
También comprueba mensajes ICMP “fragmentation needed”; si faltan y el tráfico se para en tamaños grandes, es probable un agujero PMTUD.

Chiste #2: Los bugs de MTU son como el purpurín—una vez que entran en tu red, aparecen por todas partes y nadie admite quién los trajo.

Soluciones que realmente funcionan

Hay dos categorías de soluciones: detener la hemorragia y reparar la ruta. Haz ambas, pero en ese orden.
Los sistemas de producción valoran la disponibilidad sobre la estética.

Fix 1: Ajustar TCP MSS en el borde (pragmático, a menudo inmediato)

Si controlas un firewall/router/NAT entre tus hosts y el upstream, ajusta MSS a un valor seguro para que TCP nunca intente enviar paquetes mayores de lo que el camino real puede soportar. Esto evita depender de PMTUD.

cr0x@server:~$ sudo iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o ens5 -j TCPMSS --clamp-mss-to-pmtu

Significado: LOS paquetes SYN tendrán MSS ajustada para coincidir con el PMTU descubierto (cuando sea posible).
Decisión: Si PMTUD está roto, puede que necesites un valor MSS explícito (como 1360–1400) basado en overhead de túnel. Valida con tcpdump y timeouts reducidos.

Fix 2: Poner el MTU correcto en la interfaz (correcto cuando controlas el underlay)

En redes overlay (VXLAN, IPsec) el MTU efectivo es menor que 1500. Si tu host cree que puede usar 1500, lo intentará. Entonces la ruta hace lo que las rutas hacen: descarta lo que no puede manejar.

cr0x@server:~$ sudo ip link set dev ens5 mtu 1450

Significado: El host no enviará tramas mayores a 1450 en payload L3, consistente con ese MTU.
Decisión: Haz esto solo si tu entorno lo espera (VPC cloud, túneles). Confirma revisando el MTU recomendado del proveedor y midiendo con ping -M do.

Fix 3: Dejar de bloquear PMTUD ICMP en el medio

La solución correcta a menudo es “permitir ICMP tipo 3 código 4” (fragmentation needed) a través de los firewalls. Pero esto es networking corporativo, así que “correcto” puede requerir reuniones. Aun así: presiónalo. Cura la enfermedad, no solo el síntoma.

cr0x@server:~$ sudo nft list ruleset | sed -n '1,120p'
table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;
    ct state established,related accept
    iif "lo" accept
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept
  }
}

Significado: Aquí se acepta ICMP (bien). Si ves ICMP bloqueado, PMTUD puede fallar.
Decisión: Permite el ICMP necesario para tu entorno. No “bloquees todo ICMP” y luego te sorprendas cuando la red se comporte de forma extraña.

Fix 4: Reducir drops en el host (higiene softnet/IRQ)

Si Task 11 muestra drops en softnet, arregla el host. Mejoras comunes: asegurar que RSS esté habilitado, repartir IRQs y no dejar que una CPU haga todo el trabajo.

cr0x@server:~$ grep -H . /proc/interrupts | grep -E 'ens5|virtio' | head
/proc/interrupts:  43:   9922331          0          0          0  IR-PCI-MSI 327680-edge      virtio0-input.0
/proc/interrupts:  44:         0    8877665          0          0  IR-PCI-MSI 327681-edge      virtio0-output.0

Significado: Las interrupciones no están balanceadas (CPU0 recibe la carga de entrada).
Decisión: Ajusta la afinidad IRQ o habilita irqbalance si procede, y luego vuelve a comprobar las estadísticas softnet durante la carga.

Fix 5: Hacer que conntrack vuelva a ser aburrido

Si conntrack está lleno o ves drops, arregla el estado. Aumentar el tamaño de la tabla solo si entiendes la memoria y los patrones de tráfico. Mejor es reducir la ráfaga de conexiones: mantener conexiones vivas, usar pooling y no rastrear lo que no necesitas (con cuidado en NAT y políticas de seguridad).

cr0x@server:~$ sudo sysctl -w net.netfilter.nf_conntrack_max=524288
net.netfilter.nf_conntrack_max = 524288

Significado: Más espacio para flujos rastreados.
Decisión: Si el conteo vuelve a llenar el máximo, no solucionaste la causa—solo le diste un almacén más grande para arder.

Fix 6: Preferir mtr con TCP y sondas a nivel de servicio en runbooks

Esto es una corrección cultural. Actualiza tus runbooks para que “trazar la ruta” signifique “trazar con el protocolo que importa”. Previene culpas falsas y acelera la respuesta.

Tres micro-historias del mundo corporativo

Micro-historia 1: El incidente causado por una suposición errónea

Un equipo fintech ejecutaba un conjunto de servidores Ubuntu detrás de un load balancer gestionado. Los usuarios empezaron a reportar “fallos aleatorios en checkout”.
El on-call ejecutó mtr ICMP desde un nodo API hacia la pasarela de pagos. Mostró 20–30% de pérdida en el salto 4. La conclusión se formó al instante:
“El ISP está descartando paquetes.” Se abrió un ticket. Todos esperaron.

Mientras tanto, las reintentos se acumularon. La pasarela de pagos vio tráfico en ráfagas y empezó a limitar por tasa. Ahora los timeouts eran peores.
El equipo añadió más nodos API, lo que aumentó la churn de conexiones, y eso elevó la presión de conntrack en la capa NAT de salida.
De repente, los timeouts ya no eran aleatorios—eran constantes, y cada quien tenía su teoría favorita.

Un ingeniero más discreto hizo lo poco glamuroso: mtr -T -P 443 a la pasarela y un tcpdump de 60 segundos durante los fallos.
La pérdida en el salto 4 desapareció bajo mtr TCP. El destino mostró retransmisiones SYN esporádicas. tcpdump mostró SYN repetidos sin SYN-ACK durante ráfagas.

El verdadero problema era un firewall stateful en el medio con un límite agresivo de tasa de SYN que se había copiado desde una plantilla “endurecida”.
La pérdida ICMP en el salto 4 era solo ICMP siendo depriorizado. La suposición equivocada fue creer que la pérdida en un salto intermedio de mtr equivalía a pérdida de paquetes para tu app.

La solución fue aburrida: ajustar umbrales del firewall para coincidir con los patrones de tráfico, añadir reutilización de conexiones y poner alertas sobre retransmisiones SYN.
El ticket al ISP se cerró con una respuesta educada y nebulosa, como suele ocurrir.

Micro-historia 2: La optimización que salió mal

Una compañía de medios quería subir más rápido a un object store. Alguien notó que los servidores usaban MTU 1500 en un datacenter que soportaba jumbo frames.
La propuesta: poner MTU 9000 en todas partes. Tramas más grandes, menos paquetes, menos CPU. Lo desplegaron en una flota de boxes Debian.

El rendimiento de uploads mejoró en el mismo rack. Luego empezaron los bugs: timeouts intermitentes a ciertos servicios externos, TLS inestable y comportamiento extraño donde llamadas pequeñas funcionaban pero todo lo “pesado” se quedaba colgado. mtr parecía “mayormente bien”. Ping funcionaba. Todos se sintieron orgullosos por razones equivocadas.

El culpable fue predecible: no todos los segmentos entre esos servidores y el exterior soportaban jumbo. Algunos caminos clampaban, otros descartaban y los mensajes ICMP PMTUD fueron filtrados por un appliance de seguridad intermedio. Resultado: agujeros PMTU para un subconjunto de flujos.
La optimización creó una red dividida donde el mismo host se comportaba distinto según el destino.

El rollback fue doloroso porque los servicios se habían afinado en torno a la “mejora” y ahora todo tuvo que reaprender la realidad.
Finalmente estandarizaron MTU por zona, lo documentaron, habilitaron el ICMP necesario para PMTUD y usaron MSS clamping en el límite donde existían túneles.

Micro-historia 3: La práctica aburrida pero correcta que salvó el día

Una plataforma SaaS tenía una regla interna: cada canal de incidente debía incluir una captura de paquetes desde el host que fallaba dentro de 20 minutos.
La gente se quejaba de que era burocrático. Querían “empezar por los dashboards”. Los dashboards dan consuelo. Los paquetes son honestos.

Un día, timeouts aleatorios afectaron a un conjunto de workers Ubuntu que hablaban con una base de datos por un enlace privado. Los gráficos de latencia estaban relativamente planos.
mtr no mostró nada sospechoso. El equipo de BD insistía en que no cambiaron nada. El equipo de redes insistía en que no cambiaron nada. Lo único que cambiaba era el reproche.

La captura mostró ráfagas periódicas de retransmisiones correlacionadas con un job nocturno. No mucha pérdida, solo suficiente.
En los hosts worker, /proc/net/softnet_stat mostró drops y picos de time_squeeze en un subconjunto de CPUs durante ese batch.
El problema no era el enlace; era la pila de red del host quedándose sin recursos mientras un trabajo intensivo en CPU ejecutaba compresión.

Gracias a la práctica estándar de “capturar temprano”, no pasaron un día discutiendo sobre routers. Aislaron el job en un conjunto de CPU, ajustaron la afinidad IRQ y los timeouts desaparecieron. Nadie recibió un trofeo. La producción se volvió más tranquila, que es el único trofeo que importa.

Errores comunes: síntoma → causa raíz → solución

Esta sección es opinativa porque está escrita con la sangre de horas desperdiciadas.

1) mtr muestra pérdida en un salto medio

Síntomas: mtr informa 10–50% de pérdida en el salto N, pero el destino parece bien o solo ligeramente afectado.
Causa raíz: Limitación o depriorización de ICMP en ese router. No es reenvío real.
Solución: Vuelve a ejecutar con mtr -T -P <port>. Actúa solo si la pérdida/latencia persiste hasta el destino.

2) Timeouts aleatorios solo para respuestas o subidas “grandes”

Síntomas: Los health checks pasan. Las solicitudes pequeñas pasan. Los payloads grandes se quedan o hacen timeout.
Causa raíz: Desajuste MTU, agujero PMTUD, overhead de túnel o ICMP fragmentation-needed filtrado.
Solución: Valida PMTU con ping -M do, observa MSS en SYN/SYN-ACK, ajusta MSS o MTU correcto, permite ICMP PMTUD.

3) Retransmisiones SYN durante picos

Síntomas: tcpdump muestra SYN repetidos, pocos SYN-ACK, timeouts de conexión bajo carga.
Causa raíz: Limitación de SYN en firewall, load balancer saturado, conntrack/NAT agotado o backlog de accept upstream en presión.
Solución: Inspecciona conntrack/dmesg, ajusta umbrales del firewall, reduce churn de conexiones (keepalive/pooling), escala o afina upstream.

4) Parece “pérdida de red”, pero tcpdump deja caer paquetes

Síntomas: tcpdump reporta “packets dropped by kernel”, aumentan drops softnet, la app ve timeouts.
Causa raíz: El host no puede procesar paquetes lo suficientemente rápido (contención de CPU, imbalance de IRQ, ruido por virtualización).
Solución: Reduce el alcance de la captura; arregla el host: afinidad IRQ, RSS, irqbalance, pinning de CPU, reduce la tasa de paquetes o mueve la carga.

5) Timeouts solo desde una subred o una AZ

Síntomas: Mismo código, mismo servicio, pero una zona falla más.
Causa raíz: Ruta distinta (enrutamiento, NAT gateway, política de firewall) o un segmento underlay defectuoso.
Solución: Compara mtr -T y capturas desde cada zona. Arregla el egress divergente; no “afines la app” para tolerar un carril roto.

6) “Habilitamos rp_filter estricto por seguridad” y ahora ocurren cosas raras

Síntomas: Algunas respuestas nunca regresan, drops intermitentes en hosts multi-homed.
Causa raíz: Enrutamiento asimétrico más rp_filter estricto descarta paquetes legítimos.
Solución: Usa rp_filter en modo loose (2) donde se espera asimetría y documenta el diseño de enrutamiento para que nadie vuelva a “asegurar” esto después.

Listas de comprobación / plan paso a paso

Checklist A: Triage de 30 minutos para timeouts aleatorios

  1. Identifica una IP:puerto destino que falla y un destino de control saludable.
  2. Ejecuta curl -w para ver si es connect vs TTFB vs total.
  3. Ejecuta mtr -T -P (Task 7) lo suficiente para atrapar picos.
  4. Captura 60 segundos con tcpdump filtrado a ese host:puerto (Task 9).
  5. Revisa drops de NIC (Task 3) y drops softnet (Task 11).
  6. Revisa conntrack y dmesg (Task 13).
  7. Prueba PMTU rápidamente con ping -M do (Task 8).
  8. Realiza un cambio de contención (clamp MSS o ajustar MTU) solo si coincide claramente con la evidencia.

Checklist B: Paquete de evidencia para entregar a equipo de red/proveedor

  1. Salida con timestamps de mtr -T -P mostrando pérdida/latencia en el destino.
  2. Snippet pcap mostrando retransmisiones SYN o retransmisiones de datos (incluir tiempos de inicio/fin).
  3. IP origen, IP destino, puerto y si hay NAT involucrado.
  4. Confirmación de que el host no está descartando paquetes (softnet, drops del kernel en tcpdump).
  5. Si MSS/MTU parece estar ajustado (opciones SYN, MSS observada).

Checklist C: Endurecimiento para que esto no vuelva el próximo mes

  1. Añade sondas sintéticas que midan connect y TTFB por separado.
  2. Alerta sobre retransmisiones TCP y retransmisiones SYN a nivel de nodo.
  3. Estandariza MTU por entorno y documenta overhead de túneles.
  4. Mantén ICMP necesario para PMTUD permitido en límites internos.
  5. Monitorea uso de conntrack donde existan NAT/firewalls stateful.
  6. Actualiza runbooks: usa mtr TCP al puerto del servicio, no ICMP por defecto.

Preguntas frecuentes

1) ¿Por qué mtr ICMP muestra pérdida pero mi app parece bien?

Muchos routers limitan la tasa de respuestas ICMP (plano de control) mientras reenvían datos (plano de datos) normalmente. Usa mtr -T -P para probar el protocolo que usa tu app.

2) ¿Por qué mtr TCP muestra pérdida en el destino—podría ser “falsa”?

Es menos probable que sea falsa, pero los destinos pueden limitar SYN/ACK o depriorizar respuestas bajo carga. Confirma con tcpdump: ¿ves retransmisiones SYN o retransmisiones de datos?

3) ¿Cuál es la forma más rápida de detectar agujeros MTU?

Compara el comportamiento para cargas pequeñas vs grandes, revisa MSS en SYN/SYN-ACK y prueba con ping -M do usando tamaños crecientes. Si los grandes se quedan y falta ICMP “frag needed”, sospecha fallo PMTUD.

4) ¿Debo desactivar TSO/GRO al depurar?

Solo si entiendes por qué. Los offloads pueden complicar las capturas, pero desactivarlos en producción puede perjudicar el rendimiento. Prefiere interpretar las capturas con offload en mente y mantiene las pruebas focalizadas.

5) Mi tcpdump dice “packets dropped by kernel.” ¿La red tiene la culpa?

No. Eso es tu host fallando en capturar (y a menudo en procesar) paquetes lo bastante rápido. Arregla CPU/IRQ/softnet o reduce la carga de captura antes de culpar al camino.

6) ¿Cómo sé si los timeouts son por DNS?

Usa curl -w para ver el tiempo de lookup de nombre y ejecuta getent ahosts repetidamente. Los problemas DNS se muestran como picos en time_namelookup o bloqueos en llamadas del resolvedor.

7) ¿Es MSS clamping un apaño?

Es una estrategia de contención pragmática. La solución a largo plazo es MTU consistente y PMTUD funcionando, pero MSS clamping se usa ampliamente en los límites de túneles porque funciona.

8) ¿Cómo se relacionan los timeouts aleatorios con la ingeniería de almacenamiento?

El almacenamiento remoto (iSCSI, NFS, gateways de objetos) convierte la pérdida de paquetes en bloqueos de aplicación muy rápido. Una pequeña tasa de retransmisiones puede convertirse en una latencia de cola enorme para IO síncrono.

9) ¿Qué cita debo recordar durante estas investigaciones?

“Hope is not a strategy.” — James Cameron

Conclusión: próximos pasos

Los timeouts aleatorios no son aleatorios. Están distribuidos entre flujos, ocultos por promedios y protegidos por las suposiciones equivocadas favoritas de la gente.
El flujo de trabajo fiable es simple: reproduce en el host que falla, rastrea la ruta usando el protocolo correcto, captura paquetes durante el fallo y demuestra si estás frente a pérdida, colas, MTU/PMTUD o drops a nivel de host.

Próximos pasos que puedes hacer hoy:

  1. Actualiza tu runbook para por defecto usar mtr -T -P en timeouts de aplicaciones.
  2. Añade un procedimiento ligero de tcpdump-on-demand con filtros estrictos y ventanas de captura cortas.
  3. Establece expectativas de MTU/MSS en tu entorno (especialmente si existen túneles).
  4. Instrumenta retransmisiones y presión de conntrack donde existan NAT/dispositivos stateful.
  5. Cuando encuentres la solución, documenta la evidencia—no la teoría—para que el siguiente on-call no repita tu fin de semana.
← Anterior
Optimización de pools ZFS solo NVMe: latencia, IRQs y los límites reales
Siguiente →
Controladores ‘Studio’: ¿beneficio real o solo una etiqueta?

Deja un comentario