Hoy toca hablar de Traefik, Internet. Una herramienta fantástica que no puede faltar en vuestros homelabs o incluso en entornos de producción. Traefik es un proxy inverso para los que no sepáis en qué consiste esto en los proxys inversos, os voy a poner un ejemplo sencillo para que lo entendáis. Un proxy inverso es una herramienta que se sitúa entre nuestros servidores de la red interna y los usuarios que acceden desde ya sea la intranet o Internet. Es decir, van a actuar como un camarero recibiendo las peticiones del usuario y las va a redirigir internamente al servidor que corresponda qué beneficios tiene el uso de un proximo inverso, pues tiene muchos beneficios y vamos a enumerarlos ahora:

  • Balancea carga para no saturar servidores
  • Bloquea peticiones no deseadas
  • Bloquea peticiones basadas en goelocalización
  • Enmascara nuestra red interna

Para este laboratorio nos vamos a apoyar en Docker, vamos a montar un contenedor en el que va a estar Traefic instalado. Una vez lo tengamos instalado, vamos a utilizar Traefic para servir certificados SSL a nuestros servicios internos. Estos certificados SSL van a ser válidos y firmados por una entidad certificadora pública así que nos vamos a quitar de en medio el famoso error de este sitio no es seguro tu información no está protegida y que tanto ruido hacen los certificados autofirmados.

La estructura de directorios que vamos a usar es la siguiente:

  • Contenedor Docker
    • Datos
      • acme.json
      • trefik.yml
      • config.yml
    • docker-compose.yaml
    • .env
    • cloudflare_token.txt

Empezamos con el compose de Traefik:

