643 - Un resolutor de DNS y Traefik con certificados

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

1:25
-3:15

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.

6 comentarios en “Un resolutor de DNS y Traefik con certificados

  1. MásCurioso hace 7 días

    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.

    1. AT
      atareao hace 3 días

      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.

  2. NA
    Nacho hace 6 días

    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).

    1. PA
      Paloke hace 5 días

      Lo tengo montado igual (Proxmox / LXC) y es mano de santo.

      1. AT
        atareao hace 3 días

        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?

    2. AT
      atareao hace 3 días

      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.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *