Picos de carga DNS: limitar la tasa y sobrevivir ataques sin tiempo de inactividad

¿Te fue útil?

El DNS es la dependencia que todos olvidan hasta que está en llamas. Tu capa web puede autoescalar, tus cachés pueden absorber, tus bases de datos pueden degradarse. ¿DNS? DNS responde preguntas hasta que deja de hacerlo — y entonces todo parece “caído” aunque los servidores estén bien.

Los picos de carga golpean al DNS de formas feas: popularidad repentina, reintentos rotos desde clientes, escaneos de bots, inundaciones NXDOMAIN, ataques por reflexión, o un cambio “útil” que convierte una zona tranquila en un desastre. El truco no es solamente bloquear tráfico. Es limitar las cosas correctas, en la capa correcta, sin mentir a clientes legítimos ni detonar tu propia fiabilidad.

Qué se rompe realmente durante picos de DNS

Cuando el DNS falla, normalmente no recibes una alarma clara de “DNS caído”. Recibes un desfile de síntomas de segundo orden: fallos de inicio de sesión, timeouts aleatorios de API, nodos de Kubernetes “flapeando”, y un CEO que no puede acceder al sitio de marketing (que, trágicamente, se convierte en “P0”).

Modo de fallo 1: el manejo de paquetes colapsa antes que la CPU

La mayoría de los demonios de DNS son rápidos, pero aún necesitan que el kernel reciba paquetes, los enfile y los entregue al espacio de usuario. Con QPS explosivo, puedes golpear:

  • Agotamiento del anillo de la NIC (pérdidas en el driver).
  • Desbordes del buffer de recepción de sockets (pérdidas en el kernel).
  • Cuellos de botella de hilo único (el demonio no puede drenar colas).

Resultado: los clientes ven timeouts y reintentan, lo que multiplica el tráfico y convierte un “pico” en una “espiral”. DNS es uno de los pocos sitios donde “timeout” no es solo un síntoma: es un amplificador de tráfico.

Modo de fallo 2: la latencia te mata mucho antes que los errores

Los clientes DNS suelen esperar solo unos cientos de milisegundos antes de reintentar o fallar por otro servidor. Tu servidor puede seguir respondiendo, pero si el p95 sube de 5 ms a 200 ms verás “fallos” aleatorios en aplicaciones.

Modo de fallo 3: gana el tráfico equivocado

No todas las consultas merecen el mismo trato. Durante ataques recibirás inundaciones de:

  • Consultas a subdominios aleatorios (p. ej., asdf123.example.com) diseñadas para evitar cachés y generar trabajo de NXDOMAIN o NODATA.
  • Consultas ANY (menos relevantes ahora pero aún vistas) o tipos de consulta que provocan respuestas grandes.
  • Sondeos con EDNS activado que intentan forzar respuestas UDP grandes para reflexión.

Si tu infraestructura trata esto como tráfico normal, terminas protegiendo el QPS del atacante mientras clientes legítimos esperan detrás. Eso no es neutralidad; es autolesionarse operativamente.

Modo de fallo 4: tu “protección” es la caída

La limitación de tasa mal hecha es indistinguible de un ataque. Si es demasiado estricta, bloqueas usuarios reales detrás de NAT o CGNAT. Si es demasiado “lista”, estrangulas tus propios resolutores recursivos o las comprobaciones de estado. El objetivo es degradación controlada: algunas respuestas se ralentizan o truncarán, pero el servicio sigue accesible y se recupera rápido.

Una verdad seca: DNS es donde las configuraciones “simples” se convierten en sistemas distribuidos. Negocias con resolutores stub, resolutores recursivos, cachés, middleboxes y gente con firmware antiguo en routers Wi‑Fi de hoteles.

Una frase para recordar (idea parafraseada): “La esperanza no es una estrategia”, frecuentemente citada por ingenieros y operadores hablando de fiabilidad. Trata los picos de DNS igual: diseña, mide, ensaya.

Broma #1: DNS es el único sistema donde el mejor resultado es que te ignoren porque todos te tienen en caché.

Datos interesantes y contexto histórico

  • DNS es anterior a la web moderna: fue diseñado a principios de los años 80 para reemplazar el modelo de distribución HOSTS.TXT.
  • UDP fue la opción por velocidad: DNS sobre UDP se eligió para evitar el establecimiento de conexiones, lo cual es genial hasta que aparece la suplantación y el abuso por reflexión.
  • El caché DNS es una reducción deliberada de carga: los TTL no son solo controles de corrección; son un sistema económico para el QPS.
  • El sistema root no es una sola caja: es una constelación anycast global; “el root está caído” casi siempre es un problema local.
  • Las consultas ANY se convirtieron en herramienta DDoS: muchos operadores ahora minimizan o restringen las respuestas ANY, porque se usaban para provocar respuestas sobredimensionadas.
  • DNSSEC aumentó el tamaño de respuestas: agregar firmas mejora la integridad pero puede empeorar la fragmentación y el riesgo de amplificación si no gestionas EDNS.
  • RRL (Response Rate Limiting) surgió del dolor: los operadores autoritativos necesitaban una forma de reducir la utilidad de la reflexión sin desconectarse.
  • Los ataques NXDOMAIN son antiguos: las inundaciones de subdominios aleatorios se han usado durante años porque evaden el comportamiento normal de caché.
  • Anycast cambió el libreto: repartir DNS autoritativo entre POPs reduce la saturación de un único sitio pero añade complejidad para depurar.

