Problema

En redes domésticas y de pequeñas oficinas es habitual combinar dos capas distintas: un filtro DNS que decide si un nombre debe resolverse y una política de salida que determina por qué túnel o interfaz pasa el tráfico. Cuando ambas capas están desacopladas, cada nuevo dispositivo o categoría de aplicación obliga a crear reglas en al menos dos lugares diferentes (lista de bloqueo y tabla de rutas). El resultado es una configuración fragmentada que se vuelve difícil de auditar, propensa a errores y que requiere scripts o glue manual para mantener la coherencia. Además, la mayoría de las soluciones populares (Pi‑hole, AdGuard Home) no ofrecen una forma nativa de redirigir tráfico DNS a un túnel específico por dispositivo, lo que obliga a usar VPNs o reglas de firewall externas que no siempre se alinean con la lógica de bloqueo.

Causa

  1. Separación de funciones en componentes diferentes – Los servidores DNS tradicionales solo devuelven respuestas; la decisión de usar un túnel recae en el cliente o en reglas de routing del router.
  2. Falta de visibilidad de origen – Cuando el filtro DNS no conoce la MAC/IP del cliente, no puede aplicar políticas basadas en identidad de dispositivo.
  3. Dependencia de privilegios de sistema – Implementar túneles (WireGuard, SOCKS5) suele requerir root o la creación de interfaces TUN, lo que complica la ejecución en entornos donde no se desea elevar privilegios.
  4. Gestión de listas de bloqueo fuera de línea – Los blocklists grandes se cargan en memoria sin índices eficientes, lo que genera latencias y consumo de RAM innecesario.
  5. Ausencia de integración con DNS‑over‑TLS/HTTPS – Sin una capa que pueda inspeccionar SNI antes de establecer la conexión, los filtros pierden capacidad de bloquear dominios que usan cifrado.

Solución

Un enfoque unificado consiste en un servidor DNS escrito en un lenguaje de alto rendimiento (por ejemplo Rust) que:

  • Mantenga una base de datos de bloqueos en un FST (Finite State Transducer) para consultas sub‑milisegundo y bajo consumo de RAM.
  • Asocie cada consulta al cliente (MAC, IP o nombre de host) mediante la información de la petición UDP/TCP.
  • Mapee dominios o grupos de dominios a un “egress”: salida directa, SOCKS5 (p.ej. Tor) o un túnel WireGuard configurado mediante archivo .conf.
  • Inyecte la resolución a través del túnel seleccionado antes de devolver la respuesta al cliente, garantizando que la ruta elegida sea la única posible para ese nombre.
  • No requiera privilegios de root: el proceso se ejecuta como usuario normal, abre puertos no privilegiados (>1024) y delega la creación del túnel a procesos en espacio de usuario (WireGuard‑userspace).
  • Soporte DoT/DoH/DoQ como upstreams, con stripping de ECS y sin telemetría.

Arquitectura resumida

  1. Listener DNS – Recibe consultas en UDP/5353 y TCP/853 (DoT).
  2. Resolver interno – Consulta el FST; si el dominio está bloqueado, responde con NXDOMAIN o 0.0.0.0.
  3. Motor de enrutamiento – Busca reglas por cliente → dominio → egress.
  4. Adaptador de túnel – Si el egress es WireGuard, abre una conexión UDP a la interfaz virtual gestionada por wireguard-go; si es SOCKS5, abre un socket al proxy local.
  5. Cache – Almacena respuestas válidas (incluyendo la información de egress) para acelerar consultas repetidas.

Cuándo aplicar esta solución

  • Redes con dispositivos heterogéneos (tablet de niños, IoT, estaciones de trabajo) que requieren políticas distintas de salida.
  • Entornos donde el root no está disponible (NAS, contenedores, servidores compartidos).
  • Necesidad de bloquear rastreadores sin sacrificar privacidad: la solución evita que un túnel “desbloquee” subdominios de trackers.
  • Escenarios con DPI agresivo: la opción de “evasion egress” que fragmenta el SNI permite pasar filtros de inspección profunda.

No es la mejor opción si:

  • Solo se necesita un sinkhole sin enrutamiento avanzado.
  • La infraestructura ya cuenta con un firewall capaz de aplicar reglas por MAC/IP y se prefiere mantener DNS simple.
  • Se requiere integración con DHCP para asignar automáticamente nombres de host; el servidor actual no provee DHCP.

Código

Instalación rápida (Linux, binario estático ≈ 20 MB):

```bash
curl -fsSL https://raw.githubusercontent.com/syntlyx/ferrite-server/main/install.sh | sudo sh

Ejemplo de archivo de configuración (/etc/ferrite/config.yaml):

listen:
  - address: 0.0.0.0
    port: 5353
    protocol: udp
  - address: 0.0.0.0
    port: 853
    protocol: dot

blocklist: /var/lib/ferrite/blocklist.fst

devices:
  tablet-kid:
    mac: "AA:BB:CC:DD:EE:FF"
    egress: tor
  iot-camera:
    ip: "192.168.1.45"
    egress: direct
  workstation:
    hostname: "workstation"
    egress: wg

egress:
  direct:
    type: direct
  tor:
    type: socks5
    address: 127.0.0.1:9050
  wg:
    type: wireguard
    config: /etc/wireguard/ferrite-wg.conf

Arranque del servicio (systemd):

sudo systemctl enable --now ferrite

Verificación

  1. Consulta directa – Desde un cliente configurado con egress: direct, ejecutar dig @<servidor> example.com. La respuesta debe llegar sin cambios de IP.
  2. Ruta a través de Tor – Desde el tablet, ejecutar dig @<servidor> check.torproject.org. Verificar que la IP pública devuelta corresponde a la salida de Tor (curl https://ifconfig.me).
  3. Bloqueo efectivo – Consultar un dominio listado en el blocklist (dig @<servidor> ads.tracker.com). La respuesta debe ser NXDOMAIN o 0.0.0.0.
  4. Cache hit – Repetir la consulta del paso 1 y observar en los logs que la respuesta se marca como “cache”.

Los logs de ferrite incluyen líneas como device=tablet-kid domain=example.com egress=tor action=forwarded, lo que ayuda a auditar la política aplicada.

Notas adicionales

  • Actualización de blocklists – Generar el FST a partir de un archivo de texto plano con fstool compile blocklist.txt > blocklist.fst. Automatizar con cron para mantener la lista fresca.
  • Persistencia de túneles – Cuando se usa wireguard-go, asegúrese de que el proceso se reinicie automáticamente (Restart=always en el unit).
  • Limitaciones de DoH – Algunos proveedores bloquean consultas a dominios no autorizados; en esos casos, prefiera DoT o DoQ.
  • Escalabilidad – En entornos con más de 200 dispositivos, considere distribuir la carga usando varios nodos Ferrite detrás de un balanceador DNS (Consul‑DNS o CoreDNS).
  • Seguridad – Mantenga el binario actualizado y firme su configuración con sops o age si necesita almacenar contraseñas de proxies.

Con esta arquitectura, el filtrado DNS y el enrutamiento por dispositivo se convierten en una única capa de control, eliminando la necesidad de scripts ad‑hoc y reduciendo la superficie de error. La solución se adapta bien a homelabs, pequeñas oficinas y cualquier entorno donde la privacidad y la granularidad de políticas sean prioritarias.