Todos los sistemas operativos 6 regiones offshore Pago sin KYC
Hands-on Guía de campo

Tu propio resolver DNS en un VPS: el log que nadie más guarda

Cifraste el tráfico, moviste la máquina a un país offshore y pagaste en Monero. Luego tecleaste un nombre de dominio, y antes de que un solo byte cifrado saliera de la máquina, tu dispositivo le preguntó a un desconocido adónde enviarlo — y ese desconocido se queda con la pregunta. El log de un resolver es la descripción más completa de una persona que existe en una red: cada sitio, cada app, cada servicio en segundo plano, en orden, con marcas de tiempo. Esta guía traslada ese log a una máquina que alquilas tú mismo — un Unbound recursivo que valida DNSSEC, en el plan más barato de la lista, accesible solo a través de tu propio túnel, y, en la parte que la mayoría de los tutoriales omite, sin ser un resolver abierto que alguien más pueda apuntar contra una víctima.

Actualizado el 2026-09-15 · 15 min de lectura · Operaciones de flota
En esta página
  1. El log que te describe mejor que tu historial del navegador
  2. El reenvío traslada el log. La recursión lo fragmenta.
  3. Lo que esto oculta, y lo que claramente no oculta
  4. El error que convierte tu resolver en el arma de otro
  5. Los valores por defecto de Unbound son sensatos. No son privados.
  6. Dos formas de entrar: el túnel, o DNS sobre TLS
  7. Bloquear es un producto distinto; decide antes de añadirlo a la ligera
  8. Un resolver que administras tú es una dependencia tuya
  9. Paso a paso
SP·01

El log que te describe mejor que tu historial del navegador

Antes de que tu máquina pueda enviar un solo byte cifrado a un sitio web, tiene que preguntarle a alguien dónde vive ese sitio. Esa pregunta viaja en claro, hacia un resolver que casi con toda seguridad no elegiste tú, y la respuesta a quién la conserva decide cuánto de tu vida queda por escrito. Un historial de navegador es una lista de páginas que decidiste conservar. El log de un resolver lo es todo: cada sitio, cada app que comprueba si hay actualizaciones, cada servicio en la nube con el que habla tu teléfono mientras duermes, cada dominio de cada correo que abriste, en orden, con marca de tiempo, hubiera o no un humano mirando la pantalla.

Lee una semana de eso y puedes reconstruir a una persona. El banco que usa, la aerolínea que acaba de reservar, la farmacia, la app de citas, el sistema de seguimiento de candidatos del reclutador, la hora a la que se despierta y la hora a la que se detiene. Nada de eso requiere romper ninguna clase de cifrado. Los nombres por sí solos lo revelan, y los nombres son la única parte de la transacción que, en la mayoría de las configuraciones, sigue entregándose a un tercero por diseño.

Hoy ese tercero es quienquiera que te haya asignado tu concesión DHCP — tu ISP, tu empresa, la cafetería. La gente que se da cuenta de esto suele cambiarse a un resolver público, lo cual es una mejora real en integridad y un movimiento lateral en privacidad: no has eliminado al observador, has cambiado de qué empresa se trata, cambiando una teleco regulada por una CDN cercana a la publicidad o una organización sin ánimo de lucro cuya política podría cambiar con su financiación. Las buenas publican políticas de retención honestas y algunas de verdad las cumplen. Pero una política es una promesa sobre el comportamiento, y un archivo de configuración es una afirmación sobre la capacidad. No puedes auditar una promesa. Puedes auditar veinte líneas que escribiste tú mismo, en una máquina que alquilas, en un país que elegiste.

SP·02

El reenvío traslada el log. La recursión lo fragmenta.

Casi todo tutorial que dice "monta tu propio servidor DNS" termina construyendo un forwarder: una pequeña caché en tu red que reenvía a 1.1.1.1 o 9.9.9.9 cualquier cosa que no conoce. Es algo genuinamente útil — es rápido, son cinco líneas, y evita que tu red local te vigile. También deja el log agregado exactamente donde estaba. Cada nombre que buscas sigue llegando a una sola empresa, ahora convenientemente pre-etiquetado con la única dirección IP de tu resolver, lo cual hace que el flujo sea más fácil de atribuir, no más difícil.

Un resolver recursivo hace el trabajo en lugar de delegarlo. Al preguntar por news.example.io, consulta a un servidor raíz quién gestiona .io, después consulta a los servidores de .io quién gestiona example.io, y solo entonces le pregunta directamente a ese operador. Tres conversaciones con tres partes no relacionadas entre sí, ninguna de las cuales se dedica a la agregación, y — esta es la parte que importa — ninguna de ellas ve jamás tu flujo completo de consultas. Los operadores de la raíz ven un goteo de peticiones de TLD. Verisign ve que alguien en tu dirección tocó algo bajo .com. El servidor autoritativo de un dominio ve el tráfico que de todos modos iba a ver, porque estás a punto de conectarte a él en cualquier caso.

La minimización de QNAME agudiza esto de forma considerable, y el Unbound moderno la aplica por defecto. En lugar de enviar el nombre completo a cada servidor de la cadena — que es lo que hicieron los resolvers durante treinta años — envía a cada servidor solo la etiqueta que necesita para responder: io. a la raíz, example.io. a los servidores de .io, y solo entonces el news.example.io. completo al operador que tiene derecho a conocerlo. La jerarquía deja de ser una emisión pública de tus intenciones y se convierte en lo que siempre se dibujó que era: una delegación.

El compromiso es real y merece la pena decirlo sin rodeos. Una consulta recursiva en frío da varios saltos de ida y vuelta donde un forwarder da uno solo, así que la primera visita a un dominio desconocido es perceptiblemente más lenta. Heredas la responsabilidad de una caché que antes era problema de otro. Y ya no te beneficias de una caché compartida, calentada por millones de otras personas. A cambio, el registro completo, ordenado y con marca de tiempo de lo que buscaste deja de existir en cualquier sitio que no sea tu propio disco.

SP·03

Lo que esto oculta, y lo que claramente no oculta

El alcance honesto es más estrecho de lo que sugiere el marketing en torno al DNS privado, y conocer esos límites es lo que te impide tomar una mala decisión apoyado solo en una buena sensación.

Elimina una cosa: el log agregado de nombres que mantiene un único observador. Eso es mucho, porque el agregado es lo que tiene valor comercial y lo que se solicita a granel. No es todo.

No oculta la conexión. Después de que la consulta se resuelve, tu dispositivo sigue abriendo una sesión hacia esa dirección, y cualquiera que observe tu enlace de subida ve la IP de destino. Para un sitio en infraestructura dedicada, la IP es la identidad. Tampoco oculta el hostname en el cable: a menos que ambos extremos admitan Encrypted Client Hello, el handshake de TLS sigue llevando el nombre del servidor en texto plano, que es la misma información que habría tenido tu resolver.

No oculta las consultas frente a tu proveedor de hosting. Este es el punto que la gente suele entender mal, así que merece decirse sin rodeos: el tráfico saliente de tu resolver — las preguntas que hace a la raíz, al TLD y a los servidores autoritativos — sale del VPS por el puerto UDP 53, sin cifrar, y la red en la que vive tu servidor puede leerlo todo. No hay DoT hacia la raíz. No has eliminado al observador tanto como lo has trasladado: de un ISP de consumo que vende datos y responde a citaciones judiciales en tu propio país, a una red de hosting en una jurisdicción que elegiste a propósito, que ve un flujo fragmentado gracias a la minimización de QNAME. Eso es una mejora genuina, y es un argumento sobre qué ley rige el cable, no algo que un archivo de configuración pueda resolver.

Y no te da una multitud. Un resolver usado por un solo hogar atribuye cada consulta a ese hogar sin ninguna ambigüedad. Frente a un adversario pasivo global, un resolver compartido y concurrido es, de verdad, un mejor escondite. Frente a tu ISP, tu empresa, los data brokers que compran telemetría de resolvers, y las solicitudes masivas rutinarias que de verdad le ocurren a la gente corriente, el tuyo es mejor — siempre que el último salto desde tus dispositivos esté dentro de un túnel. Usa esto junto con tu propio túnel WireGuard, no en su lugar. Por sí solo, un resolver privado sobre todo reubica tus metadatos. Detrás de un túnel, cierra el único canal que el túnel deja abierto.

SP·04

El error que convierte tu resolver en el arma de otro

Hay exactamente una forma de equivocarse gravemente con esto, es fácil hacerlo por accidente, y las consecuencias caen sobre desconocidos antes de caer sobre ti.

Un resolver que responde a cualquiera es un resolver abierto, y un resolver abierto es un amplificador. El DNS corre sobre UDP, las direcciones de origen UDP se falsifican con trivial facilidad, y una consulta pequeña puede producir una respuesta muchas veces mayor. Un atacante le envía a tu máquina una pregunta de 60 bytes con la dirección de una víctima falsificada como remitente; tu máquina, obedientemente, le envía a la víctima una respuesta varias docenas de veces mayor. Haz eso desde unos pocos miles de resolvers abiertos a la vez y la víctima queda fuera de internet, tras recibir una inundación que parece — con precisión, a nivel de paquete — venir de ti. Tú no eres el objetivo. Tú eres el arma, y el tráfico del informe del incidente es tuyo.

Lo que viene después no tiene nada de glamuroso: informes de abuso de redes de las que nunca has oído hablar, un proveedor que aplica un null route a tu dirección para proteger su propio tránsito, y una conversación sobre tu cuenta que preferirías no tener. Terminas en el extremo causante exactamente del tipo de evento descrito en nuestro runbook de la primera hora ante un DDoS, y no existe ninguna versión de esa historia en la que tu uptime sobreviva.

Dos cerrojos independientes lo evitan, y quieres los dos, porque cada uno cubre el fallo del otro. El primero es el propio access-control de Unbound, que debería refuse a todo internet en ambas familias de IP y después allow explícitamente el loopback y la subred de tu túnel — una lista de denegación por defecto, no una lista de permisos con una cola permisiva. El segundo es dónde escucha el daemon siquiera: vincúlalo a 127.0.0.1 y a la dirección del túnel, nunca a 0.0.0.0, y mantén el puerto 53 cerrado en la interfaz pública a nivel de firewall.

La trampa es hacer solo lo primero. Una regla de access-control no hace que el puerto desaparezca; una consulta rechazada sigue siendo un paquete recibido y un paquete enviado, tu dirección sigue apareciendo en los escaneos que mapean resolvers abiertos, y una edición posterior al bloque equivocado convierte un rechazo en una respuesta. Vincular el servicio a esas direcciones y cerrarlo en el firewall convierten el error en algo estructuralmente imposible, en lugar de dejarlo a una línea de configuración de distancia. Si la máquina también corre contenedores, vuelve a leer cómo Docker publica puertos rodeando tu firewall antes de asumir que la regla que escribiste es la regla que está en vigor.

SP·05

Los valores por defecto de Unbound son sensatos. No son privados.

Unbound se entrega afinado para la corrección y la estabilidad, que es el valor por defecto correcto para un software que en su mayoría despliegan ISPs. Un puñado de ajustes lo convierten en algo pensado para quien lo administra. Ninguno es exótico; simplemente vienen apagados, o sin una postura definida, de fábrica.

Deja de responder preguntas sobre ti mismo. Por defecto, un resolver informa alegremente de la versión de su software y su hostname a través de la clase CHAOSversion.bind y hostname.bind — lo cual es reconocimiento gratuito para cualquiera que esté decidiendo si tu máquina merece atención. hide-identity y hide-version no cuestan nada y eliminan una huella identificable.

Falla cerrado, no abierto. La validación DNSSEC es la diferencia entre un resolver que detecta una respuesta falsificada y uno que la sirve. harden-dnssec-stripped se niega a aceptar una respuesta sin firmar para una zona que debería estar firmada, harden-glue y harden-below-nxdomain cierran dos vías clásicas de envenenamiento de caché, y aggressive-nsec permite que el resolver responda nombres inexistentes directamente desde los registros de denegación en caché, en lugar de volver a preguntar. use-caps-for-id añade una capitalización aleatoria como entropía adicional contra el spoofing ciego — barato, y en ocasiones incompatible con un servidor autoritativo mal construido, lo cual conviene saber antes de perder una tarde con un dominio que no resuelve.

No escribas nada. Unbound no registra las consultas a menos que se le pida, pero los ajustes que harían eso están a una sola línea sin comentar de distancia, y algunos paquetes de distribución vienen con un valor por defecto más locuaz. Fija verbosity: 0 y declara log-queries: no explícitamente, para que la intención sea visible en el archivo en lugar de inferirse de su ausencia. Luego recuerda la parte que no es un ajuste: la propia caché es un registro. unbound-control dump_cache, en una máquina en marcha, imprime un historial reciente de lo que esa máquina ha buscado, y vive en la memoria de una máquina que otras manos pueden alcanzar. Se expira por sí sola, que es la razón por la que los tiempos de vida cortos en caché y la privacidad están en ligera tensión, y es la razón para no mantener un resolver vivo durante meses en un host en el que no confías en absoluto.

Almacena en caché deliberadamente. Cada respuesta servida desde la caché es una observación que nunca llega a producirse aguas arriba, así que una caché saludable es una característica de privacidad, y no solo de velocidad. prefetch renueva los registros populares antes de que caduquen, así que el caso común deja de tocar la red por completo; serve-expired te mantiene en línea cuando un servidor autoritativo está brevemente inalcanzable. Subir cache-min-ttl reduce todavía más la charla aguas arriba, pero anula decisiones deliberadas de los operadores de dominios — los TTL bajos son cómo funcionan las CDN y el failover — así que un mínimo de uno o dos minutos es razonable, y una hora acabará dejándote varado en una dirección muerta.

SP·06

Dos formas de entrar: el túnel, o DNS sobre TLS

Tus dispositivos tienen que llegar al resolver de alguna manera, y la elección entre las dos opciones sensatas es sobre todo una cuestión de qué estás dispuesto a publicar.

El túnel es la mejor respuesta para casi todo el mundo. Si tu portátil y tu teléfono ya mantienen una sesión WireGuard con ese servidor, el resolver puede escuchar en la dirección del túnel y hablar DNS normal por el puerto 53. El tráfico ya está cifrado y ya autenticado por el túnel, así que no hay ningún certificado que obtener, ningún puerto nuevo abierto a internet, ninguna pila TLS expuesta a desconocidos y — la parte que se subestima — ningún hostname en ninguna parte. La guía de WireGuard de este sitio deja a los clientes apuntando a DNS = 9.9.9.9 precisamente porque todavía no había nada mejor que poner ahí. Esto es lo que va en esa línea en su lugar: la dirección del túnel de tu propio servidor.

DNS sobre TLS es para el dispositivo que no puede mantener un túnel. El campo de DNS privado de Android es el mejor argumento a su favor — se aplica a todo el sistema, sobrevive a los reinicios, y cubre apps a las que no puedes llegar de otro modo. El coste es un hostname con un certificado válido, y un certificado significa una entrada pública y permanente en los registros de Certificate Transparency que vincula ese nombre al momento en que lo creaste. El DNS pasivo atará después ese nombre a la dirección del servidor. Si el objetivo del ejercicio era mantener tu nombre fuera de la infraestructura, usa un hostname que no lleve a nada cercano a ti, y regístralo con el cuidado descrito en registrar un dominio de forma anónima — no un subdominio del dominio que usas para todo lo demás, que ligaría los dos de forma permanente.

Hay un segundo coste, más sutil. Un endpoint DoT al que puedan llegar teléfonos en itinerancia no se puede restringir por dirección de origen, así que es, por definición, un resolver que cualquier desconocido puede usar si averigua el nombre. No es un amplificador — TLS sobre TCP exige un handshake completo, así que el origen no se puede falsificar y no hay nada que reflejar — pero es capacidad que estás regalando, y un servicio que merece la pena escanear en busca de él. Mantén activos los límites de tasa por IP, elige un hostname que nadie vaya a adivinar, y trátalo como una excepción deliberada para uno o dos dispositivos, no como la puerta por defecto.

DNS sobre HTTPS es una tercera opción, y normalmente la equivocada aquí. Necesita un servidor web delante del resolver, lo cual son más piezas en movimiento y una superficie de ataque mayor por el único beneficio de ser indistinguible del tráfico web. Ese beneficio es decisivo si estás esquivando una red que bloquea DoT, e irrelevante si no es tu caso.

SP·07

Bloquear es un producto distinto; decide antes de añadirlo a la ligera

Tarde o temprano alguien sugiere añadir blocklists, y el argumento de venta es genuinamente atractivo: filtrar en el resolver cubre todos los dispositivos del túnel, incluida la smart TV y las apps del teléfono a las que ninguna extensión puede llegar. En móvil, en particular, es el único lugar práctico donde intervenir. Es también la funcionalidad con más probabilidades de hacer que desconfíes en silencio de tu propia infraestructura, y merece la pena entender por qué antes de que pase, no mientras pasa.

El primer coste es que los fallos no parecen fallos. Un resolver roto se anuncia a sí mismo; un dominio bloqueado se presenta como un botón de pago que no hace nada, una app atascada en una rueda de carga, un correo que nunca llega. El síntoma aparece semanas después de que instalaste la lista, en un dispositivo en el que no estabas pensando, y nada lo conecta con una decisión de DNS que tomaste otro mes. Cada blocklist que instalas es una política escrita por un desconocido y aplicada en silencio sobre tu hogar. Si añades una, apunta que lo hiciste, mantenla pequeña y de confianza, y conserva una forma de desactivarla con un solo comando — el primer paso de depuración para cualquier cosa inexplicada en tu red se convierte en "saltarse el filtro y reintentar", y ese paso tiene que ser barato.

El segundo coste es que no hace lo que la gente espera. Una aplicación con la dirección del resolver fijada en el código, o con su propio cliente DoH incluido, nunca le pregunta nada a tu resolver; abre una conexión a una IP fijada en el código, y se acabó. Los navegadores cada vez más resuelven por su propio DoH salvo que se les indique lo contrario. El bloqueo de DNS es una capa de higiene que elimina mucho ruido de rastreo y publicidad de bajo esfuerzo, y no es un control de seguridad, porque cualquier cosa hostil lo rodea por diseño.

Si de todas formas la quieres, prefiere una pequeña zona local en Unbound antes que un segundo daemon — local-zone: "tracker.example." always_nxdomain no necesita software adicional, ninguna interfaz web en un puerto que después tengas que defender, ni ningún servicio nuevo que pueda caerse y arrastrar contigo la resolución de nombres. Mantén la descripción del trabajo de la máquina en una sola línea: resuelve nombres. Cada responsabilidad adicional que le das es una forma más de que todo deje de funcionar a la vez.

SP·08

Un resolver que administras tú es una dependencia tuya

Cuando se cae un sitio web que alojas, algunas personas no pueden leer algo. Cuando se cae tu resolver, no funciona nada — ni el navegador, ni el correo, ni el gestor de paquetes, ni la app que iba a avisarte de que el servidor está caído. Es el servicio con más carga que puedes poner en una máquina barata, y falla de formas que no parecen DNS.

Merece la pena conocer de antemano los modos de fallo realistas, porque cada uno tiene una firma distinta. El VPS se reinicia y Unbound nunca se activó al arranque, así que todo funciona hasta el primer reinicio no planeado. Una blocklist grande empuja la caché al swap en una instancia de 1 GB, y el OOM killer elige al resolver. Una zona en algún lugar rompe sus propias firmas DNSSEC, y tu resolver correctamente configurado rechaza la respuesta mientras todo el mundo con un resolver que no valida sigue navegando — tu máquina tiene razón, y aun así el sitio te parece roto, lo cual son cinco minutos confusos si te has olvidado de que tú validas. O el túnel se cae, y como DNS = 10.66.0.1 solo existe dentro del túnel, el dispositivo no tiene ningún resolver en absoluto y reporta que está sin conexión.

Las mitigaciones son afortunadamente baratas. Activa el servicio al arranque y pruébalo de verdad con un reinicio, en lugar de asumirlo. Dales a los clientes un resolver secundario para que un túnel muerto degrade el servicio en lugar de detenerlo — un resolver público en esa ranura es un compromiso de privacidad pequeño y explícito que solo se aplica mientras el tuyo es inalcanzable, y suele ser el cambio correcto. Mantén activado serve-expired para que una interrupción breve aguas arriba no se convierta en tu propia interrupción. Comprueba el resolver desde otro sitio, no desde la propia máquina, que es la única forma de notar la diferencia entre "caído" e "inalcanzable".

Y conserva una copia de la configuración. Todo el asunto son unas pocas docenas de líneas que te costó una tarde dejar bien, y que no recordarás dentro de un año; pertenece en tus copias de seguridad cifradas fuera de sitio, junto a las claves de WireGuard, para que reconstruirlo sean veinte minutos y no una segunda tarde. Ese es el resumen honesto de todo este ejercicio: una máquina pequeña haciendo un solo trabajo, por el precio del plan más barato de la lista, sustituyendo una promesa sobre retención por un arreglo en el que el registro sencillamente nunca llega a crearse.

SP·09

Paso a paso

  1. 01

    Empieza desde una máquina que ya esté bien asegurada

    Un resolver es un servicio pequeño y silencioso, lo cual tienta a instalarlo en lo primero que haya a mano. No lo hagas — esta máquina va a ver cada nombre que busque cada dispositivo de tu túnel, así que merece el mismo trato que cualquier otra cosa que guarde secretos. Despliega el plan más pequeño que quieras; 1 GB de RAM es de sobra para un hogar, ya que los tamaños de caché de más abajo se miden en decenas de megabytes. Repasa la primera hora tras el despliegue antes de nada: un usuario con nombre, SSH solo por clave, denegación por defecto en ambas familias de IP, actualizaciones de seguridad desatendidas.

    Después instala Unbound. El paquete de la distribución incluye los root hints y el ancla de confianza raíz de DNSSEC, y configura la rotación automática del ancla, que es uno de los pocos casos en los que la versión empaquetada de verdad te ahorra una clase entera de problemas futuros.

    sudo apt update && sudo apt install -y unbound dnsutils
    unbound -V | head -n 3
    
    # the packaged trust anchor the resolver will validate against
    sudo ls -l /var/lib/unbound/root.key

    Si falta root.key, tu paquete no ejecutó unbound-anchor, y la validación fallará cerrada en todo. Genéralo una vez con sudo -u unbound unbound-anchor -a /var/lib/unbound/root.key antes de continuar.

  2. 02

    Recupera el puerto 53 de systemd-resolved

    En la mayoría de las distribuciones actuales, algo ya es dueño del puerto 53: systemd-resolved ejecuta un listener stub en 127.0.0.53, y /etc/resolv.conf es un symlink que apunta a él. Unbound se negará a arrancar, o arrancará sin vincular nada útil, hasta que eso se resuelva. Mira antes de editar.

    ss -ulpn 'sport = :53'
    ls -l /etc/resolv.conf

    Lee este párrafo antes de ejecutar el siguiente bloque: entre desactivar el stub y arrancar Unbound, esta máquina no tiene ningún DNS funcional en absoluto. Termina los pasos 3 y 4 de una sola sentada, y no lances antes una operación de apt en otra ventana — se quedará colgada en una búsqueda de nombre, y la vas a diagnosticar mal, pensando que es el resolver que todavía no has arrancado.

    # stop resolved from holding the port (appends inside the [Resolve] section)
    printf 'DNSStubListener=no\n' | sudo tee -a /etc/systemd/resolved.conf
    sudo systemctl restart systemd-resolved
    
    # point the host at the resolver it is about to run
    sudo rm -f /etc/resolv.conf
    printf 'nameserver 127.0.0.1\noptions edns0 trust-ad\n' | sudo tee /etc/resolv.conf
    
    # the port should now be free
    ss -ulpn 'sport = :53'
  3. 03

    Escribe una configuración que recursa y olvida

    Deja intacta la configuración empaquetada y añade tu propio archivo en el directorio drop-in, para que una actualización del paquete nunca revierta tus decisiones en silencio. Cada línea de abajo trata sobre rechazar a desconocidos, recursar desde la raíz, o no guardar registros. Sustituye 10.66.0.1 y 10.66.0.0/24 por la dirección y la subred del túnel de tu propio servidor WireGuard si son distintas.

    sudo tee /etc/unbound/unbound.conf.d/private-resolver.conf > /dev/null <<'EOF'
    server:
        # listen for the host itself and for the tunnel — never on 0.0.0.0
        interface: 127.0.0.1
        interface: 10.66.0.1
        port: 53
    
        # default-deny: refuse the internet, then allow what you trust
        access-control: 0.0.0.0/0 refuse
        access-control: ::/0 refuse
        access-control: 127.0.0.0/8 allow
        access-control: 10.66.0.0/24 allow
    
        # recurse from the root and send each server only the label it needs
        qname-minimisation: yes
        harden-dnssec-stripped: yes
        harden-below-nxdomain: yes
        harden-glue: yes
        aggressive-nsec: yes
        use-caps-for-id: yes
    
        # answer nothing about the software or the host
        hide-identity: yes
        hide-version: yes
    
        # keep no query log, and say little to the journal
        verbosity: 0
        log-queries: no
        log-replies: no
    
        # a warm cache is an upstream observation that never happens
        cache-min-ttl: 120
        cache-max-ttl: 86400
        prefetch: yes
        prefetch-key: yes
        serve-expired: yes
    
        # belt and braces if a rule above is ever loosened
        ratelimit: 1000
        ip-ratelimit: 100
    
        # sizing for a small instance
        num-threads: 2
        so-reuseport: yes
        msg-cache-size: 32m
        rrset-cache-size: 64m
    EOF

    Fíjate en lo que no está en el archivo: no hay ningún forward-zone. Su ausencia es lo que convierte esto en un resolver recursivo en lugar de una caché delante de la de otro. Si más adelante pegas un fragmento de un tutorial que añade uno, has deshecho en silencio todo el sentido del ejercicio.

  4. 04

    Arráncalo, y después demuestra que DNSSEC valida de verdad

    Comprueba la sintaxis antes de reiniciar nada — en una máquina cuyo propio resolv.conf ahora apunta a Unbound, un error de configuración significa cero resolución de nombres mientras lo depuras.

    sudo unbound-checkconf
    sudo systemctl enable --now unbound
    systemctl --no-pager status unbound | head -n 5

    Ahora verifica los dos comportamientos que importan, porque un resolver que responde no es lo mismo que un resolver que valida. Un nombre firmado debe volver con el flag ad — datos autenticados — y un nombre con firmas rotas a propósito debe fallar cerrado con SERVFAIL en lugar de resolver.

    # should show: flags: qr rd ra ad
    dig @127.0.0.1 example.com +dnssec | grep -E '^;; flags'
    
    # should show: status: SERVFAIL  (not NOERROR, not an address)
    dig @127.0.0.1 dnssec-failed.org | grep -E '^;; ->>HEADER'
    
    # and a normal name should simply work
    dig @127.0.0.1 +short cloudflare.com

    Si la zona rota resuelve a una dirección, la validación no está funcionando: comprueba que /var/lib/unbound/root.key existe y es legible por el usuario unbound. Si todo es SERVFAIL, la causa habitual es un reloj que está muy desincronizado — las firmas tienen ventanas de validez, y una máquina desincronizada varias horas rechaza todo internet.

  5. 05

    Cierra la puerta pública, abre solo el túnel

    La configuración ya rechaza a los desconocidos. Este paso hace que, para empezar, no haya nada que un desconocido pueda alcanzar — el segundo de los dos cerrojos, y el que sobrevive a una futura edición del primero.

    # DNS is reachable from the tunnel interface only
    sudo ufw allow in on wg0 to any port 53 proto udp
    sudo ufw allow in on wg0 to any port 53 proto tcp
    sudo ufw status verbose

    Después verifícalo de la única forma que cuenta, desde una máquina distinta. Probarlo desde el propio servidor no demuestra absolutamente nada — el loopback está permitido a propósito. Ejecuta esto desde tu portátil con el túnel caído, o desde cualquier otro host que tengas.

    # must time out. an answer here means you are running an open resolver.
    dig @SERVER_PUBLIC_IP example.com +time=3 +tries=1
    
    # same question over IPv6, which is the half people forget
    dig -6 @SERVER_IPV6 example.com +time=3 +tries=1

    Si cualquiera de las dos devuelve una respuesta, detente y arréglalo ahora, no después del informe de abuso. Las causas habituales son un interface: 0.0.0.0 que quedó en un archivo de configuración empaquetado, una regla de firewall que permite el 53 globalmente desde un experimento anterior, o Docker publicando el puerto de un contenedor que se salta ufw por completo.

  6. 06

    Apunta tus dispositivos hacia él

    En el lado del cliente, este es un cambio de una sola línea. En la configuración del cliente WireGuard, la línea DNS pasa a ser la dirección del túnel de tu servidor en lugar de un resolver público — esta es la edición que jubila DNS = 9.9.9.9 de la guía de WireGuard.

    [Interface]
    PrivateKey = <paste client.key>
    Address = 10.66.0.2/32, fd86:ea04:1115::2/128
    DNS = 10.66.0.1
    
    [Peer]
    PublicKey = <paste server.pub>
    Endpoint = YOUR_SERVER_IP:51820
    AllowedIPs = 0.0.0.0/0, ::/0
    PersistentKeepalive = 25

    Levanta el túnel y confirma dos cosas por separado desde el cliente: que las respuestas llegan desde tu resolver, y que la recursión de verdad sale al exterior desde tu VPS y no desde otro sitio. La segunda comprobación es la útil — whoami.akamai.net devuelve la dirección de cualquier resolver que haya preguntado, así que debería imprimir la IP pública de tu servidor y nada más.

    # answers should come from the tunnel address
    dig example.com | grep -E 'SERVER:'
    
    # should print your VPS public IP — this is the leak test
    dig +short whoami.akamai.net
    
    # and the ad flag should still be there, end to end
    dig example.com +dnssec | grep -E '^;; flags'
  7. 07

    Añade DNS sobre TLS solo para un dispositivo que no pueda mantener el túnel

    Sáltate este paso a menos que tengas un dispositivo concreto — normalmente un teléfono Android, a través de su ajuste de DNS privado a nivel de sistema — que quieras cubrir sin un túnel permanente. Requiere un hostname y un certificado, y ese hostname se convierte en un registro público permanente en los registros de Certificate Transparency, así que elige uno que no lleve a nada cerca de tus otras identidades.

    sudo apt install -y certbot
    sudo ufw allow 80/tcp comment 'certbot, temporarily'
    sudo certbot certonly --standalone -d dns.example.net
    sudo ufw delete allow 80/tcp
    
    # unbound must be able to read the key
    sudo usermod -a -G ssl-cert unbound 2>/dev/null || true
    sudo chgrp -R ssl-cert /etc/letsencrypt/live /etc/letsencrypt/archive
    sudo chmod -R g+rX /etc/letsencrypt/live /etc/letsencrypt/archive

    Añade el listener TLS como su propio archivo drop-in, para poder borrarlo de una sola vez si cambias de opinión.

    # NOTE: drop-in files are read in alphabetical order and the last
    # access-control line for a given prefix wins — so this file must
    # sort AFTER private-resolver.conf, or its refuse rule overrides
    # the allow below and every DoT client gets REFUSED.
    sudo tee /etc/unbound/unbound.conf.d/zz-dot.conf > /dev/null <<'EOF'
    server:
        interface: 0.0.0.0@853
        interface: ::0@853
        tls-service-key: "/etc/letsencrypt/live/dns.example.net/privkey.pem"
        tls-service-pem: "/etc/letsencrypt/live/dns.example.net/fullchain.pem"
        # roaming clients have no fixed address, so this endpoint must accept any.
        # safe only because port 53 stays bound to loopback + wg0 and blocked at
        # the firewall — TLS over TCP cannot be spoofed, so it cannot be reflected.
        access-control: 0.0.0.0/0 allow
        access-control: ::/0 allow
    EOF
    sudo ufw allow 853/tcp
    sudo unbound-checkconf && sudo systemctl restart unbound

    Pruébalo desde fuera del túnel antes de confiar en él, y después pon el hostname en el campo de DNS privado del teléfono. La renovación es la parte que se rompe en silencio tres meses más tarde — certbot sustituye el certificado, pero Unbound mantiene el antiguo en memoria, así que añade un deploy hook que lo recargue.

    kdig -d @dns.example.net +tls-ca +tls-host=dns.example.net example.com
    
    echo 'systemctl reload unbound' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/unbound.sh
    sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/unbound.sh
SP·10 — PREGUNTAS FRECUENTES

Respuestas rápidas

¿Mi propio resolver es más rápido o más lento que 1.1.1.1?

Las dos cosas, en momentos distintos. Una consulta en frío de un dominio que nadie en tu red ha visitado es más lenta, porque la recursión completa implica preguntar a la raíz, después al TLD, después al servidor autoritativo, mientras que un resolver público suele responder desde una caché calentada por millones de otras personas. Una consulta en caliente es más rápida de lo que puede serlo cualquier resolver público, porque la caché está al final de tu propio túnel y no al otro lado de internet. En el uso diario domina el caso en caliente: los hogares repiten la visita a unos pocos cientos de dominios, prefetch renueva los populares antes de que caduquen, y la tasa de aciertos sube en un día. Si te importa más que la primera visita a un sitio desconocido se note una fracción más lenta que el log, este es el cambio equivocado para ti, y deberías reenviar en su lugar.

¿Esto impide que mi ISP vea qué sitios visito?

No por sí solo. Impide que tu ISP lea tus consultas solo si esas consultas viajan dentro de un túnel — de lo contrario, tus preguntas al VPS siguen siendo UDP en texto plano a través de la red de tu ISP, y has cambiado el destino sin ocultar nada. Incluso con el túnel, tu ISP sigue viendo una sesión cifrada hacia una dirección, y si navegas fuera del túnel sigue viendo las IP de destino y, en ausencia de Encrypted Client Hello, el nombre del servidor en el handshake de TLS. Trata a un resolver privado como el componente que cierra el canal de los nombres, y a el túnel como el componente que cierra el del transporte. Ninguno sustituye al otro.

¿Debería simplemente reenviar a Quad9 o Cloudflare por DoT en su lugar?

Es una elección legítima, y para mucha gente es la correcta. Reenviar por DoT es más simple, más rápido de configurar, te da el anonimato de una multitud muy grande, y derrota al observador que la mayoría de la gente realmente enfrenta — la red local y el ISP. Lo que no hace es eliminar la agregación: una sola organización sigue recibiendo tu flujo de consultas completo, ahora ordenadamente etiquetado con una única dirección de origen. Elige reenviar cuando tu modelo de amenaza es el Wi-Fi de la cafetería y tu ISP; elige recursión cuando lo que te molesta es el agregado en sí, o cuando prefieres no tener que decidir a la política de retención de qué empresa darle crédito.

¿Puede mi proveedor de hosting leer mis consultas DNS?

Sí, y merece la pena tenerlo claro. Las consultas recursivas a la raíz, al TLD y a los servidores autoritativos salen del VPS por el puerto UDP 53 sin cifrar — no hay DoT hacia los servidores raíz. Cualquiera con visibilidad sobre el enlace de subida del servidor puede leerlas. La minimización de QNAME hace que cada conversación individual revele solo un fragmento, y se mezclan con todo lo demás que hace la máquina, pero no están ocultas. Lo que has hecho es trasladar al observador de un ISP de consumo en tu propio país, que está obligado a retener datos y tiene un interés comercial en ellos, a una red de hosting que tú elegiste. Eso lo convierte en una cuestión de qué jurisdicción y qué proveedor, no en una pregunta que la configuración responda.

¿Necesito un nombre de dominio para esto?

No, si tus dispositivos llegan al resolver a través del túnel, que es la principal razón práctica para preferir esa vía: ningún hostname, ningún certificado, ningún registro público de que el servicio existe. Solo necesitas un dominio para DNS sobre TLS, porque los clientes verifican el certificado contra un nombre. Ten en cuenta que obtener ese certificado publica el hostname en los registros de Certificate Transparency de forma permanente, y el DNS pasivo lo atará a la dirección del servidor poco después — así que no uses un subdominio de un dominio que ya señale hacia ti. Registrar un dominio de forma anónima cubre lo que todavía se filtra cuando lo intentas.

¿Esto bloqueará anuncios y rastreadores?

No por defecto — un Unbound de fábrica resuelve nombres, no los filtra. Puedes añadir blocklists o zonas locales por encima, y en dispositivos móviles es la única capa que llega al tráfico de las apps. Mantén las expectativas honestas: las aplicaciones con la IP del resolver fijada en el código, o con un cliente DoH incorporado, nunca le preguntan nada a tu resolver, los navegadores cada vez más resuelven por su propio transporte cifrado, y una gran blocklist de terceros terminará rompiendo algo el día en que te hayas olvidado de que está instalada. Elimina ruido de rastreo de bajo esfuerzo. No es un control de seguridad, y cualquier cosa hostil está diseñada para rodearlo.

Ponlo en práctica

VPS en línea en 15 min, dedicado entregado en 2–12 h. Recarga desde $30.00 en cripto — sin identidad asociada.

Desplegar un VPS