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
- Datos
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