Acceso seguro con doble factor con Authelia y NGINX Proxy Manager

Acceso seguro con doble factor con Authelia y NGINX Proxy Manager

En este post vamos a seguir yendo un poco más allá en la seguridad de nuestro NAS y de los servicios que montamos en él.

Para ello vamos a montar y configurar login de usuario con usuario, contraseña y verificación de doble factor para aquellos contenedores que, por defecto, no tienen esta forma de hacer login en su configuración de forma nativa.

¿Qué tenemos que tener?

  • Un dispositivo que ejecute docker, en nuestro caso el NAS, pero podemos hacerlo en un ordenador, una raspberry pi o cualquier otro dispositivo donde podamos montar docker.
  • Portainer instalado, ya que lo haremos a través de portainer, aunque podemos hacerlo a través de Linux y docker-compose y para ello pondré los archivos por aquí.
  • Dominio propio
  • NGINX Proxy Manager como gestor de nuestros proxys inversos.

Paso 1

  • Vamos a Portainer, y nos vamos a stack
  • Le damos al stack el nombre de authelia y pegamos el código del docker-compose que está en este archivo
  • Antes de darle al botón DEPLOY STACK, tendrémos que ir a FILE STATION y crear las carpetas que pongamos en la ruta desde la que el contenedor cogerá la información.
  • Ahora cuando pulsamos sobre DEPLOY STACK, nos pasará algo que no es lo habitual y es que el contenedor no se inicia, sino que se para. Si entramos al log del contenedor, veremos que nos dice que el archivo configuration.yml no está, o no está correctamente configurado.
  • Entramos en la carpeta config y borramos el archivo configuration.yml que existe.
  • Nos bajamos este archivo y lo colocamos dentro de la misa carpeta donde hemos borrado el anterior.
  • Tendremos que hacer los cambios que os comento en el mismo archivo
# yamllint disable rule:comments-indentation
---
###############################################################################
#                           Authelia Configuration                            #
###############################################################################

theme: dark #light/dark Elige el tema que más te guste
jwt_secret: 1234567890abcdefghifjkl #Visita https://www.grc.com/passwords.htm y copia el numero largo de la ventana que se llama 64 random hexadecimal characters (0-9 and A-F):

default_redirection_url: https://google.com/ #Aqui hará una redireccion si no existe ningun dominio en nuestro archivo

server:
  host: 0.0.0.0 #No tocar, hay que dejarlo así
  port: 9091 #Este es el puerto por defecto, no cambiarlo
  path: ""
  buffers:
    read: 4096
    write: 4096
  enable_pprof: false
  enable_expvars: false
  disable_healthcheck: false
  tls:
    key: ""
    certificate: ""

log:
  level: debug

totp:
  issuer: yourdomain.com #tu nombre de dominio. No es el subdominio, sino que es el fulanito.es
  period: 30
  skew: 1

authentication_backend:
  password_reset:
    disable: false
  refresh_interval: 5m
  file:
    path: /config/users_database.yml #Este es el archivo que hemos creado con los usuarios, se configura en el archivo user_database.yml que tenéis en la carpeta
    password:
      algorithm: argon2id
      iterations: 1
      key_length: 32
      salt_length: 16
      memory: 1024
      parallelism: 8

access_control:
  default_policy: two_factor #yo elijo doble factor por defecto
  rules:
    ## bypass rule
    - domain:
        - "auth.yourdomain.com" #Debe ser tu subdominio creado para authelia
      policy: bypass
    - domain:
        - "sub1.yourdomain.com" #Debes poner el dominio de uno de los proxys inversos si quieres que tenga solo una validación sencilla tipo usuario/contraseña
      policy: one_factor
    - domain:
        - "sub2.yourdomain.com" #Debes poner el dominio de uno de los proxys inversos si quieres que tenga solo una validación de doble factor tipo usuario/contraseña y codigo cambiante cada 30 segundos
      policy: two_factor


      #Cada vez que modifiquemos un dominio, hay que parar y arrancar el contenedor de authelia para que ejecute los cambios.
session:
  name: authelia_session
  secret: unsecure_session_secret #Visita https://www.grc.com/passwords.htm y copia el numero largo de la ventana que se llama 64 random hexadecimal characters (0-9 and A-F):
  expiration: 3600  # 1 hour
  inactivity: 300  # 5 minutes
  domain: yourdomain.com  # tu nombre de dominio. No es el subdominio, sino que es el fulanito.es

regulation:
  max_retries: 3
  find_time: 10m
  ban_time: 12h

