Problema
En muchos homelabs se combinan Pi‑hole como resolutor DNS interno, Nginx Proxy Manager (NPM) para la terminación TLS y Cloudflare Tunnel para exponer servicios al exterior. Cuando los navegadores dentro de la LAN intentan acceder a sub‑dominios gestionados por NPM, aparecen errores como ERR_SSL_UNRECOGNIZED_NAME_ALERT o ERR_QUIC_PROTOCOL_ERROR. La causa típica es que el cliente recibe una respuesta DNS que mezcla direcciones internas (IPv4) con registros externos (IPv6 o A) obtenidos de Cloudflare, lo que rompe la coincidencia del certificado y obliga al navegador a abortar la conexión TLS.
Este patrón se repite en cualquier entorno donde:
- El dominio está registrado en Cloudflare y se usa un túnel (
cloudflared) que apunta a NPM. - Pi‑hole es el DNS autoritario para la LAN y está configurado para reenviar consultas desconocidas a los servidores de Cloudflare.
- NPM tiene la opción Force SSL activada para todos los hosts.
- Se utilizan certificados wildcard emitidos por Let’s Encrypt mediante DNS‑01 challenge.
El síntoma es idéntico independientemente del número de dominios o sub‑dominios implicados: el navegador funciona correctamente desde fuera de la red, pero falla dentro, a pesar de que curl contra la IP interna con el nombre correcto devuelve la página esperada.
Causa
1. Consulta HTTPS (QTYPE=HTTPS) que escapa al resolutor externo
Pi‑hole, por defecto, permite cualquier tipo de consulta DNS y reenvía lo que no reconoce a los upstream configurados. Cuando el cliente (p. ej. Chrome) solicita un registro HTTPS (RFC 9460) para descubrir parámetros de TLS, Pi‑hole no tiene una entrada local y la envía a Cloudflare. Cloudflare responde con un registro que apunta a la IP pública del túnel (IPv6 o IPv4). El navegador, al combinar esa respuesta con la dirección interna que obtuvo de una consulta A/AAAA previa, termina intentando conectar a la IP pública mientras el certificado está emitido para el nombre interno, provocando los errores de SSL.
2. Prioridad de registros AAAA sobre A en IPv6‑enabled LAN
Incluso cuando Pi‑hole devuelve solo la dirección IPv4 interna en la consulta A, la respuesta HTTPS puede contener un registro AAAA que el cliente prefiere. El tráfico se dirige fuera de la red y el túnel vuelve a pasar por Cloudflare, generando una ruta de doble salto que rompe la coincidencia de nombre.
3. NPM con Force SSL envía siempre HTTPS al cliente
Al forzar HTTPS, NPM no permite una negociación HTTP‑only que pudiera “engañar” al cliente para usar la IP interna. El cliente confía en la dirección que le entrega DNS; si esa dirección es externa, la conexión falla antes de que NPM pueda servir el certificado correcto.
Solución
Bloquear localmente las consultas HTTPS (QTYPE=HTTPS) para los dominios gestionados por NPM evita que Pi‑hole reenvíe esas peticiones a Cloudflare. La forma más sencilla es crear una regla regex que niegue esas consultas. La regla se aplica a nivel de dominio y tipo de consulta, dejando intactas las consultas A/AAAA que siguen resolviendo a la IP interna.
Pasos generales
-
Identificar los dominios gestionados por NPM
Anote los dominios (p. ej.example.com) y cualquier sub‑dominio wildcard (*.example.com) que necesite resolución interna. -
Crear una expresión regular que coincida con el dominio y el tipo HTTPS
La sintaxis de Pi‑hole permite especificar el tipo de consulta después de un punto y coma:^.*\.example\.com$;querytype=HTTPS -
Añadir la regla a la lista de regex denegados
- UI → Group Management → Domains → Regex filter → Add
- Pegue la expresión y asigne el filtro al grupo Default (u otro que use para la LAN).
-
Reiniciar Pi‑hole para que la nueva regla entre en vigor:
pihole restartdns -
Verificar que la consulta HTTPS ya no se reenvía
En una máquina cliente, ejecute:dig +dnssec +short -t HTTPS sub.example.com @<IP_PIHOLE>La respuesta debe ser NOERROR sin registros, indicando que Pi‑hole bloqueó la petición.
Con esta configuración, el cliente solo recibe los registros A/AAAA internos y nunca combina una dirección pública con el certificado interno, eliminando los errores de SSL y QUIC.
Alternativas
- Desactivar IPv6 en la LAN: elimina la ruta externa, pero no siempre es viable si la red ya usa IPv6.
- Configurar Pi‑hole para responder con registros AAAA internos: requiere crear entradas estáticas para cada sub‑dominio, lo cual complica la gestión cuando se usan wildcards.
- Usar un DNS‑over‑HTTPS (DoH) interno que filtre QTYPE=HTTPS antes de reenviar a Cloudflare. Esta opción implica desplegar un resolver adicional (p. ej.
coredns) y no siempre justifica la complejidad.
Cuándo aplicar esta solución
Aplica cuando:
- Se usan dominios internos gestionados por NPM con Force SSL.
- Pi‑hole es el resolutor DNS de la LAN y está configurado para reenviar consultas desconocidas a Cloudflare (u otro resolutor público).
- Los navegadores internos presentan
ERR_SSL_UNRECOGNIZED_NAME_ALERT,ERR_QUIC_PROTOCOL_ERRORo fallos similares al acceder a sub‑dominios internos.
No aplica si:
- No se utiliza Pi‑hole como DNS interno (p. ej. se usa solo DHCP con DNS externo).
- Todos los servicios están expuestos exclusivamente a través de HTTP y no se fuerza TLS.
- La red no tiene IPv6 habilitado y no se realizan consultas HTTPS DNS.
Código
# 1. Añadir regla regex a Pi-hole (puede hacerse vía UI o editando el archivo)
echo '^.*\.example\.com$;querytype=HTTPS' >> /etc/pihole/regex.list
# 2. Recargar la configuración DNS
pihole restartdns
Verificación
- Desde una workstation, ejecutar
dig -t A sub.example.com @<IP_PIHOLE>y confirmar que la IP devuelta es la interna. - Ejecutar
dig -t HTTPS sub.example.com @<IP_PIHOLE>y comprobar que la respuesta está vacía o contieneNOERRORsin registros. - Abrir el mismo sub‑dominio en Chrome/Firefox dentro de la LAN; la página debe cargar sin errores SSL.
- Probar desde el exterior (red móvil o VPN) para asegurarse de que la resolución pública sigue funcionando; la regla solo afecta a consultas dirigidas a Pi‑hole.
Notas adicionales
- La regla regex es sensible a mayúsculas/minúsculas; Pi‑hole trata los dominios en minúsculas, así que use siempre minúsculas en la expresión.
- Si tiene varios dominios, puede combinar varias expresiones en una sola línea usando
|, por ejemplo:^.*\.(example\.com|demo\.net)$;querytype=HTTPS. - Mantenga la lista de regex bajo control de versiones; un cambio accidental puede bloquear consultas legítimas.
- Aunque bloquear QTYPE=HTTPS reduce la superficie de ataque, siga aplicando buenas prácticas de hardening en NPM y Cloudflare (cifrado TLS fuerte, HSTS, etc.).
- Si en el futuro necesita que un sub‑dominio externo sea accesible mediante HTTPS DNS, excluya ese dominio de la regla regex o cree una política de excepción en Pi‑hole.