643 - Un resolutor de DNS y Traefik con certificados
Como montar tu propio resolutor de #DNS y un proxy inverso como #Traefik con certificados autofirmados para tener todos tus servicios a tu alcance
Cuando me di cuenta de que necesitaba, a priori, al menos una decena de servicios para el stack multimedia, me entró una enorme pereza de forma casi instantánea. No por el hecho de tener que levantar todos esos servicios, si no mas bien por la cantidad de puertos que iba a tener en funcionamiento, al menos uno para cada uno de los servicios, y en algunos casos mas de uno. Claro, esto me lleva a lo siguiente, me tendrÃa que acordar de cada uno de los puertos y asociar el número de puerto al servicio alojado. Simplemente una auténtica pereza. En ese momento, me di cuenta que tenÃa que resolverlo de alguna manera. Y claro, ¿que mejor forma que utilizar un resolutor de DNS y un proxy inverso? Pues efectivamente, esa es la solución y por lo que he comenzado. AsÃ, en este episodio te hablaré sobre como montar un resolutor de DNS en tu red local y utilizar un proxy inverso con certificados autofirmados.
Un resolutor de DNS y Traefik con certificados
Sobre los DNS
Antes de meterme en harina, querÃa dar una visión general sobre los DNS y los proxy inversos, para aquellos que estos dos conceptos le suenen a chino.
Empezaré por el principio. Como sabes las direcciones IP son números que identifican a un dispositivo en una red. Pero claro, no es fácil recordar una dirección IP, por eso se crearon los nombres de dominio. Un nombre de dominio es una cadena de caracteres que se asocia a una dirección IP. AsÃ, en lugar de tener que recordar una dirección IP, puedes recordar un nombre de dominio. Es mucho mas sencillo recordar atareao.es que 67.123.12.191, esto es innegable.
Un resolutor de DNS es un servidor que se encarga de traducir un nombre de dominio a una dirección IP. AsÃ, cuando tu escribes atareao.es en tu navegador, el resolutor de DNS se encarga de traducirlo a la dirección IP correspondiente. Por ejemplo, el conocido de Google 8.8.8.8, es un resolutor de DNS.
Sobre el proxy inverso
Una vez aclarado el tema del DNS, llegamos al proxy inverso, que es un concepto similar. Básicamente lo que hace es dirigir el tráfico. Cuando el tráfico llega a un proxy inverso, en base a una serie de condiciones este se dirige a un sitio u otro.
Por ponerte un ejemplo práctico. Pongamos que tienes un servidor en internet con dirección 1.2.3.4. Y esa dirección IP se la has asociado a tuservidor.com. Pongamos que tienes un blog, un podcast y un servicio de música. ¿Como llevarÃas a cabo esto? Pues bien, con un proxy inverso. Cuando el tráfico llega a tuservidor.com el proxy inverso se encarga de dirigirlo al blog, al podcast o al servicio de música, en función de la URL que se haya solicitado. Si cuando haces la llamada pones blog.tuservidor.com te llevará al blog, si pones podcast.tuservidor.com te llevará al podcast y si pones musica.tuservidor.com te llevará al servicio de música.
¿Porque quiero utilizar un resolutor de DNS?
¿Que es lo que pasa en tu casa? Pues que tienes un montón de dispositivos conectados a tu red local. Y cada uno de esos dispositivos tiene una dirección IP. Y claro, si quieres acceder a uno de esos dispositivos, tienes que recordar la dirección IP. Es mucho mas sencillo recordar un nombre de dominio que una dirección IP. Asà que, si tienes un resolutor de DNS en tu red local, puedes asignar un nombre de dominio a cada uno de tus dispositivos. AsÃ, en lugar de tener que recordar la dirección IP de tu NAS, puedes asignarle el nombre de nas.local. Y asà para cada uno de los dispositivos que tengas.
En mi caso, actualmente tengo el un NAS, y un par de servidores. Uno de estos servidores es precisamente donde están alojados todos los servicios de este stack multimedia.
¿Porque quiero utilizar un proxy inverso?
Como te comentaba al principio, no quiero tener que recordar los puertos de cada uno de los servicios que tengo en funcionamiento. Asà que, con un proxy inverso, puedo asignar un nombre de dominio a cada uno de los servicios. AsÃ, en lugar de tener que recordar que el blog está en el puerto 8080, simplemente tengo que recordar que está en blog.local. Y asà para cada uno de los servicios que tengo en funcionamiento.
Por ejemplo, el servicio multimedia lo puedo tener en multimedia.local, el blog en blog.local, el podcast en podcast.local y asà sucesivamente. Y todos pueden estar en la misma máquina o en distintas. Me da igual, simplemente tengo que recordar el nombre de dominio. Y entre el resolutor de DNS y el proxy inverso se encargan de llevarme al sitio adecuado.
¿Porque quiero utilizar certificados autofirmados?
Esto ya es mas cuestión de poder acceder a los servicios utilizando protocolo seguro, porque es por defecto lo que ofrecen hoy en dÃa los navegadores. Asà que no quiero tener que corregir y escribir http
en lugar de https
. Simplemente, creo certificados autofirmados y me olvido. Además me olvido de verdad, porque les he dado una validez de 10 años.
¿Y como he montado todo esto?
Como ya te puedes imaginar, esta todo montado con Docker, y en particular he utilizado Unbound
para el resolutor DNS y Traefik
para el proxy inverso.
services:
unbound:
container_name: unbound
image: mvance/unbound:latest
init: true
ports:
- 53:53/tcp
- 53:53/udp
volumes:
- ./unbound.conf:/opt/unbound/etc/unbound/unbound.conf
- ./conf:/opt/unbound/etc/unbound/unbound.conf.d/
restart: unless-stopped
La configuración de unbound.conf
la puedes encontrar en mis repositorios de GitHub Y dentro del directorio ./conf
, he puesto dos archivos, a-records.conf
, que tiene el siguiente contenido,
local-zone: "mi.local" redirect
local-data: "mi.local" 86400 IN A 192.168.1.21"
Lo de local.mi
es un ejemplo, puedes poner lo que tu quieras, o mejor dicho, lo que te resulte mas cómodo.
Y el otro archivo es blacklist.conf
. Básicamente un listado de mas de 100.000 direcciones de dominio que no quiero que se resuelvan. Lo que hace una pihole
. El contenido es similar a este,
local-zone: "ejemplo.com" always_nxdomain
Esas direcciones de dominio corresponden a servicios de telemetrÃa, anuncios, etc. De esta manera cuando desde la red local miro una página web donde hay insertados anuncios, no se resuelven y no se muestran. Es una manera de bloquear anuncios en la red local. Sencillo, simple y eficaz.
En este apartado me queda automatizar el proceso para hacer esto. Algo sencillo, básicamente un cron, que cada 24 horas se conecte a github.com y me descargue ese listado actualizado, me lo convierta al formato adecuado y reinicie el servicio de unbound. Pero eso ya es otra historia.
Traefik
Traefik es un proxy inverso que se encarga de dirigir el tráfico en función de la URL solicitada. Es algo complejo de configurar, al menos inicialmente, pero cuando le coges el truco, la verdad es que no es tan difÃcl. Pero la gran ventaja que tiene es que es muy potente y te ofrece muchas posibilidades. Además, es muy rápido y consume pocos recursos. Asà que es ideal para tenerlo en tu red local.
El docker-compose
que he utilizado es el siguiente,
services:
traefik:
image: traefik:v3.2
container_name: traefik
init: true
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./configuration:/configuration
- ./certificates:/certificates
networks:
- proxy
networks:
proxy:
external: true
Algunas indicaciones, es que estoy utilizando la versión 3.2 de Traefik, que está recien salida del horno, y que he creado una red llamada proxy
. Para esto tienes que ejecutar lo siguiente antes de levantar traefik o de otra forma te dará error,
docker network create proxy
La configuración de traefik es la siguiente,
api:
dashboard: true
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
permanent: true
https:
address: ":443"
http:
tls: true
serversTransport:
maxIdleConnsPerHost: 1
log:
level: INFO
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: true
watch: true
network: proxy
file:
directory: /configuration
watch: true
Por otro lado, en el directorio ./configuration
he puesto un archivo dynamic.yml
, que tiene el siguiente contenido,
http:
routers:
api:
rule: Host(`traefik.mi.local`)
service: api@internal
middlewares:
- auth
middlewares:
auth:
basicAuth:
users:
- "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
- "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
tls:
stores:
default:
defaultCertificate:
certFile: /certificates/mi.local+4.pem
keyFile: /certificates/mi.local+4-key.pem
Para generar la contraseña de los usuarios para la autenticación básica, puedes utilizar el siguiente comando,
htpasswd -nb <user> <password>
Mientras que para los certificados he utilizado mkcert
, que es una herramienta que te permite generar certificados autofirmados. Para instalarlo simplemente tienes que ejecutar lo siguiente,
mkcert mi.local "*.mi.local" localhost 127.0.0.1 ::1
mkcert es una herramienta muy sencilla de utilizar y muy potente. Te permite generar certificados autofirmados para cualquier nombre de dominio. Y lo mejor de todo es que te permite generar certificados con validez de 10 años. Asà que, una vez que los has generado, te olvidas de ellos.
Una vez generados los certificados e instalados en Traefik siguiendo las instrucciones indicadas anteriormente, solo te queda instalar los certificados en tu navegador. Esto lo puedes hacer fácilmente de nuevo con mkcert
, simplemente ejecutando el siguiente comando,
mkcert -install
Conclusión
Con esto ya tengo la primera parte del sistema. Ahora solo me queda ir añadiendo servicios y configurando el proxy inverso para que me dirija al sitio adecuado. Y por supuesto, ir añadiendo nombres de dominio a los dispositivos de la red local. Pero eso ya es otra historia.
En el seguiente episodio pasaré a montar el resto de servicios auxiliares que si bien no son extricamente necesario creo que son fundamentales para conseguir que esto esté lo mas automatizado posible, y que las necesidades de mantenimiento se reduzan a la mÃnima expresión.
La duda es en cuanto a los certificados autofirmados: ¿Los aceptan todos los dispositivos? Por ejemplo, con una configuración sencilla de HTTPS local, Firefox básicamente no te deja acceder a menos que esté firmado por una autoridad ‘legal’. Me imagino que esto será un problema en dispositivos como televisores. Nota aparte: hay errores gramaticales en los Ãndices de las preguntas. DeberÃa ser ‘¿Por qué …’, y no ‘¿Porque …’. Para esos despistes, se pueden utilizar modelos generativos de texto para corregir la gramática. Saludos.
Hola,
Pues no te sabrÃa decir, dependerá de la propia configuración y si te permite añadir certicado CA con lo que con eso se evitarÃa.
Respecto al tema de los errores, siempre cometo el mismo error con los «porques» incluso es posible que aquà lo haya cometido. Tengo que prestar mas atención.
Muchas gracias y un saludo.
Y para hacerlo sin tirar de consola, ni una sóla lÃnea, y además con Let’s Encrypt, nginxproxymanager.
Bueno, en mi caso es que no tengo dockers, sino servidores completos en contenedores LXC (con Proxmox).
Lo tengo montado igual (Proxmox / LXC) y es mano de santo.
Hola Paloke,
En tu caso haces igual que Nacho? Dedicas servidores virtualizados en lugar de contenedores? Si es asÃ, porque lo haces de esta forma?
Hola,
una duda que siempre me surge, aunque no es exactamente lo mismo que tu comentas. Si que encuentro muchos que montan un servidor virtualizado con proxmox y dentro los contenedores con Docker. ¿Por qué se hace as�
Es una curiosidad mÃa
Saludos y gracias.