#Numero de intentos en un tiempo antes de ser baneado durante la duración que pongamos. En este caso si introduce 3 intentos erróneos en 10 minutos, será baneado 12 horas.
storage:
  local:
    path: /config/db.sqlite3 #Base de datos que se crea con los usuarios, no es necesario complicarse la vida para usar Authelia de forma particular
  encryption_key: you_must_generate_a_random_string_of_more_than_twenty_chars_and_configure_this #borrar el texto y sustituirlo por una cadena de 20 caracteres alternados con letras y números.

notifier:
  disable_startup_check: true #true/false
  smtp:
    username: [email protected] #tu usuario de correo
    password: Y0uRp@55W0rD! #Creamos una contraseña de aplicacion en goggle, la copiamos y la pegamos aquí
    host: smtp.gmail.com #email smtp server, este es correcto si usas gmail
    port: 587 #email smtp port, es este el que se utiliza si usas gmail
    sender: [email protected] #el correo de quien lo envia, poen el mismo que tu usuario
    identifier: localhost
    subject: "[Authelia] {title}" #email subject

Ojo que la contraseña en el mail, no es la contraseña de acceso al mail sino una contraseña de aplicación creada específicamente para esto.

Paso 2

Una vez que hayamos configurado correctamente el archivo CONFIGURATION.YML y antes de volver a poner en marcha ell contenedor de nuevo, hay que configurar el archivo USER_DATABASE.YML.

Cuando abramos este archivo, nos vamos a encontrar con lo siguiente

users:
  user1: #username for user 1. Cambia el nombre al que más te guste, este será el que usemos para el login
    displayname: "User Name 1" #Cambia el nombre al que más te guste, introducelo entre las comillas
    password: "$argon2i$v=19$m=1024,t=1,p=8$eTQ3MXdqOGFiaDZoMUtMVw$OeHWQSg9zGKslOepe5t4D1T9BZJjHA1Z+doxZrZYDgI"
    #La creamos con https://argon2.online/
    #En plain text input, ponemos la contraseña que queremos para hacer el login en authelia
    #Seleccionamos el boton de argon2id
    #Pulsamos en la tuerca de salt y nos deben salir unas letras en ese recuadro
    #Configramos con los siguientes parametros parallelism Factor: 8 memory cost: 1024 iterations: 1 hash length: 32
    #Pulsamos en generate hash y nos debe dar algo asi en el campo outputin Encoded Form $argon2id$v=19$m=1024,t=1,p=8$NTEwNGFYVHNGNlo2OGxwOA$rPYzg2lYoNH7MQ5pv6m3isHCCcJYnf+1A/uIiMUrUhE

    email: [email protected] #tu correeo electronico
    groups: #si quieres crear un grupo o grupos, cambia los nombres a continuacion
      - admins
      - dev


      #Cada vez que creemos un usuario, hay que parar y arrancar el contenedor de authelia para que ejecute los cambios.

Para obtener el enlace de la forma correcta, sólo tendremos que seguir los pasos en el orden que está comentado en el archivo.

Lo guardamos en la misma carpeta CONFIG y ahora sí, podemos arrancar el contenedor de Authelia.

Para verificar que funciona bien, en una navegador iremos a la direccion http://IPDELNAS:PUERTOELEGIDO y pulsamos intro. Deberíamos ver algo así.

Paso 3

Comenzamos la configuración de nuestros proxys inversos en NGINX Proxy Manager, para ello previamente hemos tenido que crear los subdominios en nuestro dominio.

En mi caso he creado el subdominio autheliaprueba y metube.

En NGINX Proxy Manager añado un nuevo host para el proxy autheliaprueba.bilito.es con la el subdominio correcto, la dirección IP del contenedor y el puerto elegido.

Creo el certificado SSL y guardo.

Vuelvo a editar el proxy y en SSL selecciono los cuatro checks y me voy a la pestaña de ADVANCED, donde tengo que pegar el siguiente código

location / {
set $upstream_authelia http://IPDELNAS:9091; # Tenemos que poner la IP del nas:puerto elegido
proxy_pass $upstream_authelia;
client_body_buffer_size 128k;

#Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

# Advanced Proxy Config
send_timeout 5m;
proxy_read_timeout 360;
proxy_send_timeout 360;
proxy_connect_timeout 360;

# Basic Proxy Config
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-Ssl on;
proxy_redirect  http://  $scheme://;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 64 256k;

# If behind reverse proxy, forwards the correct IP, assumes you're using Cloudflare. Adjust IP for your Docker network.
set_real_ip_from 192.168.0.0/24; #Aqui tienes que poner el rango de la tu red de casa
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
}

Haremos los cambios que os pongo indentificados en los comentarios, en la linea 2 y en la línea 31 del archivo.

Ahora añado un nuevo host para el proxy metube.bilito.es con la el subdominio correcto, la dirección IP del contenedor y el puerto elegido.

Creo el certificado SSL y guardo.

Vuelvo a editar el proxy y en SSL selecciono los cuatro checks y me voy a la pestaña de ADVANCED, donde tengo que pegar el siguiente código

location /authelia {
    internal;
    set $upstream_authelia http://IPDELNAS:9091/api/verify; #Tenemos que poner la IP del nas:puerto elegido
    proxy_pass_request_body off;
    proxy_pass $upstream_authelia;
    proxy_set_header Content-Length "";

    # Timeout if the real server is dead
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
    client_body_buffer_size 128k;
    proxy_set_header Host $host;
    proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-Uri $request_uri;
    proxy_set_header X-Forwarded-Ssl on;
    proxy_redirect  http://  $scheme://;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_cache_bypass $cookie_session;
    proxy_no_cache $cookie_session;
    proxy_buffers 4 32k;

    send_timeout 5m;
    proxy_read_timeout 240;
    proxy_send_timeout 240;
    proxy_connect_timeout 240;
}

    location / {
        set $upstream_nombredelcontenedor  http://IPDELNAS:PUERTODELDOCKER;  #Tenemos que poner la IP del nas:puerto elegido del contenedor sobre el que queremos crear el acceso seguro
        proxy_pass $upstream_nombredelcontenedor ;  #cambiar por el nombre del contenedor de la linea de arriba

		auth_request /authelia;
		auth_request_set $target_url $scheme://$http_host$request_uri;
		auth_request_set $user $upstream_http_remote_user;
		auth_request_set $groups $upstream_http_remote_groups;
		proxy_set_header Remote-User $user;
		proxy_set_header Remote-Groups $groups;
		error_page 401 =302 https://auth.dominio.es/?rd=$target_url; #Cambiar auth.dominio.es por el subdominio elegido para la validacion de authelia

		client_body_buffer_size 128k;

		proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

		send_timeout 5m;
		proxy_read_timeout 360;
		proxy_send_timeout 360;
		proxy_connect_timeout 360;

		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header X-Forwarded-Host $http_host;
		proxy_set_header X-Forwarded-Uri $request_uri;
		proxy_set_header X-Forwarded-Ssl on;
		proxy_redirect  http://  $scheme://;
		proxy_http_version 1.1;
		proxy_set_header Connection "";
		proxy_cache_bypass $cookie_session;
		proxy_no_cache $cookie_session;
		proxy_buffers 64 256k;

		set_real_ip_from 192.168.0.0/16; #Aqui tienes que poner el rango de la tu red de casa, por ejemplo 192.168.1.0, dejando el /16
		real_ip_header X-Forwarded-For;
		real_ip_recursive on;

    }

Hacemos los cambios que comento en las lineas 3, 33, 34, 42 y 67.

Una vez hecho estos cambios reinciamos el contenedor de authelia para que se apliquen de forma correcta.

Paso 4

Una vez reinciado el contenedor, si accedemos en el ejemplo creado a https://metube.bilito.es accederemos a la misma pantalla de comprobacion de funcionamiento

Introducimos el usuario creado en el archivo USER_DATABASE.yml y la contraseña que habáimos elegido.

Nos debe de salir una ventana en la que nos pide que registremos un dispositivo para la gestión del doble factor. Al pulsar en el enlace nos saldrá que nos ha enviado un correo a la dirección configurada.

En este correo hay un enlace, que debemos pulsar.

Al pulsar nos mostrará una ventana con un código QR para descargar Google authenticator y un enlace web debajo de este código QR.

En mi caso lo que hago es copiar ese código y configurarlo en bitwarden que es mi app de contraseñas, edito y le pongo ese dirección en el doble factor. Le doy a guardar y ya esta generando un código que cambia cada 30 segundos.

Cuando pulsemos sobre el botón HECHO, nos pedirá ese código y ya nos dejará entrar de forma correcta al proxy inverso creado de forma segura.

Mi nombre es David Rodríguez, apasionado por un millón de cosas que lleven placas y chips dentro.

Puedes encontrarme como @_Bilito en twitter y en grupo de Telegram de Synology NAS https://t.me/synologyNAS

Tengo un un canal de youtube que complementa al blog https://www.youtube.com/@_Bilito y que me harías un gran favor si te subscribes.

También colaboro en podcast como Bateria 2x100 https://pod.link/1115144939 y también hemos comenzado otra aventura en otro podcast Detras del Mostrador

Detrás del Mostrador
Tu Podcast de Tecnología