Últimamente me estoy esforzando en securizar todas las comunicaciones que hago desde mi red hacia el exterior. Sin embargo, aún tenía pendiente un punto bastante crítico y olvidado por lo general en toda red segura: El protocolo DNS.

Con el DNS estándar, las solicitudes se envían en texto sin formato, sin ningún método para detectar alteraciones o comportamientos indebidos. Esto significa que un actor malintencionado no sólo puede ver todas las solicitudes de DNS que estás realizando (y, por lo tanto, los sitios web que estás visitando), sino que también puede alterar la respuesta y redirigir tu dispositivo a los recursos bajo su control (como un inicio de sesión en una página de banca falsa).

Para evitar eso, podemos hacer uso del protocolo DNS-sobre-HTTPS (en inglés, DNS-Over-HTTPS), que se encarga de realizar búsquedas de DNS a través del mismo protocolo que usa para navegar por la web de forma segura: HTTPS.

DNS-sobre-HTTPS se vale del uso de solicitudes HTTPS estándar para recuperar información de DNS. Esto significa que la conexión desde el dispositivo al servidor DNS es segura y no se puede espiar, monitorear, manipular o bloquear fácilmente. Sin embargo, vale la pena señalar que el proveedor de DNS con el que estemos contactando seguirá teniendo esta capacidad. Es por ello que es importante que usemos uno "de confianza" (en la medida de lo posible)... En mi caso, he estado usando un tiempo AdGuard y, últimamente, he vuelto a Cloudflare para hacer uso de su DNS-sobre-HTTPS.

¿Cómo instalo en mi red el protocolo DNS-sobre-HTTPS?

Comenzaremos por instalar la herramienta que nos proporciona Cloudflare para ello, aunque puede trabajar con otros proveedores de DNS-sobre-HTTPS. Posteriormente, conectaremos nuestro Pi-Hole con dicha herramienta para completar el circuito dentro de nuestra red 😀.

Instalando la herramienta cloudflared

El primer paso será bajarnos el binario, .deb o .rpm que necesitemos (según la arquitectura de nuestra máquina) de https://developers.cloudflare.com/argo-tunnel/downloads.

Si optamos por los instaladores, haremos lo siguiente:

# For Debian/Ubuntu
wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-amd64.deb
sudo apt-get install ./cloudflared-stable-linux-amd64.deb
cloudflared -v

# For CentOS/RHEL/Fedora
wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-amd64.rpm
sudo yum install ./cloudflared-stable-linux-amd64.rpm
cloudflared -v
Comandos para bajar los instaladores .deb y .rpm

En caso de querer bajar el binario directamente (por ejemplo, si lo vamos a instalar en nuestra Raspberry Pi), los comandos serán:

wget -O cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64
sudo mv cloudflared /usr/local/bin
sudo chmod +x /usr/local/bin/cloudflared
cloudflared -v
Comandos para bajar los binarios y desplegarlos en el sistema
Si os pasa como a mí, que tenéis una Raspberry Pi bastante viejuna, y al ejecutar el comando cloudflared -v os da una violación de segmento o "Segmentation fault", probad con esta versión: https://bin.equinox.io/a/4SUTAEmvqzB/cloudflared-2018.7.2-linux-arm.tar.gz

Configurando la herramienta cloudflared

Una vez instalada la herramienta, procedemos a configurarla. El primer paso para ello será crear un usuario encargado de correr el demonio:

sudo useradd -s /usr/sbin/nologin -r -M cloudflared
Creación del usuario cloudflared para gestionar el demonio

Tras ello, creamos el fichero de configuración /etc/default/cloudflared y lo editaremos añadiendo la siguiente información, que constará de los parámetros de inicio con los que se arrancará el demonio:

# Commandline args for cloudflared, using Cloudflare DNS
CLOUDFLARED_OPTS=--port 5053 --upstream https://1.1.1.1/dns-query --upstream https://1.0.0.1/dns-query
Contenido que le será pasado al demonio al arranque como parámetros de entrada

En dicha configuración, podemos especificar lo siguiente:

  • port: El puerto que expondrá el demonio y al que deberemos conectar. Este dato lo deberemos apuntar para configurar nuestra Pi-Hole en el último paso.
  • upstream: Dirección HTTPS a la que consultará el demonio. Aquí podemos añadir tantas como queramos, en el ejemplo podéis ver las de Cloudflare, pero igualmente podríamos poner, por ejemplo, las de Google: https://8.8.8.8/dns-query, o cualquiera otra que deseemos (no tienen por qué ser, necesariamente, las de Cloudflared).

Actualizamos los permisos, tanto del fichero de configuración como del binario, y le asignamos el usuario que hemos creado:

sudo chown cloudflared:cloudflared /etc/default/cloudflared
sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared
Asignamos al usuario cloudflared la propiedad del ejecutable y su configuración

Ahora crearemos el script de systemd para que gestione su arranque y ciclo de vida:

sudo nano /etc/systemd/system/cloudflared.service
Comando para crear/editar el script para systemd

Y lo rellenamos con lo siguiente:

[Unit]
Description=cloudflared DNS over HTTPS proxy
After=syslog.target network-online.target

[Service]
Type=simple
User=cloudflared
EnvironmentFile=/etc/default/cloudflared
ExecStart=/usr/local/bin/cloudflared proxy-dns $CLOUDFLARED_OPTS
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target
Contenido del script para systemd

Habilitamos el servicio para que arranque al inicio, lo arrancamos y comprobamos su estado:

sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared
Damos de alta el servicio, lo arrancamos y comprobamos su estado

¡Con esto, tendríamos ya nuestro demonio listo para ser usado! Si preferís el proceso automático, existe, pero ejecuta el servicio como root y, potencialmente, será menos seguro... por lo que he optado aquí por poner la manera manual.

Actualizando la herramienta cloudflared

Al haber instalado la herramienta de manera manual, es preciso definir el proceso de actualización de la misma. Creamos un fichero de actualización que llamaremos, por ejemplo, cloudflared-update.sh y en él pondremos los comandos para actualizarlo. Para el ejemplo me baso en el caso de que lo tenemos instalado en una Raspberry Pi y la instalación la hicimos descargando directamente el binario, por lo que el script tendrá esta forma:

#!/bin/bash

cd /tmp
wget -O cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64
sudo systemctl stop cloudflared
sudo mv ./cloudflared /usr/local/bin
sudo chmod +x /usr/local/bin/cloudflared
sudo systemctl start cloudflared
VERSION=$(cloudflared -v)
STATUS=$(systemctl status cloudflared | grep "Active:" | awk '{ print $2 " " $3 }')

publishMessageToTelegram.sh "Actualización de cloudflared completada. Nueva versión: *$VERSION*. Estado: *$STATUS*" >/dev/null 2>&1
script para actualizar el binario de cloudflared

Dicho script se descargará la última versión que tengamos especificada (como véis, la URL de descarga es la misma que usamos en el primer paso para descargar dicho binario), detendrá el servicio, lo reemplazará y lo volverá a arrancar, y finalmente nos avisará por Telegram de que el proceso se ha completado, además del estado actual del servicio (que debería ser active (running) si todo ha ido bien).

Si en lugar del binario, habéis instalado el .deb o el .rpm, deberéis modificar el script para que haga la descarga y actualización, en lugar del reemplazo directo.

Configurar Pi-Hole para usar DNS-sobre-HTTPS

Como último paso, conectaremos nuestro Pi-Hole con el servicio de cloudflared para que haga las peticiones de DNS a través de él. Accedemos a nuestra consola web de Pi-Hole y, en el apartado de Settings, en la pestaña de DNS, el apartado de Upstream DNS Servers lo dejaremos tal que así:

Configuración en Pi-Hole para usar el servicio de cloudflared
Configuración en Pi-Hole
¡No os olvidéis de darle a Save para guardar los cambios!

Tras todo esto, y pasado un tiempo de uso, veréis que en vuestro dashboard de Pi-Hole desaparece cualquier referencia a los servidores DNS y tendrá un aspecto similar a éste:

Consultas en Pi-Hole haciendo uso del servicio de DNS-sobre-HTTPS
Consultas en Pi-Hole haciendo uso del servicio de DNS-sobre-HTTPS

Y con esto ya tendríamos un poquito más segura nuestra red de cara al exterior y, sobre todo, más privada 💪🏽😎. Si queréis ver cómo hacer el proceso automático o más detalle de los pasos a seguir, los podéis ver en la documentación oficial de Pi-Hole (en inglés).