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
EDNSactivado 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”
- Desde una red cliente afectada, consulta tu autoritativo directamente (evita la recursión). Comprueba latencia y timeouts.
- 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.
- Comprueba si el pico está en autoritativo, recursivo o ambos. Fallen de maneras diferentes.
Segundo: localiza la capa que hace de cuello de botella
- Entrada de red: pérdidas de paquetes en NIC/kernel, torbellinos conntrack, límites de PPS.
- Demonio: CPU por hilo, contención de locks, tormentas de fallos de caché, costos de firmar/validar DNSSEC.
- 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
- Despliega limitación de tasa en el borde (dnsdist / firewall / load balancer) antes de tocar internals del demonio.
- Prioriza: mantén funcionales A/AAAA/CNAME/SOA/NS básicos. Degrada lo “agradable de tener” (ANY, TXT, respuestas grandes).
- 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.
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)
- Establece tu línea base. Registra QPS típico, mezcla de qtypes, tasa NXDOMAIN, latencia p50/p95, división UDP/TCP.
- Separa roles. Autoritativo y recursivo en instancias diferentes y preferiblemente en subredes/bordes distintos.
- Fija TTLs sensatos. No uses TTLs de 30 segundos para registros que cambian una vez al mes.
- Decide política EDNS. Limita payload UDP y verifica comportamiento con DNSSEC.
- Pon un borde consciente de DNS. dnsdist o equivalente, con un conjunto de reglas de emergencia probado que puedas activar rápido.
- 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)
- Confirma dónde duele. dig directo al autoritativo; compara interno vs externo.
- Encuentra el limitador. Pérdidas vs CPU vs latencia upstream (usa las tareas arriba).
- Aplica contención en el borde. Limita por fuente, luego por qtype/qname, luego ajusta el tamaño de respuesta.
- Estabiliza la latencia p95. Un “error rápido” suele ser mejor que un éxito lento en DNS, porque el éxito lento provoca reintentos.
- Reduce funciones caras temporalmente. Desactiva logging verboso; considera minimizar ciertas respuestas si tu software lo soporta con seguridad.
- 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)
- Clasifica el tráfico. ¿Reflexión? ¿NXDOMAIN? ¿Aumento legítimo? ¿Cliente con mal comportamiento?
- Arregla los incentivos económicos. Aumenta TTLs, reduce tamaños de respuesta, minimiza amplificación y bloquea recursión abierta.
- Automatiza guardrails. Reglas de limitación preaprobadas y toggles seguros; dashboards que muestren mezcla de qtypes y tasa NXDOMAIN.
- 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.
- Implementa un borde consciente de DNS (dnsdist o equivalente) y preconfigura reglas de emergencia para inundaciones NXDOMAIN y qtypes abusivos.
- Limita el tamaño UDP EDNS y verifica el comportamiento DNSSEC para no fragmentarte a ti mismo en caídas.
- 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.
- 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.
- 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.