DNS recursivo y privado con Pi-hole y Unbound en Debian 13

En mi entrada anterior sobre DNS over HTTPS con dnscrypt-proxy conseguíamos cifrar las consultas DNS, pero seguíamos confiando en un servidor externo (Cloudflare, Quad9, etc.). ¿Y si te dijera que puedes eliminar esa confianza por completo y convertir tu Raspberry Pi en tu propio servidor DNS recursivo?

Con Unbound tu Raspberry Pi resuelve las consultas DNS directamente desde los servidores raíz de Internet, sin depender de ningún tercero. Esto:

  • Elimina intermediarios: Nadie sabe qué dominios consultas.
  • Mayor seguridad: Al ser un resolver local, es prácticamente inmune a ataques de envenenamiento de caché masivos.
  • DNSSEC incluido: Valida que las respuestas no han sido manipuladas.
  • Sin límites ni ratelimit: Al no depender de un servidor público, no hay restricciones de volumen de consultas.

Todo esto, en una configuración que además es muy ligera para tu Raspberry Pi.

⚠️ Atención con Debian 13 (Trixie): La guía oficial de Pi-hole para Unbound tiene un pequeño problema en Debian 13 relacionado con el buffer de recepción de sockets. En esta entrada incluyo la solución definitiva para que no tengas que pelearte con errores.

Requisitos previos

  • Una Raspberry Pi (o cualquier equipo) con Debian 13 (Trixie).
  • Pi-hole instalado y funcionando (versión 6.x o superior).
  • Acceso root o usuario con permisos sudo.

Paso 1: Instalar Unbound

Unbound está disponible en los repositorios oficiales de Debian. La instalación es trivial:

sudo apt update
sudo apt install unbound

El paquete crea automáticamente el usuario unbound y configura el servicio de systemd. No necesitas hacer nada más.

Paso 2: Crear el archivo de configuración para Pi-hole

La configuración de Unbound se compone de varios archivos en /etc/unbound/unbound.conf.d/.

Vamos a crear el archivo específico para Pi-hole:

sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf

Pega el siguiente contenido:

server:
    # Puerto en el que escuchará Unbound (5335 para no interferir con Pi-hole)
    port: 5335
    # Solo acepta peticiones desde localhost
    interface: 127.0.0.1
    # No escuchar en IPv6 (a menos que lo necesites)
    do-ip6: no
    # Resolución recursiva
    do-not-query-localhost: no
    # Activar DNSSEC
    val-log-level: 2
    # Tamaño del buffer de recepción (ver más abajo)
    so-rcvbuf: 1m
    # Cache negativo (opcional, mejora rendimiento)
    cache-min-ttl: 3600
    cache-max-ttl: 86400
    # Prevenir ataques de amplificación
    hide-identity: yes
    hide-version: yes
    # Respuesta mínima
    minimal-responses: yes
    # Usuarios y grupos
    username: "unbound"

Guarda el archivo (Ctrl+O) y sal (Ctrl+X).

⚠️ Paso 3: La solución para Debian 13 (el «problema del buffer»)

Este paso es fundamental en Debian 13. La configuración anterior incluye so-rcvbuf: 1m, que pide un buffer de recepción de 1 MB. En Debian 13, el antiguo método de modificar /etc/sysctl.conf ya no funciona porque systemd-sysctl ya no lo lee.

Si intentas aplicar la solución tradicional con sudo sysctl -p /etc/sysctl.conf, verás que no tiene efecto.

La solución correcta en Debian 13 es crear un archivo en /etc/sysctl.d/:

sudo nano /etc/sysctl.d/99-unbound.conf

Añade esta línea:

net.core.rmem_max=1048576

Guarda y aplica los cambios:

sudo sysctl -p /etc/sysctl.d/99-unbound.conf

Verifica que se ha aplicado:

sudo sysctl net.core.rmem_max

Deberías ver net.core.rmem_max = 1048576. Con esto, Unbound ya podrá usar el buffer de 1 MB sin mostrar warnings.

Paso 4: Verificar que la configuración de Unbound es correcta

Antes de arrancar el servicio, comprueba que la sintaxis del archivo de configuración es correcta:

sudo unbound-checkconf

Si no devuelve nada, significa que todo está bien.

Paso 5: Reiniciar y habilitar Unbound

sudo systemctl restart unbound
sudo systemctl enable unbound

Comprueba que el servicio está activo:

sudo systemctl status unbound

Deberías ver active (running) y ningún warning sobre so-rcvbuf.

Paso 6: Configurar Pi-hole para que use Unbound

Ahora debemos indicar a Pi-hole que use nuestro nuevo resolver local.

