En el mundo actual, donde la privacidad en línea es cada vez más valiosa, confiar en servidores DNS de terceros puede ser un riesgo. Por eso, en esta guía te mostraré cómo convertir tu Pi-hole en una solución DNS completa y autónoma, instalando y configurando Unbound como servidor DNS recursivo local.
El problema: ¿en quién confiar?
Pi-hole incluye su propio servidor DNS (FTLDNS) que, después de aplicar las listas de bloqueo, reenvía las consultas de los clientes a los servidores DNS upstream configurados.
Sin embargo, esto plantea un problema de privacidad: cuando confías tus consultas DNS a un proveedor externo, estás delegando información sobre qué sitios visitas. Y aunque muchos proveedores prometen ser «privados y gratuitos», ¿cómo puedes saber realmente que cumplen su palabra?.
Además, los servidores DNS de grandes proveedores son objetivos muy atractivos para los atacantes. Si logran envenenar la caché de uno de ellos, millones de usuarios podrían ser redirigidos a sitios de phishing sin saberlo.
Cuando ejecutas tu propio servidor DNS recursivo (pequeño y local), la probabilidad de verse afectado por este tipo de ataques se reduce drásticamente.
¿Qué es un servidor DNS recursivo?
La primera distinción importante es entre un servidor autoritativo y uno recursivo:
- Un servidor autoritativo conoce la respuesta correcta para un dominio porque es el que lo gestiona (por ejemplo, el servidor autoritativo de
pi-hole.netsabe cuál es su IP real). - Un servidor recursivo, en cambio, resuelve cualquier consulta que recibe recorriendo la jerarquía del sistema DNS: pregunta a los servidores raíz, luego a los de nivel superior (TLD), y finalmente a los autoritativos, hasta obtener la respuesta.
¿Qué ofrece esta guía?
En pocos pasos, configuraremos tu propio servidor DNS recursivo en el mismo dispositivo donde ya tienes Pi-hole. No necesitas hardware adicional. La guía asume un sistema basado en Debian/Ubuntu relativamente reciente y utiliza los paquetes oficiales para simplificar el proceso.
Antes de empezar: prueba de acceso a los servidores raíz
Es fundamental verificar que tu ISP o router no esté interceptando o redirigiendo el tráfico DNS en el puerto 53. Si lo hace, Unbound no podrá comunicarse directamente con los servidores raíz y fallará de formas difíciles de diagnosticar.
Ejecuta estas pruebas en el sistema donde instalarás Unbound:
1. Prueba de reachabilidad UDP
Consulta directamente el servidor raíz a.root-servers.net (198.41.0.4) sin solicitar recursión:
dig @198.41.0.4 . NS +norec +time=3
Revisa la línea flags: en la respuesta. Si estás hablando directamente con un servidor raíz, verás aa (Authoritative Answer) y no verás ra (Recursion Available), ya que los servidores raíz no ofrecen recursión.
Ejemplo de respuesta correcta:
;; flags: qr aa; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 27
Si tu tráfico está siendo interceptado, aparecerá ra y probablemente faltará aa.
2. Prueba de reachabilidad TCP
Unbound también depende de TCP/53 para respuestas DNSSEC grandes y para reintentos:
dig @198.41.0.4 . NS +norec +tcp +time=3
Si esta prueba falla (timeout) pero la anterior funcionó, puede que tu red esté bloqueando tráfico DNS sobre TCP, lo que causará fallos crípticos en Unbound.
3. Confirmación de identidad vía CHAOS
Los servidores raíz responden a consultas de clase CHAOS con identificadores únicos. La mayoría de los proxies de ISP no manejan este tipo de consultas:
dig @198.41.0.4 version.bind CH TXT +time=3
Si te conectas directamente al servidor raíz, la respuesta será un registro TXT con «ATLAS»:
version.bind. 0 CH TXT "ATLAS"
Si el tráfico está siendo interceptado, obtendrás otra cadena, timeout o SERVFAIL.
Si alguna de estas pruebas falla, no es recomendable continuar con la instalación hasta investigar y resolver la causa (redirección del ISP, bloqueo de TCP DNS, filtros de seguridad en el router, etc.).
Configurando Pi-hole como servidor DNS recursivo
Vamos a utilizar Unbound, un servidor DNS recursivo seguro y de código abierto desarrollado por NLnet Labs, VeriSign, Nominet y Kirei.
1. Instalación de Unbound
sudo apt install unbound
Si instalas desde el gestor de paquetes, el archivo root.hints se instalará automáticamente con la dependencia dns-root-data y se actualizará con el gestor de paquetes.
Opcional: Si no instalas desde un gestor de paquetes, puedes descargar manualmente la lista de servidores raíz (actualízala cada seis meses aproximadamente):
wget https://www.internic.net/domain/named.root -qO- | sudo tee /var/lib/unbound/root.hints
Si haces esto, tendrás que descomentar la línea root-hints: en el archivo de configuración.
2. Configuración de Unbound
Crea o edita el archivo /etc/unbound/unbound.conf.d/pi-hole.conf con el siguiente contenido:
server:
# Si no se especifica logfile, se usa syslog
# logfile: "/var/log/unbound/unbound.log"
verbosity: 0
interface: 127.0.0.1
port: 5335
do-ip4: yes
do-udp: yes
do-tcp: yes
# Puedes cambiarlo a no si no tienes conectividad IPv6
do-ip6: yes
# Déjalo en no a menos que tengas IPv6 nativo
prefer-ip6: no
# Usa esto solo si descargaste manualmente la lista de servidores raíz
# root-hints: "/var/lib/unbound/root.hints"
# Confía en la información de glue solo si está dentro de la autoridad del servidor
harden-glue: yes
# Requiere datos DNSSEC para zonas con trust-anchors; si faltan, la zona se marca como BOGUS
harden-dnssec-stripped: yes
# No uses randomización de mayúsculas (puede causar problemas con DNSSEC)
use-caps-for-id: no
# Reduce el tamaño del buffer de reensamblaje EDNS (recomendado por DNS Flag Day 2020)
edns-buffer-size: 1232
# Precarga entradas de caché próximas a expirar (solo para dominios consultados frecuentemente)
prefetch: yes
# Un hilo suele ser suficiente; aumenta solo en máquinas potentes
num-threads: 1
# Asegura que el buffer del kernel sea lo suficientemente grande para no perder mensajes
so-rcvbuf: 1m
# Protege la privacidad de rangos IP privados
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: fd00::/8
private-address: fe80::/10
# Evita consultas inversas a rangos IP no públicos (RFC6303)
private-address: 192.0.2.0/24
private-address: 198.51.100.0/24
private-address: 203.0.113.0/24
private-address: 255.255.255.255/32
private-address: 2001:db8::/32
Nota: En algunas distribuciones basadas en Red Hat (incluyendo CentOS hasta v10), la ruta del archivo puede ser /etc/unbound/conf.d/pi-hole.conf.
3. Iniciar y probar Unbound
Reinicia el servidor y comprueba que funciona:
sudo service unbound restart
dig pi-hole.net @127.0.0.1 -p 5335
La primera consulta puede ser algo lenta, pero las siguientes (incluso para otros dominios bajo el mismo TLD) deberían ser bastante rápidas.
4. Prueba de validación DNSSEC
Para verificar que DNSSEC funciona correctamente:
dig fail01.dnssec.works @127.0.0.1 -p 5335
dig +ad dnssec.works @127.0.0.1 -p 5335
- El primer comando debería devolver
SERVFAILy sin dirección IP. - El segundo debería devolver
NOERROR, una dirección IP y la banderaad(Authentic Data) en la secciónflags:, indicando que la respuesta ha sido autenticada y validada mediante DNSSEC.
5. Configurar Pi-hole
Ve a la interfaz web de Pi-hole: Settings > DNS.
En la sección Custom DNS servers, especifica:
127.0.0.1#5335
Asegúrate de desmarcar todos los demás servidores upstream.
No olvides hacer clic en Save & Apply.
6. Deshabilitar entrada de resolvconf (requerido para Debian Bullseye+)
En Debian Bullseye y versiones posteriores, se instala automáticamente el paquete openresolv con una configuración que puede causar comportamientos inesperados en Pi-hole y Unbound.
El servicio unbound-resolvconf.service escribe nameserver 127.0.0.1 (sin el puerto 5335) en /etc/resolv.conf, lo que afecta a los servicios locales.
Paso 1: Deshabilitar el servicio
Comprueba si está activo:
systemctl is-active unbound-resolvconf.service
Deshabilítalo:
sudo systemctl disable --now unbound-resolvconf.service
Paso 2: Deshabilitar el archivo de configuración
sudo sed -Ei 's/^unbound_conf=/#unbound_conf=/' /etc/resolvconf.conf
sudo rm /etc/unbound/unbound.conf.d/resolvconf_resolvers.conf
Reinicia Unbound:
sudo service unbound restart
7. (Opcional) Añadir logs a Unbound
Advertencia: No se recomienda aumentar la verbosidad para uso diario, ya que Unbound genera muchos logs. Puede ser útil para depuración.
Niveles de verbosidad:
- 0: Solo errores
- 1: Información operativa
- 2: Información operativa detallada
- 3: Información a nivel de consulta
- 4: Información a nivel de algoritmo
- 5: Registro de identificación de cliente para fallos de caché
Edita /etc/unbound/unbound.conf.d/pi-hole.conf y añade en la sección server:
server:
logfile: "/var/log/unbound/unbound.log"
log-time-ascii: yes
verbosity: 1
Crea el directorio y archivo de log, y establece permisos:
sudo mkdir -p /var/log/unbound
sudo touch /var/log/unbound/unbound.log
sudo chown unbound /var/log/unbound/unbound.log
En sistemas modernos Debian/Ubuntu, añade una excepción en AppArmor:
Crea o edita /etc/apparmor.d/local/usr.sbin.unbound y añade:
/var/log/unbound/unbound.log rw,
Recarga AppArmor:
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.unbound
sudo service apparmor restart
Reinicia Unbound:
sudo service unbound restart
8. Verificar que Pi-hole está usando Unbound
Realiza una consulta DNS:
dig en.wikipedia.org @127.0.0.1
Luego revisa el log de Pi-hole:
sudo tail /var/log/pihole/pihole.log
Deberías ver líneas como:
Nov 24 11:57:47 dnsmasq[973]: query[A] en.wikipedia.org from 127.0.0.1
Nov 24 11:57:47 dnsmasq[973]: forwarded en.wikipedia.org to 127.0.0.1#5335
Nov 24 11:57:47 dnsmasq[973]: reply en.wikipedia.org is <IP>
Si ves que las respuestas vienen de 127.0.0.1#5335, ¡enhorabuena! Pi-hole está usando Unbound como upstream.
Para otros clientes de la red
La configuración de la Raspberry solo afecta a la propia Raspberry. Para que el resto de dispositivos (móviles, portátiles, etc.) usen tu Pi-hole, configura tu router DHCP para que entregue 192.168.1.18 como único servidor DNS (y no entregue ningún secundario). Así, toda la red estará protegida.
Desinstalar Unbound
Si en algún momento quieres revertir los cambios:
sudo apt remove unbound
Recuerda volver a configurar otro servidor DNS upstream en Pi-hole.
Conclusión
Has configurado exitosamente tu propio servidor DNS recursivo con Pi-hole y Unbound. Ahora:
- Tu privacidad mejora: ninguna entidad externa registra todas tus consultas DNS.
- Tu seguridad aumenta: al ser un servidor pequeño y local, es un objetivo mucho menos atractivo para ataques de envenenamiento de caché.
- Tienes control total: decides cómo se resuelven tus consultas DNS, sin depender de terceros.
Comprobaciones, errores y soluciones
🛑 Advertencia so-rcvbuf en Unbound
La configuración establece so-rcvbuf: 1m para manejar altas tasas de consultas. Puedes ver esta advertencia:
so-rcvbuf 1048576 was not granted. Got 425984.
¿Dónde se puede ver esta advertencia? En dos sitios principales:
1. En los logs de Unbound
Esta es la forma más común de encontrar la advertencia. Unbound la escribe en sus propios registros cuando no puede establecer el tamaño de búfer que ha solicitado en su configuración (so-rcvbuf: 1m).
Puedes comprobar los logs de Unbound con el siguiente comando:
sudo journalctl -u unbound | grep "so-rcvbuf"
Si la advertencia está presente, verás un mensaje similar a este:
unbound[110586:0] warning: so-rcvbuf 1048576 was not granted. Got 425984.[reference:0]
Este mensaje indica que Unbound pidió un búfer de recepción de 1048576 bytes (1 MB), pero el sistema solo le concedió 425984 bytes.
2. Al iniciar Unbound manualmente (en primer plano)
Si ejecutas Unbound en primer plano (por ejemplo, para depuración), la advertencia aparecerá directamente en la terminal:
sudo unbound -d
¿Qué significa esta advertencia?
- No es un error crítico: Unbound seguirá funcionando, pero podría tener un rendimiento ligeramente inferior en momentos de mucho tráfico.
- Es un problema de límites del sistema: Unbound está pidiendo un búfer de red más grande para manejar mejor picos de tráfico, pero el límite del kernel (
net.core.rmem_max) es más bajo.
Para solucionarlo, tendrías que aumentar el límite del kernel de forma permanente, por ejemplo, creando un archivo en /etc/sysctl.d/ (especialmente importante en sistemas más nuevos como Debian 13, donde /etc/sysctl.conf ya no se usa por defecto).
¿Como se soluciona?
- Comprueba el límite actual:
sudo sysctl net.core.rmem_max
- Aumenta temporalmente:
sudo sysctl -w net.core.rmem_max=1048576
- Hazlo permanente. Edita
sudo nano /etc/sysctl.d/99-unbound.conf
y añade:
net.core.rmem_max=1048576
- Aplica los cambios:
- En sistemas actualizados (ej. Debian 13):
sudo systemctl restart systemd-sysctl
- Reinicia Unbound:
sudo service unbound restart
🛑 Error en la prueba de DNSSEC
Durante la configuración de Pi-hole + Unbound como servidor DNS recursivo con validación DNSSEC, nos encontramos con un problema aparente, al realizar consultas con la bandera +dnssec, el sistema mostraba timeouts y terminaba resolviendo a través del router (fallback) en lugar de nuestro propio Pi-hole.
Síntoma
Desde el cliente, al ejecutar:
dig +dnssec sigfail.verteiltesysteme.net
obteníamos:
;; communications error to 192.168.1.18#53: timed out
...
;; SERVER: 192.168.1.1#53 (el router)
La consulta funcionaba sin +dnssec (respuesta inmediata desde Pi-hole), pero al pedir validación DNSSEC, el cliente se quedaba sin respuesta de Pi-hole y recurría al router, que sí devolvía SERVFAIL (porque también valida DNSSEC). Esto enmascaraba el problema real: Pi-hole no estaba respondiendo a tiempo.
Causa raíz
El motivo eran tres timeouts encadenados:
- Timeout de reenvío de dnsmasq (Pi-hole):
Por defecto, el servidor DNS interno de Pi-hole (dnsmasq) espera 2 segundos para que el upstream (Unbound) responda. Si Unbound tarda más (por ejemplo, en la primera resolución recursiva con DNSSEC, que puede llevar 400‑700 ms), dnsmasq aborta la conexión y no devuelve nada al cliente. - Timeout por defecto de
dig:
El comandodigtiene un tiempo de espera de 3 segundos. Si en el primer intento no recibe respuesta (por el aborto de dnsmasq), da el mensaje decommunications errory reintenta. En el segundo intento, dnsmasq ya ha recibido la respuesta de Unbound (porque la caché ya está caliente) y la devuelve, pero el daño del mensaje de error ya está hecho. - Presencia del router como DNS secundario en
/etc/resolv.conf:
Al tenernameserver 192.168.1.1como fallback, el sistema operativo, al no obtener respuesta de Pi-hole en el primer intento, acude al router, que responde rápidamente. Esto hacía que pareciera que «funcionaba» (porque se veía elSERVFAILcorrecto), pero en realidad no estábamos usando nuestro propio Unbound para validar DNSSEC, sino el router.
Solución, eliminar el router como DNS secundario
Para asegurar que todas las consultas pasen por nuestro Pi-hole, es buena práctica dejar únicamente la IP de Pi-hole en /etc/resolv.conf (o configurar el DHCP del router para que entregue solo esa IP). Así, si Pi-hole falla, el sistema no tendrá un fallback y el error será evidente, pero en condiciones normales todas las consultas usarán nuestro propio resolver.
De forma gráfica.
Solo tienes que hacer clic derecho sobre el icono de red en la esquina superior derecha de la pantalla (el que parece dos monitores o unas barras de WiFi) y seleccionar «Wireless & Wired Network Settings» o una opción similar. Allí se abrirá una ventana para configurar tu conexión de red.
Para asegurarte de que los cambios son permanentes y no se sobrescriben, lo más fiable es usar el editor gráfico de conexiones de NetworkManager. Para ello, en lugar de la opción anterior, haz clic en «Advanced Options» y luego en «Edit Connections…». Se abrirá la ventana «Network Connections».
Aquí verás una lista de tus conexiones (por ejemplo, «Wired connection 1» para Ethernet o tu red WiFi). Selecciona la que estés usando y haz clic en el botón «Edit» (o «Configurar»). En la nueva ventana, ve a la pestaña «IPv4 Settings» (o «Ajustes IPv4»).
En esta pestaña, cambia el «Method» (Método) de Automatic (DHCP) a «Manual». Ahora se habilitarán los campos para que introduzcas tu configuración:
- Address (Dirección): La IP fija de tu Raspberry Pi (ej.
192.168.1.18). - Netmask (Máscara de red): Normalmente
255.255.255.0. - Gateway (Puerta de enlace): La IP de tu router (ej.
192.168.1.1). - DNS servers (Servidores DNS): Aquí es donde pones
127.0.0.1.
Finalmente, haz clic en «Save» (Guardar) y luego cierra las ventanas. Para que los cambios surtan efecto, puedes reiniciar la interfaz de red o, simplemente, reiniciar la Raspberry Pi.