Guía de diagnóstico rápido (primero/segundo/tercero)

Esta es la secuencia de “dejar de adivinar”. Puedes hacerla en 10 minutos mientras todos los demás discuten en Slack.

Primero: confirma que es DNS, no algo “con forma de DNS”

  1. Desde una red cliente afectada, consulta tu autoritativo directamente (evita la recursión). Comprueba latencia y timeouts.
  2. Desde dentro del centro de datos/VPC, haz lo mismo. Si interno está bien y externo no, sospecha saturación del borde o filtrado aguas arriba.
  3. Comprueba si el pico está en autoritativo, recursivo o ambos. Fallen de maneras diferentes.

Segundo: localiza la capa que hace de cuello de botella

  1. Entrada de red: pérdidas de paquetes en NIC/kernel, torbellinos conntrack, límites de PPS.
  2. Demonio: CPU por hilo, contención de locks, tormentas de fallos de caché, costos de firmar/validar DNSSEC.
  3. Dependencias backend: backends dinámicos (bases de datos), transferencias de zona lentas, sinks de logging o telemetría sobrecargados.

Tercero: aplica contención segura y luego optimiza

  1. Despliega limitación de tasa en el borde (dnsdist / firewall / load balancer) antes de tocar internals del demonio.
  2. Prioriza: mantén funcionales A/AAAA/CNAME/SOA/NS básicos. Degrada lo “agradable de tener” (ANY, TXT, respuestas grandes).
  3. Estabiliza la latencia (p95) primero. Luego persigue el QPS absoluto.

Mide primero: tareas, comandos, salidas, decisiones

No puedes limitar por tasa sin saber qué está pasando. Abajo hay tareas prácticas que puedes ejecutar durante un incidente o ensayo. Cada una incluye un comando, una salida de ejemplo, qué significa y la decisión que tomarías.

Tarea 1: Verificar respuesta autoritativa y latencia (consulta directa)

cr0x@server:~$ dig @203.0.113.53 www.example.com A +tries=1 +time=1

; <<>> DiG 9.18.24 <<>> @203.0.113.53 www.example.com A +tries=1 +time=1
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43112
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
;; ANSWER SECTION:
www.example.com. 60 IN A 198.51.100.10
;; Query time: 12 msec
;; SERVER: 203.0.113.53#53(203.0.113.53) (UDP)
;; WHEN: Tue Dec 31 12:00:00 UTC 2025
;; MSG SIZE  rcvd: 93

Qué significa: Estás recibiendo una respuesta autoritativa (flag aa), con baja latencia.

Decisión: Si esto es rápido pero los usuarios se quejan, el problema puede ser los resolutores recursivos, la ruta de red o el comportamiento de caché/negativo—not el autoritativo en sí.

Tarea 2: Comparar comportamiento UDP vs TCP (detectar fragmentación/problemas EDNS)

cr0x@server:~$ dig @203.0.113.53 example.com DNSKEY +dnssec +time=1 +tries=1

;; Truncated, retrying in TCP mode.
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5321
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; Query time: 210 msec
;; SERVER: 203.0.113.53#53(203.0.113.53) (TCP)

Qué significa: La truncación UDP forzó reintento en TCP. Bajo carga, TCP cuesta más (estado, colas de accept, overhead del kernel).

Decisión: Ajusta el tamaño del buffer EDNS y el comportamiento de respuestas DNSSEC; considera limitar respuestas grandes y asegúrate de que la capacidad TCP sea sensata.

Tarea 3: Verificar QPS en servidor y tipos de consulta principales en BIND (autoritativo)

cr0x@server:~$ sudo rndc stats
cr0x@server:~$ sudo tail -n 20 /var/cache/bind/named.stats
++ Incoming Requests ++
[View: default]
                          1987632 QUERY
                           504112 NOTIFY
++ Incoming Queries ++
[View: default]
                           912331 A
                           701221 AAAA
                           389002 TXT
                           211332 DNSKEY
                           122880 ANY

Qué significa: Tienes una mezcla alta de TXT/DNSKEY/ANY. Esa es una firma clásica de “hacer las respuestas más grandes”.

Decisión: Considera apretar la política de respuestas: minimizar ANY, limitar por tasa los tipos abusados y revisar DNSSEC/EDNS sizing.

Tarea 4: Inspeccionar estadísticas de Unbound rápidamente (recursivo)

cr0x@server:~$ sudo unbound-control stats_noreset | egrep 'total\.num\.queries|num\.query\.type|unwanted|cache\.hits|cache\.miss|avg\.recursion'
total.num.queries=18422301
num.query.type.A=10233444
num.query.type.AAAA=6012231
num.query.type.TXT=1589222
unwanted.queries=433221
msg.cache.hits=11022334
msg.cache.misses=7401130
avg.recursion.time=0.145000

Qué significa: Los misses de caché son altos y el tiempo de recursión está subiendo. Las consultas no deseadas son no triviales—probablemente abuso o clientes con mal comportamiento.

Decisión: Añade limitación por cliente, ajusta control de acceso (quién puede usar recursión) y aumenta la caché donde sea seguro. Si el tiempo de recursión sube por timeouts upstream, considera estrategia de forwarding o la alcanzabilidad de root/TLD.

Tarea 5: Identificar principales habladores y nombres de consulta (muestra de paquetes)

cr0x@server:~$ sudo tcpdump -ni eth0 udp port 53 -c 50
12:00:01.001234 IP 192.0.2.10.53211 > 203.0.113.53.53: 1234+ A? asdf91k2.example.com. (38)
12:00:01.001260 IP 192.0.2.10.53212 > 203.0.113.53.53: 2234+ AAAA? asdf91k2.example.com. (38)
12:00:01.001289 IP 198.51.100.77.41922 > 203.0.113.53.53: 3321+ ANY? example.com. (28)
...

Qué significa: Labels aleatorios para tu zona sugieren una inundación que evade caché NXDOMAIN/NODATA; las consultas ANY sugieren sondeos de amplificación.

Decisión: Aplica limitación por fuente y por qname/qtype en el borde, y considera servir respuestas “sintetizadas” mínimas donde corresponda (con cuidado) o ajustes agresivos de cache negativo.

Tarea 6: Revisar pérdidas en kernel y errores de recepción UDP

cr0x@server:~$ netstat -su
Udp:
    1283221 packets received
    0 packets to unknown port received
    22111 packet receive errors
    904321 packets sent
    22111 receive buffer errors

Qué significa: Errores de buffer de recepción implican que el kernel está descartando UDP porque la aplicación no puede drenar lo suficientemente rápido o los buffers son demasiado pequeños.

Decisión: Aumenta buffers de socket y ajusta el networking del kernel; también reduce el CPU por paquete moviendo la limitación antes (dnsdist, XDP, firewall) y disminuye el overhead de logging.

Tarea 7: Revisar pérdidas a nivel de NIC y kernel

cr0x@server:~$ ip -s link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    RX:  bytes  packets  errors  dropped overrun mcast
    9876543210 12345678  0       4321    0       0
    TX:  bytes  packets  errors  dropped carrier collsns
    8765432109 11223344  0       0       0       0

Qué significa: Ya están ocurriendo drops en RX en la interfaz antes de que tu demonio vea el tráfico.

Decisión: Añade capacidad (más instancias/anycast), usa NICs con mayor PPS, o aplica filtrado/limitación upstream para que el host no vea lo peor.

Tarea 8: Confirmar que conntrack no esté involucrado por accidente

cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_count = 982312
net.netfilter.nf_conntrack_max = 1048576

Qué significa: Estás cerca del máximo de conntrack. DNS sobre UDP no debería necesitar conntrack en muchos diseños, pero firewalls/NAT pueden arrastrarlo.

Decisión: Evita tracking stateful para DNS de alto QPS si es posible; mueve el filtrado a reglas stateless o dispositivos de borde dedicados, o aumenta límites con precaución.

Tarea 9: Validar salud del demonio y saturación de hilos (systemd + CPU)

cr0x@server:~$ systemctl status named --no-pager
● named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled)
     Active: active (running) since Tue 2025-12-31 11:20:12 UTC; 39min ago
   Main PID: 1023 (named)
      Tasks: 42
     Memory: 1.3G
        CPU: 18min 22.331s
cr0x@server:~$ top -b -n1 | head -n 15
top - 12:00:10 up 10 days,  3:22,  1 user,  load average: 18.21, 17.44, 16.02
%Cpu(s): 92.1 us,  4.1 sy,  0.0 ni,  1.2 id,  0.0 wa,  0.0 hi,  2.6 si,  0.0 st
MiB Mem :  32110.0 total,   2100.0 free,  12000.0 used,  18010.0 buff/cache
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 1023 bind      20   0  2460.0m  1320.0m   8.1m R  580.0   4.1  18:25.12 named

Qué significa: La CPU está caliente; named consume múltiples núcleos. Si la latencia sigue siendo mala, la CPU no es el único cuello de botella—revisa pérdidas y encolamiento.

Decisión: Si la CPU es el limitador, escala horizontalmente y/o reduce trabajo costoso (firmado/validación DNSSEC, logging, actualizaciones dinámicas). Si hay pérdidas, limita por tasa antes del demonio.

Tarea 10: Revisar distribución de tamaños de respuesta DNS (detectar riesgo de amplificación)

cr0x@server:~$ sudo tcpdump -ni eth0 udp port 53 -vv -c 10
12:00:12.100001 IP 203.0.113.53.53 > 192.0.2.10.53211: 1234 NXDomain 0/1/0 (112)
12:00:12.100120 IP 203.0.113.53.53 > 198.51.100.77.41922: 3321 4/0/6 (1452)