Opción A: Desde la interfaz web de Pi-hole (recomendada)

  1. Accede a la interfaz web de Pi-hole (http://<IP-de-tu-RPi>/admin).
  2. Ve a SettingsDNS.
  3. En la sección Upstream DNS Servers, desmarca TODOS los servidores que estén marcados (Cloudflare, Google, etc.).
  4. En el campo Custom 1 (IPv4), introduce 127.0.0.1#5335.
  5. Haz clic en Save.

Opción B: Desde la línea de comandos

sudo pihole-FTL --config dns.upstreams '["127.0.0.1#5335"]'

Opción C: Editar directamente el archivo de configuración

sudo nano /etc/pihole/pihole-FTL.conf

Añade la línea:

UPSTREAM_DNS=127.0.0.1#5335

Reinicia FTLDNS:

sudo systemctl restart pihole-FTL

Paso 7: Probar que todo funciona

Prueba 1: Consulta directa a Unbound

dig @127.0.0.1 -p 5335 google.com

Deberías ver una respuesta con status: NOERROR y la dirección IP de google.com.

Prueba 2: Consulta a través de Pi-hole

dig google.com

Como Pi-hole es ahora el DNS por defecto (en 127.0.0.1:53), esta consulta debería pasar por Pi-hole → Unbound → servidores raíz y devolverte la respuesta.

Prueba 3: Comprobar que no hay errores en los logs

sudo journalctl -u unbound -f

No deberías ver warnings sobre so-rcvbuf. Si ves algún error, revisa que el paso 3 se ha aplicado correctamente.

Paso 8: (Opcional) Configurar DNS over TLS (DoT) en Unbound

Si además de ser recursivo quieres que Unbound reenvíe las consultas cifradas a un servidor externo (por ejemplo, Cloudflare o Quad9) en lugar de resolverlas recursivamente, puedes configurarlo como «forwarder» con DNS over TLS.

Crea un archivo para la configuración DoT:

sudo nano /etc/unbound/unbound.conf.d/dot.conf

Añade:

forward-zone:
    name: "."
    forward-tls-upstream: yes
    forward-addr: 1.1.1.1@853#cloudflare-dns.com
    forward-addr: 1.0.0.1@853#cloudflare-dns.com
    # Alternativa: Quad9
    # forward-addr: 9.9.9.9@853#dns.quad9.net

Nota: Si usas esta configuración, Unbound ya no será recursivo, sino un forwarder cifrado. Es una alternativa válida si prefieres delegar la resolución a un tercero pero con tráfico cifrado.

Resumen de lo que has conseguido

CaracterísticaCon Unbound
Privacidad✅ Tus consultas no salen de tu red (modo recursivo).
Seguridad✅ DNSSEC validado localmente.
Dependencia de terceros❌ Ninguna (modo recursivo).
CifradoOpcional (DoT si usas modo forwarder).
Rendimiento✅ Caché local, respuestas rápidas en consultas repetidas.
Mantenimiento✅ Se actualiza con apt upgrade.

Solución de problemas comunes

«so-rcvbuf 1048576 was not granted»

Has omitido el Paso 3. Vuelve a él y asegúrate de que el archivo /etc/sysctl.d/99-unbound.conf existe y contiene net.core.rmem_max=1048576. Luego ejecuta sudo sysctl -p /etc/sysctl.d/99-unbound.conf y reinicia Unbound.

«SERVFAIL» o «DNSSEC bogus»

Puede ser que tu conexión a Internet tenga problemas o que algún servidor raíz esté dando respuestas incorrectas. Prueba a desactivar temporalmente DNSSEC en la configuración de Unbound (añadiendo val-permissive-mode: yes en pi-hole.conf) para descartar problemas.

Unbound no arranca

Comprueba la sintaxis: sudo unbound-checkconf. Si hay errores, revisa que no haya typográficos en el archivo de configuración.

Conclusión

Con estos pasos has convertido tu Raspberry Pi en un servidor DNS recursivo, privado y seguro. Ya no dependes de ningún proveedor externo para resolver tus consultas DNS, y además has solucionado el problema específico de Debian 13 que afecta a la configuración del buffer de recepción.

Esta configuración es la que recomienda la propia documentación oficial de Pi-hole, y es una de las formas más robustas y privadas de gestionar el DNS en tu red doméstica.

¿Te ha sido útil? Si tienes alguna duda o sugerencia, no dudes en dejar un comentario.

Saber más

Con la configuración de los puntos del 1 al 7, ¿voy a obtener los 4 check de Clouflare?

Es muy normal pensar que, al configurar un DNS privado y seguro, el test de Cloudflare debería dar un «check» en todo.

La respuesta corta es: no, con los pasos 1 al 7 no obtendrás los 4 checks. Y ese es un punto muy importante y, a menudo, malinterpretado.

Vamos a desglosar qué comprueba realmente ese test y por qué tu configuración de Unbound (incluso con el paso 8) no lo cambiará todo.

¿Qué mide el «Browsing Experience Security Check» de Cloudflare?

El test revisa cuatro aspectos diferentes:

  1. Secure DNS (DNS Seguro): Comprueba si tu navegador está configurado para usar DNS sobre HTTPS (DoH) o DNS sobre TLS (DoT) directamente.
  2. DNSSEC: Verifica si el resolver DNS que estás usando valida las firmas DNSSEC para asegurar que las respuestas no han sido manipuladas.
  3. TLS 1.3: Comprueba la versión del protocolo TLS que tu navegador usa para conectarse a la web de Cloudflare.
  4. Encrypted SNI (ECH): Evalúa si tu navegador soporta ECH, una tecnología que cifra el nombre del sitio web en la conexión TLS.

Analizando tu configuración de Unbound (Pasos 1-7)

  • Secure DNS: FALLARÁ. Este check no mide cómo viajan tus consultas DNS desde tu Raspberry Pi hacia Internet. Mide cómo viajan desde tu navegador hasta el resolver DNS.
    En tu configuración, tu navegador (o sistema operativo) envía las consultas DNS en texto plano a tu Pi-hole (que está en 127.0.0.1 o en tu IP local). Aunque Pi-hole las pase a Unbound y Unbound haga una resolución recursiva y segura, el primer tramo (navegador → Pi-hole) no está cifrado. Por lo tanto, para el test de Cloudflare, no estás usando «Secure DNS».
  • DNSSEC: PASARÁ. Al ser un resolver recursivo, Unbound valida las firmas DNSSEC por sí mismo. El test detectará que tu consulta DNS ha sido validada con DNSSEC.
  • TLS 1.3: PASARÁ. Esto es independiente de tu DNS. Simplemente comprueba que tu navegador es moderno y soporta TLS 1.3, algo que hoy en día todos hacen.
  • Encrypted SNI (ECH): FALLARÁ. Al igual que TLS 1.3, esto es una característica de tu navegador y del sitio web, no de tu DNS. Para que este check pase, tu navegador debe tener ECH activado. No tiene nada que ver con Unbound.

¿Y el Paso 8 (DNS over TLS)?

El paso 8 añade una capa de cifrado en el tramo Unbound → Servidor DNS upstream (ej. Cloudflare). Esto es excelente para proteger tu privacidad de tu ISP, ya que tus consultas DNS viajarán cifradas desde tu Raspberry Pi hasta Cloudflare.

Sin embargo, el test de Cloudflare seguirá mostrando «Secure DNS» como fallido, porque el cifrado que has añadido no es el que el test está midiendo. El test sigue viendo que tu navegador se comunica en texto plano con el DNS local.

Conclusión: ¿Para qué sirve entonces esta configuración?

Es fundamental entender que configurar un DNS recursivo o cifrado en tu red local no es para pasar un test de una web. Es para proteger tu privacidad real:

  • Con Unbound (Pasos 1-7): Tu Raspberry Pi resuelve las consultas por sí misma. Tu ISP solo ve que preguntas por los servidores raíz, pero no ve qué dominios específicos estás consultando. Es la máxima privacidad.
  • Con Unbound + DoT (Paso 8): Tu ISP ve que te conectas a Cloudflare (o el que elijas) para resolver DNS, pero no puede ver el contenido de tus consultas porque van cifradas.

Ambas configuraciones son mucho más privadas que usar el DNS de tu ISP por defecto.

En resumen

Check de Cloudflare¿Pasará con tu configuración?¿Por qué?
Secure DNSNoEl test mide si tu navegador usa DoH/DoT, no tu red interna.
DNSSECUnbound valida DNSSEC.
TLS 1.3Depende de tu navegador, no de tu DNS.
Encrypted SNINoDepende de que tu navegador soporte ECH, no de tu DNS.

No te preocupes por no tener los 4 checks. Tu configuración con Unbound es excelente y mucho más privada que la mayoría. El test de Cloudflare está diseñado para comprobar características del navegador y su conexión directa a Internet, no para evaluar la seguridad de tu red local.

Si quieres que el check de «Secure DNS» sea verde, tendrías que configurar DoH/DoT directamente en tu navegador o sistema operativo, pero eso haría que Pi-hole quedara fuera de juego, perdiendo el bloqueo de anuncios. Es una decisión de compromiso entre privacidad y funcionalidad.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio