Entrada

Pi-hole & Unbound

Despliegue y configuración de Pi-hole DNS & AdBlocker

Pi-hole & Unbound

Para el post de hoy me gustaría cubrir un tema que había pasado de alto hasta el momento, la instalación y administración de un servidor DNS. Esto es esencial para un homelab y ha sido un actor fundamental -aunque silencioso- de los posts anteriores. Sin un sistema de resolución de nombres, no podríamos contar con nombres de servicios fácilmente recordables, y mucho menos con certificados SSL automatizados.

¿Qué es Pi-hole?

Pi-hole es un servidor DNS que actúa como un sinkhole, interceptando peticiones a dominios conocidos por servir anuncios o malware, y devolviendo respuestas vacías. Esto tiene dos beneficios principales:

  • Mejora la experiencia de navegación bloqueando publicidad a nivel de red.
  • Aumenta la privacidad y la seguridad de los dispositivos conectados.
  • Además, tiene una interfaz web muy cómoda y estadísticas en tiempo real del tráfico DNS en tu red.

Contar con Pi-hole en tu red interna significará que cualquier dispositivo que lo use como nameserver se beneficiará del bloqueo automático de anuncios, además de lo obvio que es poder resolver nombres internos para nuestras aplicaciones.

¿Qué es Unbound?

Unbound es un resolvedor DNS recursivo. En lugar de consultar servidores autoritativos como 8.8.8.8 (Google) o 1.1.1.1 (Cloudflare), Unbound construye las respuestas desde los servidores raíz de internet, lo que da más privacidad, independencia y rendimiento.

Al usar Unbound como upstream de Pi-hole, logramos una solución completa: DNS local, seguro y privado.

Requisitos

  • Una VM o contenedor LXC.
    • Permisos de sudo / usuario root
    • Dirección IP Estática.
    • Sistema operativo soportado oficialmente.
    • Puertos 53/udp, 80/tcp, 443/tcp expuestos.
    • Salida hacia internet.

Hands-On

Entorno

Para acelerar el proceso estaré instalando Pi-hole en un contenedor LXC creado en Proxmox utilizando terraform. Como yo ya cuento con un servidor DNS con Pi-hole de antemano, crearé uno nuevo llamado pihole-demo.

Para futuros post compartiré el proceso y código para desplegar VM y contenedores LXC en Proxmox utilizando terraform.

  • OS: Debian 12 bookworm
  • Dirección IP: 192.168.1.155
  • CPU: 1vCPU
  • Memoria: 512MB
  • Disco: 4GB

Cada quién puede asignar recursos como estime conveniente pero he descubierto que con esto es más que suficiente para Pi-hole.

Instalación Pi-hole

Una vez dentro como usuario root, iniciaremos la instalación con el siguiente comando. Pero antes, instalaré curl ya que mi contenedor no lo trae.

1
apt update && apt install -y curl

One-Step Automated Install

1
curl -sSL https://install.pi-hole.net | bash

Esto nos llevará a una instalación interactiva donde podremos personalizar configuraciones de Pi-hole. En mayor medida será seleccionar OK o Continue

En este punto solicitará seleccionar los Upstream DNS providers. Seleccionaré Google pero de todas formas esto lo modificaremos más adelante.

Ahora nos dará la opción de agregar una lista para bloquear Ads, es recomendable agregarla.

En mi caso habilitaré query logging ya que me interesa saber que consultas DNS se hacen en mi red.

Y acá podemos seleccionar el nivel de privacidad de estos logs.

Finalmente mostrará la pantalla final en donde indica que Pi-hole se ha instalado.

Esto es algo que también veremos desde el output de la consola. Es importante tomar la URL y la contraseña autogenerada para ingresar a la interfaz web.

Configuración

Ingresaremos con la contraseña que obtuvimos en el paso anterior y haremos una prueba rápida para verificar que todo funciona correctamente:

  1. Ir a System > Settings > DNS y verificar que existen Upstream DNS Servers habilitados, en mi caso son los de Google -esto nos permitirá resolver DNS externos-.

  1. Ir a System > Settings > Local DNS Records y crear un registro DNS para pihole, yo crearé el nombre pihole-demo.home.cervant.net y lo asignaré a su IP (192.168.1.155). Se debe crear como registro tipo A (panel izquierdo), ya que apunta a una dirección IP.

  1. Actualizar DNS Servers de una máquina cliente y verificar la resolución de dominios internos y externos. Yo modificaré la configuración DNS de mi PC de escritorio para hacer las pruebas.

Por consola podemos verificar que ya tenemos configurado el DNS server apuntando a la IP de nuestro Pi-hole y que al consultar su DNS responde con la IP como es de esperar. Con esto ya podemos usar el nombre para acceder a la UI, en donde podremos visualizar métricas del tráfico que se ha generado.

En este punto ya podemos continuar con la instalación de Unbound.

Instalación Unbound

Si instalaste un S.O. distinto a Ubuntu/Debian deberás referirte a la guía de instalación de unbound para continuar, de lo contrario estos son los pasos:

  1. Instalar desde package manager
1
sudo apt install -y unbound
  1. Copiar este archivo de configuración en la ruta /etc/unbound/unbound.conf.d/pi-hole.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
server:
    # If no logfile is specified, syslog is used
    # logfile: "/var/log/unbound/unbound.log"
    verbosity: 0

    interface: 127.0.0.1
    port: 5335
    do-ip4: yes
    do-udp: yes
    do-tcp: yes

    # May be set to no if you don't have IPv6 connectivity
    do-ip6: no

    # You want to leave this to no unless you have *native* IPv6. With 6to4 and
    # Terredo tunnels your web browser should favor IPv4 for the same reasons
    prefer-ip6: no

    # Use this only when you downloaded the list of primary root servers!
    # If you use the default dns-root-data package, unbound will find it automatically
    #root-hints: "/var/lib/unbound/root.hints"

    # Trust glue only if it is within the server's authority
    harden-glue: yes

    # Require DNSSEC data for trust-anchored zones, if such data is absent, the zone becomes BOGUS
    harden-dnssec-stripped: yes

    # Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes
    # see https://discourse.pi-hole.net/t/unbound-stubby-or-dnscrypt-proxy/9378 for further details
    use-caps-for-id: no

    # Reduce EDNS reassembly buffer size.
    # IP fragmentation is unreliable on the Internet today, and can cause
    # transmission failures when large DNS messages are sent via UDP. Even
    # when fragmentation does work, it may not be secure; it is theoretically
    # possible to spoof parts of a fragmented DNS message, without easy
    # detection at the receiving end. Recently, there was an excellent study
    # >>> Defragmenting DNS - Determining the optimal maximum UDP response size for DNS <<<
    # by Axel Koolhaas, and Tjeerd Slokker (https://indico.dns-oarc.net/event/36/contributions/776/)
    # in collaboration with NLnet Labs explored DNS using real world data from the
    # the RIPE Atlas probes and the researchers suggested different values for
    # IPv4 and IPv6 and in different scenarios. They advise that servers should
    # be configured to limit DNS messages sent over UDP to a size that will not
    # trigger fragmentation on typical network links. DNS servers can switch
    # from UDP to TCP when a DNS response is too big to fit in this limited
    # buffer size. This value has also been suggested in DNS Flag Day 2020.
    edns-buffer-size: 1232

    # Perform prefetching of close to expired message cache entries
    # This only applies to domains that have been frequently queried
    prefetch: yes

    # One thread should be sufficient, can be increased on beefy machines. In reality for most users running on small networks or on a single machine, it should be unnecessary to seek performance enhancement by increasing num-threads above 1.
    num-threads: 1

    # Ensure kernel buffer is large enough to not lose messages in traffic spikes
    so-rcvbuf: 1m

    # Ensure privacy of local IP ranges
    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

    # Ensure no reverse queries to non-public IP ranges (RFC6303 4.2)
    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

Debería funcionar directamente sin modificaciones adicionales.

Tendrás que setear do-ip6: yes si estás utilizando ipv6.

  1. Reiniciar servicio
1
sudo service unbound restart
  1. Realizar pruebas utilizando dig
1
dig pi-hole.net @127.0.0.1 -p 5335

Las primeras consultas podrían tomar más tiempo del esperado. El resultado debe verse así.

Si en lugar de pi-hole.net consultamos un registro DNS local nuestro como pihole-demo.home.cervant.net, veremos que Unbound -corriendo en el puerto 5335- intenta resolver el nombre consultando a su dominio raíz, que es cervant.net, el cual tengo hospedado con Cloudflare. Esto es lo normal y el resultado esperado, ya que estamos utilizando a Unbound como upstream DNS server.

Ahora bien, si hacemos la misma consulta pero al puerto 53, veremos que responde con el registro que habíamos configurado para nuestra red interna.

La última prueba será para probar la validación DNSSEC.

1
2
dig fail01.dnssec.works @127.0.0.1 -p 5335
dig +ad dnssec.works @127.0.0.1 -p 5335

La primera consulta debería retornar SERVFAIL sin dirección IP.

La segunda NOERROR con una dirección IP y la flag ad.

  1. Configurar pi-hole para utilizar Unbound

Para esto iremos a Settings > DNS > Custom DNS servers y nos aseguraremos de no tener ningún Upstream DNS Server habilitado. Luego, en Custom DNS Servers colocaremos 127.0.0.1#5335 como único valor y guardaremos los cambios.

La manera de verificar que esto funciona correctamente es seguir usando Pi-hole como nameserver y consultar dominios externos. Debería permitir navegación de manera normal con el plus de bloquear anuncios.

Instalar listas de bloqueo

Si bien Pi-hole por defecto bloquea anuncios al traer una lista de dominios a bloquear -si habilitaste esa opción- también tenemos la posibilidad de agregar nuestras propias listas o utilizar unas de terceros. Para esto yo recomiendo utilizar las listas del repositorio dns-blocklists.

Yo personalmente estoy utilizando la lista Multi Pro Adblock y me funciona perfecto.

Es importante verificar que la lista es compatible con nuestro servidor DNS, para eso revisar la columna Should be used for.

El utilizar una lista muy agresiva podría provocar bloqueos en sitios legítimos sin ads.

Para instalar la lista copiaremos su enlace, iremos a Lists para agregarla como blocklist.

Una vez hecho quedará con un ícono gris, es decir inactiva. Para activarla se debe ejecutar el comando pihole -g desde CLI.

Esto cargará la lista y quedará funcional.

De esta forma ya tendríamos resolución DNS y bloqueos de Ads en nuestra red local.

Próximos pasos

Si estás en este punto, en donde acabas de montar tu propio DNS local, querrás continuar con la implementación de un Proxy Manager. Básicamente, es una herramienta que te permite redirigir y exponer otros servicios que tengas corriendo en tu red (como apps web, dashboards o contenedores) usando nombres de dominio personalizados, certificados SSL automáticos y sin necesidad de configuraciones complicadas. Es una forma práctica de mantener tu homelab organizado y accesible.

Opciones populares para Proxy son Nginx Proxy Manager, Traefik y Caddy. Personalmente utilizo NPM para mi entorno de Docker Swarm y otros contenedores independientes y Traefik como Proxy de mi entorno de Kubernetes con K3s. Te dejo los enlaces a los post anteriores en donde se implementan ambas opciones:

Otras opciones

  • Pi-hole Container: Al ejecutarlo en un contenedor Docker, puedes integrarlo fácilmente en tu infraestructura sin modificar directamente tu sistema operativo. Es una opción interesante mientras podamos disponer del puerto 53 y eso no haga conflicto con el sistema operativo host.
  • Adguard Home: AdGuard Home es una alternativa moderna a Pi-hole que también funciona como un servidor DNS con bloqueo de rastreadores y anuncios. Lo instalé antes de Pi-hole y la verdad no tengo quejas, cumple con creces para un entorno de homelab.
  • Technitium: DNS server orientado a la seguridad y privacidad. Aunque no lo he utilizado personalmente, he leído excelentes opiniones sobre su rendimiento y capacidad de personalización

Referencias

Construye, automatiza, repite. ¡Nos vemos en el próximo post!

Esta entrada está licenciada bajo CC BY 4.0 por el autor.