Luego reiniciamos Pi-hole:
sudo systemctl restart pihole-FTL
Desde la terminal.(usando nmcli)
1. Identifica tu conexión de red
sudo nmcli connection show
Anota el nombre de tu conexión activa (ej. eth0, Wired connection 1).
2. Ignora los DNS entregados por DHCP
sudo nmcli connection modify "eth0" ipv4.ignore-auto-dns yes
3. Asigna 127.0.0.1 como único DNS
sudo nmcli connection modify "eth0" ipv4.dns "127.0.0.1"
4. Aplica los cambios
sudo nmcli connection up "eth0"
5. Verifica que se ha aplicado
cat /etc/resolv.conf
Debe mostrar únicamente:
nameserver 127.0.0.1
Verificación final
Tras aplicar los cambios:
raspberry@terrapi:~ $ dig +dnssec sigfail.verteiltesysteme.net
; <<>> DiG 9.20.23-1~deb13u1-Debian <<>> +dnssec sigfail.verteiltesysteme.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 42460
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;sigfail.verteiltesysteme.net. IN A
;; Query time: 772 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Fri Jun 26 20:10:10 CEST 2026
;; MSG SIZE rcvd: 57
Resultado correcto:
- Sin mensajes de timeout.
SERVER: 192.168.1.18#53(nuestro Pi-hole).status: SERVFAILconEDE: 6 (DNSSEC Bogus).
Y para un dominio válido:
dig +dnssec +time=10 dnssec.works
status: NOERRORflags: qr rd ra ad(banderaad= Authentic Data, validación DNSSEC correcta).
Conclusión
El problema no era un fallo de DNSSEC ni de Unbound, sino un timeout insuficiente en la capa de reenvío de Pi-hole. Al aumentar ese tiempo, el sistema funciona a la perfección: todas las consultas (con o sin DNSSEC) son resueltas por nuestro propio servidor recursivo, sin depender de terceros.
Moraleja: en configuraciones recursivas, especialmente con DNSSEC, es recomendable dar margen de tiempo a los componentes internos para que puedan completar la resolución, que puede ser más lenta en las primeras consultas pero se acelera con la caché.
¡Disfruta de una navegación más privada y segura!