Qué significa: Respuestas UDP de 1452 bytes coquetean con fragmentación (dependiendo del MTU de la ruta). La fragmentación aumenta pérdidas y puede convertirte en mejor arma de reflexión.

Decisión: Limita el tamaño UDP EDNS (a menudo alrededor de 1232 bytes es práctico), reduce registros adicionales y asegúrate de que el fallback TC=1 sea aceptable.

Tarea 11: Revisar estadísticas del front-end dnsdist (limitador de borde)

cr0x@server:~$ sudo dnsdist -c -e 'showStats()'
aclDrops                                 12345
responses                                9812234
queries                                  9921100
rdQueries                                221001
ruleDrop                                 88321
ruleNXDomain                             0
latency0_1                                7122331
latency1_10                               2501123
latency10_50                              210992
latency50_100                             12012
latency100_1000                            542

Qué significa: Estás descartando tráfico vía ACL/reglas mientras mantienes la mayor parte de la latencia por debajo de 10 ms. Esa es la forma ideal durante un ataque.

Decisión: Si los drops son demasiado altos y afectan a usuarios legítimos, afina las reglas (por bloques de red, por qtype, por qname) en lugar de subir límites globales.

Tarea 12: Validar corrección de zona y TTL de caché negativo (SOA)

cr0x@server:~$ dig @203.0.113.53 example.com SOA +noall +answer
example.com. 300 IN SOA ns1.example.com. hostmaster.example.com. 2025123101 7200 3600 1209600 60

Qué significa: El último campo (minimum/negative TTL en práctica moderna) es 60 segundos. Eso gobierna cuánto tiempo los resolutores pueden cachear NXDOMAIN/NODATA.

Decisión: Durante inundaciones NXDOMAIN, un TTL negativo demasiado bajo empeora las cosas porque los resolutores vuelven a preguntar constantemente. Auméntalo con cuidado (no a días; minutos u hora según tu cadencia de cambios).

Tarea 13: Averiguar si los clientes reintentan en exceso (muestreo de logs)

cr0x@server:~$ sudo journalctl -u named --since "10 min ago" | egrep 'client|query' | head
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0a: query (cache) 'asdf91k2.example.com/A/IN' denied
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0b: query (cache) 'asdf91k2.example.com/AAAA/IN' denied
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0c: query (cache) 'asdf91k2.example.com/A/IN' denied

Qué significa: Ves consultas repetidas por el mismo nombre aleatorio, potencialmente desde resolutores recursivos. Los denegados pueden ser ACLs o decisiones de limitación por tasa.

Decisión: Si resolutores legítimos están siendo denegados, estás yendo demasiado al límite. Prefiere estrategias de “slip”/truncado o shaping por fuente en lugar de negaciones generales.

Tarea 14: Confirmar sincronía horaria (DNSSEC y sanidad de TTL)

cr0x@server:~$ timedatectl
               Local time: Tue 2025-12-31 12:00:30 UTC
           Universal time: Tue 2025-12-31 12:00:30 UTC
                 RTC time: Tue 2025-12-31 12:00:29
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active

Qué significa: El tiempo es sensato. El desajuste horaria puede causar fallos de validación DNSSEC y comportamientos extraños de caché.

Decisión: Si no está sincronizado, arregla NTP primero. Depurar DNS bajo desincronía horaria es como depurar almacenamiento con el disco en llamas.

Patrones de limitación de tasa que funcionan (y qué evitar)

Limitar la tasa en DNS no es “bloquear IPs malas”. El tráfico de ataque suele ser suplantado, distribuido, o proviene de resolutores recursivos legítimos que a su vez están saturados. Estás dando forma a un sistema donde la identidad del cliente es difusa y el transporte suele ser UDP.

Principio: limitar en el borde, no dentro del cerebro

Tu demonio autoritativo debería gastar CPU en responder consultas legítimas, no en hacer de policía de tráfico. Pon una capa delante:

  • dnsdist para filtrado y shaping con conocimiento DNS.
  • iptables/nftables para límites PPS gruesos y ACLs.
  • Anycast + múltiples POPs para convertir “un objetivo” en muchos objetivos pequeños.

No hagas que tu servidor autoritativo analice y registre cada consulta abusiva a nivel debug. Eso no es observabilidad. Es imprimir el DDoS en papel.

Patrón 1: cubeta de tokens por origen (con la realidad del NAT)

Un límite QPS por IP es el control más simple. También es como accidentalmente bloquear a todo un operador móvil detrás de CGNAT. Úsalo, pero:

  • Fija límites lo bastante altos para grandes resolutores.
  • Prefiere límites por /24 o /56 solo si entiendes el daño colateral.
  • Incluye en lista blanca resolutores recursivos conocidos de los que dependes (los tuyos, resolutores públicos grandes si procede).

Patrón 2: limitar por patrón de qname (inundaciones de subdominios aleatorios)

Los subdominios aleatorios están diseñados para causar misses de caché. Limitar por sufijo de qname y “entropía” puede ser efectivo:

  • Tasa para respuestas NXDOMAIN por origen.
  • Frena consultas por etiquetas “profundas” (p. ej., prefijo aleatorio de 20+ chars) si tu negocio no las usa.
  • Considera cuidadosamente los registros wildcard—los wildcard pueden convertir NXDOMAIN en NOERROR, lo que cambia la economía del ataque.

Patrón 3: minimizar valor de amplificación

Los ataques por reflexión buscan respuestas grandes para consultas pequeñas. Haz que tu servidor sea un mal amplificador:

  • Minimiza respuestas ANY (muchos autoritativos responden mínimamente o rechazan ANY).
  • Limita el tamaño UDP EDNS para reducir fragmentación y respuestas sobredimensionadas.
  • Evita registros adicionales gratuitos (como glue extra) salvo cuando sean necesarios.
  • Asegúrate de no ser un resolvedor abierto si eres autoritativo. Ese error nunca muere.

Patrón 4: “Slip” (truncar) en lugar de caída total, cuando ayuda

Algunas implementaciones de limitación pueden “slip”: enviar respuestas truncadas (TC=1) ocasionalmente para que resolutores legítimos reintenten por TCP, mientras los atacantes pierden eficiencia. Esto no es magia—TCP también puede atacarse—pero puede trasladar el coste al solicitante.

Qué evitar: topes globales de QPS sin clasificar tráfico

Un tope global dice “no sé qué pasa, así que haré daño a todos por igual”. Esa es una vía rápida para mantener el ataque en marcha mientras tus clientes se van.

Broma #2: Lo único más aterrador que un DDoS DNS es un DDoS DNS más un “aumento de logging de emergencia” de alguien que extraña los años 90.

Autoritativo vs recursivo: enemigos distintos, controles distintos

DNS autoritativo: protege tus zonas y tu reputación

Los servidores autoritativos responden por tu dominio. El tráfico de abuso suele dirigirse a ellos porque son públicos y predecibles. Abusos comunes:

  • Reflexión: direcciones origen suplantadas; tu servidor “ataca” a otro.
  • Inundaciones NXDOMAIN: subdominios aleatorios; calculas respuestas negativas repetidamente.
  • Amplificación DNSSEC: respuestas grandes DNSKEY/DS/NSEC*.

Buenos controles en autoritativo:

  • RRL (Response Rate Limiting) para respuestas similares a muchos clientes.
  • Reglas por qtype (p. ej., restringir ANY, vigilar patrones TXT/DNSKEY).
  • Distribución anycast y tránsito upstream diverso.
  • Contenido de zona corto y sensato (evita TXT enormes salvo cuando sean necesarios).

DNS recursivo: protege a tus usuarios y a tu upstream

Los resolutores recursivos obtienen respuestas de Internet en nombre de clientes. Son abusados mediante:

  • Recursión abierta: extraños usan tu resolvedor; pagas ancho de banda y recibes la culpa.
  • Evasión de caché: qnames aleatorios fuerzan búsquedas upstream y mantienen ocupada tu recursión.
  • Torbellinos de reintentos de clientes: apps mal configuradas o resolutores stub rotos.

Buenos controles en recursivo:

  • Control de acceso: solo tus redes pueden consultar recursión.
  • Caching agresivo donde sea seguro; prefetch de registros populares.
  • Limitación por cliente y mitigación de “consultas no deseadas”.
  • Servir expirados (con cuidado) para sobrevivir fallos upstream.

La trampa: mezclar autoritativo y recursivo en el mismo host

Sí, “funciona”. También acopla dominios de fallo. Bajo ataque, tu recursión puede dejar sin recursos al autoritativo, o viceversa. Mantén roles separados salvo que tengas un entorno pequeño y disfrutes vivir peligrosamente.

Diseña para sobrevivir: arquitectura y movimientos de capacidad

Usa anycast, pero no lo adores

Anycast reparte la carga de consultas entre múltiples sitios anunciando la misma IP desde muchas ubicaciones. Es el estándar para autoritativos a escala. También introduce realidades operativas:

  • El tráfico sigue BGP, no tu intención. Un flap de ruta puede mover la DNS de medio continente a un POP.
  • Depurar “por qué este resolvedor llega a ese POP” se vuelve un ejercicio de networking.
  • El estado debe ser mínimo: contenido de zona y claves deben replicarse de forma fiable.

Usa anycast si puedes gestionarlo bien. Si no, usa múltiples NS unicast con protección DDoS upstream fuerte. La meta de fiabilidad es la diversidad.

Separa “responder” de “pensar”

Los mejores sistemas autoritativos hacen cómputo mínimo por consulta:

  • Zonas prefirmadas (si usas DNSSEC) o infraestructura de firmado eficiente.
  • Datos de zona en memoria.
  • No llamadas síncronas a bases de datos en la vía de consulta. Si necesitas respuestas dinámicas, colócalas detrás de cachés y breakers estrictos.

Ajusta EDNS y tamaño UDP como si importara

Respuestas UDP grandes se fragmentan. Los fragmentos se pierden. Los fragmentos perdidos provocan reintentos. Los reintentos multiplican QPS. Así obtienes un “pico misterioso” que parece que Internet olvidó cómo cachear.

Movimiento pragmático: mantén las respuestas UDP en un tamaño razonable. Limita el payload EDNS a un valor conservador; acepta que el fallback a TCP a veces es necesario y diseña para ello.

Estrategia de TTL: la caché es tu capacidad más barata

Los TTL cortos dan sensación de agilidad. También son caros. Bajo ataque o tráfico viral, la diferencia entre TTL 30 y TTL 300 es un factor 10 en volumen de consultas desde recursors que respetan TTL.

No configures TTLs por sensaciones. Hazlo según:

  • Qué tan rápido necesitas cambiar registros en emergencias.
  • Si tienes otros controles de enrutamiento (load balancers, anycast, failover).
  • Tu tolerancia a servir datos ligeramente obsoletos durante incidentes.

Logging: muestrea, no te ahogues

El logging de consultas a volumen total durante picos es un clásico auto-sabotaje. Usa:

  • Muestreo (1 de cada N consultas).
  • Métricas agregadas (conteos por qtype, tasa NXDOMAIN, top clientes por PPS).
  • Capturas de paquetes cortas con filtros estrictos.

Mantén tu subsistema de almacenamiento fuera del radio de blast. DNS es un servicio de red; no lo conviertas en una prueba de disco.

Tres mini-historias corporativas desde el terreno

Mini-historia 1: el incidente causado por una suposición errónea

Una compañía SaaS mediana ejecutaba DNS autoritativo en dos VMs detrás de un load balancer “fiable” de la nube. El equipo creía que el load balancer proporcionaba “protección DDoS por defecto”, porque venía de un gran proveedor y tenía un panel bonito.

Luego un partner integró un nuevo SDK. El SDK hizo una consulta SRV en el arranque de la app, por cada petición, porque alguien leyó mal una guía de caching. Eso creó un pico perfectamente legítimo: no fue un ataque, solo cien mil clientes entusiastas. Los servidores autoritativos fueron golpeados con consultas repetitivas que evitaban caché porque los registros tenían TTL 30 segundos “para flexibilidad”.

La latencia subió. Los timeouts aumentaron. Los clientes reintentaron. El load balancer empezó a encolar y finalmente las comprobaciones de salud fallaron porque los servidores DNS estaban ocupados respondiendo tráfico real. El balanceador los drenó, lo que concentró carga, lo que empeoró las cosas. Bucle de realimentación positiva clásico, ahora con un servicio gestionado metiendo misterio.

La suposición equivocada no fue “la nube es poco fiable”. Fue creer que un load balancer genérico equivale a un borde consciente de DNS. Lo arreglaron aumentando TTLs, añadiendo dnsdist delante con shaping por cliente sensato, y separando las comprobaciones de salud de las rutas de consulta sobrecargadas. También escribieron una prueba que simulaba el patrón de consultas del SDK, porque el siguiente incidente sería más extraño.

Mini-historia 2: la optimización que salió mal

Un gran equipo de red decidió “optimizar latencia DNS” forzando a todos los clientes internos a usar un pequeño conjunto de resolutores recursivos en un centro de datos. Escalaron los resolutores: mucha RAM, CPUs grandes, NVMe elegante para logs. El cambio se veía bien en una prueba de oficina única.

Dos meses después, un problema de tránsito degradó la conectividad de ese centro de datos a varios servidores de nombre de TLD. Nada estaba totalmente caído, solo más lento. El tiempo de resolución recursiva aumentó, los misses de caché se volvieron dolorosos y los resolutores empezaron a acumular backlog. Los clientes—especialmente endpoints Windows y algunos dispositivos IoT—reintentaron agresivamente ante la lentitud percibida.

La “optimización” creó un dominio de fallo centralizado. Peor: el equipo había activado logging detallado de consultas para demostrar la mejora, y bajo condiciones de pico la canalización de logs saturó I/O de disco y CPU. Los resolutores no solo eran lentos porque Internet estaba lento; eran lentos porque narraban su sufrimiento al disco.

La solución fue poco glamorosa: distribuir la recursión entre regiones, reducir logging a muestreo/métricas agregadas, y habilitar serve-expired con guardrails para que la lentitud upstream transitoria no se convirtiera en torbellinos de reintentos de clientes. También dejaron de tratar DNS como un servicio web donde “un gran clúster” siempre es la solución.

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

Una empresa de servicios financieros operaba DNS autoritativo con anycast a través de múltiples POPs. Nada sofisticado en la zona—A, AAAA, CNAME, unos pocos TXT. Lo aburrido era su disciplina: cada cambio pasaba por una zona de staging, rastreaban la intención de TTL y ensayaban un runbook DDoS trimestralmente.

Una tarde empezó un ataque: QPS alto con subdominios aleatorios más sondeos TXT y DNSKEY. Su monitorización señaló un fuerte aumento en la tasa NXDOMAIN y errores de recepción UDP en un POP. El on-call no entró en pánico. Siguió el playbook: confirmar drops, confirmar mezcla de consultas, habilitar límites más estrictos para respuestas NXDOMAIN, limitar tamaño EDNS y temporalmente de-preferenciar el POP sobre BGP.

El impacto al cliente fue mínimo. Algunos resolutores cayeron a TCP; algunas consultas se ralentizaron; pero el dominio siguió resolviéndose. El ataque se movió, como suelen hacer cuando dejas de ser un objetivo divertido.

La práctica que salvó no era un producto secreto. Fue medir líneas base, controles ensayados y la autoridad (organizativa) para aplicarlos rápido. La revisión del incidente fue corta, que es lo mejor.

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

1) Síntoma: muchos timeouts, pero la CPU no está al máximo

Causa raíz: Pérdidas de paquetes en NIC/kernel (ring buffers, buffers de socket), o congestión upstream.

Solución: Revisa ip -s link y netstat -su; aumenta buffers, reduce overhead por paquete, añade limitación en el borde, escala/anycast.

2) Síntoma: pico repentino en respuestas NXDOMAIN

Causa raíz: Inundación de subdominios aleatorios, o un cliente mal configurado generando qnames sin sentido.

Solución: Aumenta TTL negativo sensatamente, aplica límites NXDOMAIN por tasa e identifica redes origen que generan nombres con alta entropía.

3) Síntoma: aumento masivo de conexiones DNS TCP

Causa raíz: Truncación por respuestas UDP sobredimensionadas (DNSSEC, TXT grandes), EDNS mal dimensionado, o forzar deliberadamente TCP para agotar recursos.

Solución: Limita tamaño UDP EDNS, minimiza respuestas grandes, asegura capacidad TCP y limita por tasa qtypes abusivos.

4) Síntoma: fallos “aleatorios” de clientes detrás de redes móviles

Causa raíz: Limitación por IP castigando poblaciones NATed o grandes resolutores.

Solución: Usa límites por IP más altos, lista blanca de resolutores grandes que dependes o cambia a límites por qname/qtype que apunten a patrones abusivos.

5) Síntoma: servidores autoritativos se convierten en resolutores abiertos “accidentalmente”

Causa raíz: Recursión activada o ACLs demasiado amplias; a veces introducido al copiar una configuración recursiva en una autoritativa.

Solución: Desactiva recursión en autoritativos; audita la gestión de configuraciones; valida externamente que la recursión sea rechazada.

6) Síntoma: todo se rompe después de activar logging completo de consultas

Causa raíz: Overhead de I/O y CPU; pipeline de logs saturado; contención de locks en el demonio.

Solución: Apágalo primero. Luego implementa muestreo y métricas agregadas. Captura tcpdump cortos en lugar de intentar registrar el apocalipsis.

7) Síntoma: el tráfico “se mueve” durante un ataque y un POP se derrite

Causa raíz: Cambios de ruta anycast, peculiaridades de preferencia BGP, o un POP siendo apuntado específicamente.

Solución: Controla el enrutamiento: de-preferencia rutas para el POP caliente, asegura simetría de capacidad y confirma que cada POP tenga manejo DDoS upstream.

8) Síntoma: tiempo de recursión explota, tasa de cache hit baja

Causa raíz: Evasión de caché por qnames aleatorios; problemas de alcanzabilidad upstream; caches demasiado pequeños.

Solución: Limita clientes, habilita protecciones (mitigación de consultas no deseadas), escala resolutores horizontalmente y asegura diversidad de conectividad upstream.

Listas de verificación / plan paso a paso

Fase 0: antes de que te ataquen (haz esto en un martes tranquilo)

  1. Establece tu línea base. Registra QPS típico, mezcla de qtypes, tasa NXDOMAIN, latencia p50/p95, división UDP/TCP.
  2. Separa roles. Autoritativo y recursivo en instancias diferentes y preferiblemente en subredes/bordes distintos.
  3. Fija TTLs sensatos. No uses TTLs de 30 segundos para registros que cambian una vez al mes.
  4. Decide política EDNS. Limita payload UDP y verifica comportamiento con DNSSEC.
  5. Pon un borde consciente de DNS. dnsdist o equivalente, con un conjunto de reglas de emergencia probado que puedas activar rápido.
  6. Ensaya el playbook. Simula inundaciones NXDOMAIN y sondeos de respuestas grandes en un entorno de staging.

Fase 1: durante un pico (manténlo online primero)

  1. Confirma dónde duele. dig directo al autoritativo; compara interno vs externo.
  2. Encuentra el limitador. Pérdidas vs CPU vs latencia upstream (usa las tareas arriba).
  3. Aplica contención en el borde. Limita por fuente, luego por qtype/qname, luego ajusta el tamaño de respuesta.
  4. Estabiliza la latencia p95. Un “error rápido” suele ser mejor que un éxito lento en DNS, porque el éxito lento provoca reintentos.
  5. Reduce funciones caras temporalmente. Desactiva logging verboso; considera minimizar ciertas respuestas si tu software lo soporta con seguridad.
  6. Escala si puedes hacerlo limpiomente. Más instancias detrás de anycast/unicast NS, pero asegúrate de no replicar una mala configuración.

Fase 2: después del pico (haz que sea menos probable la próxima vez)

  1. Clasifica el tráfico. ¿Reflexión? ¿NXDOMAIN? ¿Aumento legítimo? ¿Cliente con mal comportamiento?
  2. Arregla los incentivos económicos. Aumenta TTLs, reduce tamaños de respuesta, minimiza amplificación y bloquea recursión abierta.
  3. Automatiza guardrails. Reglas de limitación preaprobadas y toggles seguros; dashboards que muestren mezcla de qtypes y tasa NXDOMAIN.
  4. Escribe un anexo de incidente de una página. Qué cambiaste, qué observaste y qué contadores lo probaron.

Preguntas frecuentes

1) ¿Debo limitar por dirección IP para DNS?

Sí, pero trátalo como un instrumento contundente. Los límites basados en IP pueden castigar poblaciones NATed y grandes resolutores públicos. Combínalos con controles conscientes de qtype/qname.

2) ¿Cuál es la limitación más segura para aplicar primero durante un ataque?

Empieza con shaping en el borde que apunte a patrones claramente abusivos: NXDOMAIN excesivos por origen, qtypes sospechosos (ráfagas de ANY, inundaciones TXT) y respuestas sobredimensionadas. Evita topes globales.

3) ¿El fallback a TCP es bueno o malo?

Ambas cosas. TCP reduce la utilidad de la reflexión suplantada y evita la fragmentación, pero cuesta más por consulta y también puede ser atacado. Dimensiona capacidad para TCP, pero no forces todo a TCP.

4) ¿Los TTL cortos empeoran los ataques DNS?

Los TTL cortos empeoran cualquier pico, ataque o no, porque los recursors deben refrescar más seguido. Usa TTLs cortos solo cuando realmente necesitas conmutación rápida.

5) ¿Cómo sé si me están usando para amplificación?

Busca muchas consultas con orígenes suplantados (difícil de probar directamente), qtypes inusuales (DNSKEY, ANY) y una relación bytes de respuesta/consulta que parezca absurda. Las muestras de paquetes ayudan.

6) ¿Puedo fiarme solo de mi proveedor DNS y dejar de preocuparme?

Puedes externalizar infraestructura, no responsabilidad. Aún necesitas TTLs sensatos, contenido de zona razonable y un plan de incidentes. Los proveedores no pueden arreglar una zona diseñada para amplificar.

7) ¿Cuál es la diferencia entre NXDOMAIN y NODATA, y por qué importa?

NXDOMAIN significa que el nombre no existe. NODATA significa que el nombre existe pero no ese tipo de registro. Los ataques usan ambos para evadir cachés; el TTL de caché negativo determina con qué frecuencia los resolutores vuelven a preguntar.

8) ¿Debería desactivar por completo las consultas ANY?

En autoritativos, al menos deberías minimizarlas. Algunos clientes aún piden ANY para diagnóstico. Proporciona una respuesta mínima y segura en lugar de una enorme.

9) ¿Por qué mi DNS “funciona” desde dentro de la VPC pero no desde Internet?

El tráfico interno evita congestión de borde y filtrado upstream. Las fallas externas suelen indicar saturación de PPS, problemas en scrubbing DDoS, cambios de enrutamiento anycast o problemas MTU/fragmentación.

10) ¿Qué métricas deberían estar en el dashboard de DNS?

QPS, PPS, latencia p50/p95, ratio UDP vs TCP, tasa NXDOMAIN, top qtypes, distribución de tamaños de respuesta, pérdidas del kernel y hit/miss de caché (para recursivos).

Conclusión: próximos pasos que realmente reducen el tiempo de inactividad

Si quieres que el DNS sobreviva picos sin tiempo de inactividad, deja de pensar en “bloquear al atacante”. Piensa en proteger la latencia para el tráfico legítimo mientras haces que el abuso sea caro y poco interesante.

  1. Implementa un borde consciente de DNS (dnsdist o equivalente) y preconfigura reglas de emergencia para inundaciones NXDOMAIN y qtypes abusivos.
  2. Limita el tamaño UDP EDNS y verifica el comportamiento DNSSEC para no fragmentarte a ti mismo en caídas.
  3. Arregla la estrategia de TTL: aumenta TTLs donde puedas, sube el TTL negativo a un valor sensato y mantén conmutación rápida solo para los registros que realmente la necesiten.
  4. Instrumenta pérdidas y latencia en NIC/kernel y en el demonio. Los gráficos de CPU solos son cómo los incidentes se vuelven folklore.
  5. Ensaya el playbook trimestralmente. El momento de aprender qué perilla lastima a los clientes no es durante un ataque.

DNS debería ser aburrido. Vuélvelo aburrido otra vez—ingeniérialo como si fuera crítico, porque lo es.

← Anterior
La caída de Nokia: cómo el rey de los teléfonos no tomó la curva
Siguiente →
pvedaemon.service falló en Proxmox: por qué las tareas no se ejecutan y cómo solucionarlo

Deja un comentario