Homelab · Seguridad · 2026-09-03 · 4 min de lectura
Cuando el router de la oficina se volvió un arma
Mantengo un stack de monitoreo 24/7 para la red de una oficina en Córdoba: un router MikroTik y access points UniFi, observados desde una sola Raspberry Pi que corre Grafana, VictoriaMetrics y VictoriaLogs, alimentados por los exporters mktxp, unpoller, blackbox e IPFIX — diez contenedores, todo en docker-compose, con 17 reglas de alerta provisionadas que disparan a Slack.
Una de esas reglas es de una simpleza casi vergonzosa: conexiones activas por encima del umbral. Fue la que detectó esto.
La alerta
El contador de conexiones del router, que en reposo ronda las 700, saltó a ~2.600 y se quedó ahí. Ningún reclamo de usuarios precedió a la alerta — ataques como este rara vez se anuncian como algo peor que "internet anda medio lento".
Los flows de la interfaz WAN mostraron el patrón de inmediato: una inundación de paquetes UDP/53 pequeños llegando desde internet, y paquetes UDP/53 mucho más grandes saliendo. El router estaba respondiendo consultas DNS desde la WAN.
El diagnóstico: un open resolver
El cliente DNS de MikroTik también funciona como servidor DNS. La opción que hace que el router resuelva nombres para la LAN —
/ip dns
set allow-remote-requests=yes servers=8.8.8.8,...
— lo hace resolver nombres para cualquiera que alcance UDP/53, salvo que el firewall diga lo contrario. Y el firewall no decía nada.
Eso es un open resolver, y los open resolvers se encuentran rápido. Los atacantes los usan como reflectores en un ataque de amplificación DNS: envían una consulta pequeña con la dirección de origen falsificada de la víctima, y el resolver le manda a la víctima una respuesta mucho más grande. En nuestra captura: una consulta de 132 bytes que producía una respuesta de 4.980 bytes — una amplificación de ~37×. El router de la oficina no era el objetivo; era munición contra otro, quemando nuestro enlace y la CPU del router en el proceso. (Cloudflare tiene un buen explicador de la mecánica: ataques de amplificación DNS.)
El fix, y dónde corresponde ponerlo
La jugada obvia es una regla de filtro: drop de UDP/53 desde WAN en la cadena input. Funciona, pero hay una sutileza que importa bajo el volumen de un ataque: filter corre después del connection tracking. Cada paquete falsificado igual crea una entrada de conntrack antes de ser descartado — seguís pagando CPU y espacio en la tabla de conexiones por tráfico que ya decidiste tirar. El contador de conexiones sigue inflado y, en un router chico, agotar conntrack se convierte en su propia denegación de servicio.
RouterOS tiene una tabla diseñada exactamente para esto: raw, cuya cadena prerouting corre antes de conntrack (documentación del firewall de RouterOS). Los paquetes descartados ahí nunca tocan la tabla de conexiones:
/ip firewall raw
add action=drop chain=prerouting protocol=udp dst-port=53 \
in-interface-list=WAN \
comment="Anti DNS amplification - drop pre-conntrack"
Noten lo que esto no hace: no deshabilita el resolver. La LAN sigue resolviendo a través del router con normalidad — allow-remote-requests queda activo, pero la WAN ya no puede alcanzarlo. El servicio no era el problema; su exposición sí.
Ya que estaba: defensa en profundidad
Un incidente es algo demasiado valioso para desperdiciarlo, así que el resto del firewall se endureció en la misma sesión:
- Ban escalonado anti fuerza bruta en los puertos de management (SSH 22, Winbox 8291, API 8728), estilo fail2ban usando solo address lists: el primer intento de conexión desde la WAN te pone en
wan_stage1(1 min), el segundo enwan_stage2(1 min), y el tercero te deja baneado por una semana — logueado con el prefijoWAN-BAN:
/ip firewall filter
add action=add-src-to-address-list address-list=wan_stage1 \
address-list-timeout=1m chain=input connection-state=new \
dst-port=22,8291,8728 protocol=tcp in-interface-list=WAN
add action=add-src-to-address-list address-list=wan_stage2 \
address-list-timeout=1m chain=input connection-state=new \
dst-port=22,8291,8728 protocol=tcp in-interface-list=WAN \
src-address-list=wan_stage1
add action=add-src-to-address-list address-list=wan_blacklist \
address-list-timeout=1w chain=input connection-state=new \
dst-port=22,8291,8728 protocol=tcp in-interface-list=WAN \
src-address-list=wan_stage2 log=yes log-prefix=WAN-BAN
add action=drop chain=input src-address-list=wan_blacklist
- Default-drop desde internet: después de los accepts explícitos (established/related, ICMP, el puerto de la VPN), una regla final de
drop todo lo demás desde WANeninput. - Management fuera de internet por completo: Winbox, SSH y la API ahora solo son alcanzables por WireGuard.
- Wi-Fi de invitados aislado de la LAN con un drop explícito en la cadena forward.
Resultados
- Conexiones activas: 2.600 → ~700 (de vuelta a la línea base) en el momento en que entró la regla raw.
- Tráfico del ataque: → 0. Sin reflector, los atacantes siguieron de largo — siempre tienen más open resolvers para elegir.
- Superficie de management en la WAN: cero puertos, solo VPN.
- Y los mismos dashboards de Grafana que levantaron la alerta ahora muestran el antes y el después, que es un cierre satisfactorio.
Lecciones
- 1. Un open resolver es un pasivo a cualquier escala. Esto no era un datacenter — era un router de oficina con una config DNS casi default.
- 2. Dónde descartás importa tanto como qué descartás. Bajo una inundación,
raw/pre-conntrack versusfilteres la diferencia entre sacudirse el ataque y fundir la tabla de conexiones. - 3. No podés arreglar lo que no ves. El ataque no produjo caída, ni error, ni reporte de usuario — solo una métrica que abandonó su línea base. Sin el stack de monitoreo habría corrido durante meses.
- 4. Las address lists con timeout son un sistema de prevención de intrusiones completo en cuatro reglas de firewall.