services: # Define la sección de servicios del archivo docker-compose
  traefik: # Define un servicio llamado traefik
    image: traefik:latest # Utiliza la imagen oficial de traefik más reciente
    container_name: traefik # Establece el nombre del contenedor a traefik
    restart: unless-stopped # Reinicia el contenedor a menos que esté detenido
    security_opt: # Opciones de seguridad
      - no-new-privileges:true # Deshabilita privilegios para mayor seguridad del contenedor
    networks: # Conecta el contenedor a la red proxy (definida más adelante)
      - proxy
    ports:
      - 80:80 #(expone el puerto 80 del contenedor en el puerto 80 del host para tráfico HTTP)
      - 443:443 #(expone el puerto 443 del contenedor en el puerto 80 del host para tráfico HTTPS)
      - 8080:8080 #(expone el puerto 8080 del contenedor en el puerto 8080 del host para un servicio adicional)
      # - 443:443/tcp #descomentar para usar HTTP3
      # - 443:443/udp #descomentar para usar HTTP3
    environment:
      CF_DNS_API_TOKEN_FILE: /run/secrets/cloudflare_token # Establece la ruta al token de API de Cloudflare desde un secreto de Docker (más seguro)
      # CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN} # Alternativa: usar variable de entorno desde el archivo .env (menos seguro, comentar la línea anterior)
      TRAEFIK_DASHBOARD_CREDENTIALS: ${CREDENCIALES_DASHBOARD} # Establece credenciales para el panel de Traefik (reemplazar con el nombre real de la variable)
    secrets: # Define secretos usados por el contenedor
      - cloudflare_token # Referencia al secreto llamado cloudflare_token
    env_file: .env # use .env        # Usa variables de entorno desde un archivo llamado .env
    volumes:
      - /etc/localtime:/etc/localtime:ro #Monta la información de zona horaria del host en el contenedor
      - /var/run/docker.sock:/var/run/docker.sock:ro #Otorga acceso al socket de Docker para descubrimiento de servicios
      - ./datos/traefik.yml:/traefik.yml:ro #Monta el archivo de configuración de Traefik
      - ./datos/acme.json:/acme.json #Monta volumen para almacenar certificados
      - ./datos/config.yml:/config.yml:ro #Lo descomentaremos para usar nuestro Proxmox
    labels:
      - "traefik.enable=true" # Habilita el servicio Traefik
      - "traefik.http.routers.traefik.entrypoints=http" # Define el punto de entrada para el panel de Traefik (usa HTTP)
      - "traefik.http.routers.traefik.rule=Host(`traefik-dashboard.local.nshlab.de`)" # Define una regla para enrutar el tráfico de `traefik-dashboard.local.nshlab.de` al servicio Traefik
      - "traefik.http.middlewares.traefik-auth.basicauth.users=${CREDENCIALES_DASHBOARD}" # Define autenticación básica para el panel de Traefik (reemplazar con el nombre real de la variable)
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https" # Define middleware para redirigir el tráfico HTTP a HTTPS
      - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https" # Define middleware para establecer la cabecera X-Forwarded-Proto para reconocimiento HTTPS
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect" # Asocia el middleware de redirección con el router Traefik
      - "traefik.http.routers.traefik-secure.entrypoints=https" # Define un router seguro para tráfico HTTPS
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik-dashboard.local.nshlab.de`)" # Define una regla para el router seguro (misma que el router HTTP)
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth" # Asocia el middleware de autenticación con el router seguro
      - "traefik.http.routers.traefik-secure.tls=true" # Habilita TLS para el router seguro
      - "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare" # Utiliza el resolvedor de certificados de Cloudflare
      - "traefik.http.routers.traefik-secure.tls.domains[0].main=local.nshlab.de" # Define el dominio principal y los nombres alternativos (SANs) para el certificado
      - "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.local.nshlab.de" # Define el dominio principal y los nombres alternativos (SANs) para el certificado
      - "traefik.http.routers.traefik-secure.service=api@internal" # Asocia el router seguro con el servicio interno "api" (suponiendo que tienes un servicio llamado "api")

secrets:
  cloudflare_token:
    file: ./cloudflare_token.txt # Especifica el archivo que contiene el token de Cloudflare

networks:
  proxy:
    external: true # Indica que la red "proxy" es externa y ya existe

Archivo traefik.yml:

# Habilita el panel de control de la API (opcional)
api:
  dashboard: true #habilita el dashboard
  debug: true # Habilita el modo debug de la API (útil para depuración)
entryPoints:
  http:
    address: ":80" #Punto de entrada HTTP (escucha en el puerto 80 por defecto)
    http: # Configura redirecciones forzadas de HTTP a HTTPS
      redirections:
        entryPoint:
          to: https # Redirigir a este punto de entrada
          scheme: https # Forzar el esquema HTTPS
  https: # Punto de entrada HTTPS (escucha en el puerto 443 por defecto)
    address: ":443"
serversTransport: # Configura la seguridad del transporte (evita advertencias de certificados no válidos)
  insecureSkipVerify: true # Omitir la verificación de certificados (no recomendado en producción)
providers: # Define los proveedores de servicios
  docker: # Proveedor para servicios Docker
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false # Deshabilita la exposición automática de servicios Docker
  file:
    filename: /config.yml
certificatesResolvers:
  cloudflare:
    acme: # Configura el módulo ACME para obtener certificados SSL
      email: carlos@nosolohacking.info
      storage: acme.json # Archivo donde se almacenarán los certificados
      caServer: https://acme-v02.api.letsencrypt.org/directory # Servidor ACME de Let's Encrypt (producción)
      #caServer: https://acme-staging-v02.api.letsencrypt.org/directory # Servidor ACME de Let's Encrypt para pruebas (opcional)
      dnsChallenge: # Configura el uso de Cloudflare para desafíos DNS
        provider: cloudflare

        resolvers: # Servidores DNS utilizados para resolver registros durante los desafíos
          - "1.1.1.1:53"
          - "1.0.0.1:53"

Archivo config.yml

# Sección http de la configuración de Traefik
http:
  #region routers (Bloque de comentarios para definir routers)
  routers:
    # Define un router llamado "proxmox"
    proxmox:
      # Indica el punto de entrada para este router (solo HTTPS)
      entryPoints:
        - "https"
      # Define una regla para el router. Solo atiende tráfico dirigido al host "pve.local.nshlab.de"
      rule: "Host(`pve.local.nshlab.de`)"
      # Define middlewares que se aplicarán a este router
      middlewares:
        # Aplica el middleware "default-headers" (definido más adelante)
        - default-headers
        # Aplica el middleware "https-redirectscheme" (definido más adelante)
        - https-redirectscheme
      # Habilita TLS para este router (requiere certificado SSL válido)
      tls: {}
      # Enruta el tráfico a un servicio llamado "proxmox" (definido más adelante)
      service: proxmox

    # Define otro router llamado "pihole" (configuración pendiente)
    pihole:
      # ... (agregar la configuración específica para el router "pihole")

  #endregion (Fin del bloque de comentarios para routers)

  #region services (Bloque de comentarios para definir servicios)
  services:
    # Define un servicio llamado "proxmox"
    proxmox:
      # Configura el balanceador de carga para este servicio
      loadBalancer:
        # Define los servidores a los que se distribuirá la carga
        servers:
          # Agrega un servidor con la URL "https://10.10.100.11:8006"
          - url: "https://10.10.100.11:8006"
        # Indica que se debe incluir el encabezado Host en la solicitud al servidor
        passHostHeader: true

  #endregion (Fin del bloque de comentarios para servicios)

  # Define middlewares (filtros de tráfico) utilizados por los routers
  middlewares:
    # Middleware "https-redirectscheme" (redirecciona a HTTPS)
    https-redirectscheme:
      # Define la configuración de redirección
      redirectScheme:
        # Indica que se debe redirigir a HTTPS
        scheme: https
        # Indica que la redirección debe ser permanente (código de estado 301)
        permanent: true

    # Middleware "default-headers" (añade encabezados de seguridad)
    default-headers:
      # Define los encabezados que se añadirán a las respuestas
      headers:
        # Previene ataques Clickjacking (X-Frame-Options)
        frameDeny: true
        # Filtra ataques XSS en el navegador (X-XSS-Protection)
        browserXssFilter: true
        # Evita la detección del tipo de contenido por el navegador (X-Content-Type-Options)
        contentTypeNosniff: true
        # Fuerza el encabezado Strict-Transport-Security (STS)
        forceSTSHeader: true
        # Incluye subdominios en la política de seguridad STS
        stsIncludeSubdomains: true
        # Precarga la política STS en los navegadores
        stsPreload: true
        # Define la duración de la política STS en segundos (6 meses)
        stsSeconds: 15552000
        # Define el valor personalizado del encabezado X-Frame-Options
        customFrameOptionsValue: SAMEORIGIN
        # Añade un encabezado personalizado X-Forwarded-Proto con valor "https"
        customRequestHeaders:
          X-Forwarded-Proto: https

    # Middleware "default-whitelist" (permite lista blanca de IPs)
    default-whitelist:
      # Define una lista de IPs permitidas
      ipAllowList:
        # Define rangos de IPs permitidas
        sourceRange:
          - "10.0.0.0/8" # Red privada 10.0.0.0 - 10.255.255.255
          - "192.168.0.0/16" # Red privada 192.168.0.0 - 192.168.255.255
          - "172.16.0.0/12" # Red privada 172.16.0.0 - 172.31.255.255

    # Middleware "secured" (cadena de middlewares de seguridad)
    secured:
      chain:
        middlewares:
          - default-whitelist
          - default-headers

Comandos para crear la red:

docker network create proxy

Comando para instalar htpasswd:

sudo apt update
sudo apt install apache2-utils

Comando para crear usuario de Traefik:

echo $(htpasswd -nB carlos) | sed -e s/\\$/\\$\\$/g

Vídeo

error: ooops!