
Uno de los problemas molestos que surgen al crear un NAS es que no todo el software puede funcionar con LDAP, y algunos no contienen mecanismos de autenticación.
La solución es la autenticación de extremo a extremo a través de un proxy inverso.
Un ejemplo de cómo hacer esto se discute en gran detalle, por ejemplo, en este artículo .
Dado que este artículo es parte del ciclo NAS ,
Aquí me centraré en cómo adaptar esta solución a los servicios en contenedores Docker.
La solución se basa en el ejemplo de implementación de autenticación a través de un agente externo de autenticación Nginx LDAP , pero uso la versión en contenedor de LinuxServer.io porque es una imagen preparada que cumple con ciertos estándares.
El único problema fue que los parches LinuxServer.io rompieron la autenticación HTTP básica, pero después de que se cargó la corrección de errores, fue posible volver a usar esto.
Autenticación general
Como se muestra en los artículos, la autenticación se realiza de la siguiente manera:
- El cliente accede al servicio.
- El proxy inverso redirigirá si se establece una cookie.
- Si no hay cookie, se realiza una solicitud al servicio de autenticación.
- El servicio de autenticación solicita un nombre de usuario y contraseña, que verifica accediendo al servidor LDAP.
- Si la verificación es exitosa, establece una cookie y redirige al servicio.

Una alternativa puede ser usar un módulo compilado para nginx, pero no consideraré esta opción aquí debido a algunos problemas con este módulo y su menor flexibilidad.
Una imagen modificada para el servidor OpenLDAP está aquí .
Autenticación de contenedores
Dentro de NAS, los servicios funcionan en contenedores, por lo que existe el deseo de hacer posible cambiar los modos de autenticación simplemente configurando las variables dentro del contenedor.
Dicho mecanismo ya se encuentra en la imagen ngingx-proxy utilizada y se implementa a través de plantillas que procesa docker-gen .
Inserta metadatos en la plantilla que contiene una descripción de los contenedores Docker actualmente en ejecución.
Por lo tanto, todo lo que hay que hacer es refinar la plantilla de configuración del proxy inverso para que si hay una variable condicional en el contenedor, se incluya la redirección al servicio de autenticación de extremo a extremo, que también funciona en el contenedor.
Luego, realice los ajustes apropiados a la configuración de docker-compose.
Implementación de autenticación
Modificación de la plantilla de configuración nginx-proxy
En primer lugar, se agrega un nuevo flujo ascendente, que le permite acceder al servicio de autenticación en la configuración:
proxy_cache_path cache/ keys_zone=auth_cache:10m; upstream ldap-backend { server {{ $.Env.LDAP_BACKEND }}:{{ or $.Env.LDAP_LOGIN_PORT "9000" }}; }
Se puede ver que el servicio de autenticación se ejecuta en el host ${LDAP_BACKEND}
y el puerto ${LDAP_LOGIN_PORT }
, el valor predeterminado es 9000.
Los valores de las variables serán sustituidos por docker-gen para que esta parte de la configuración se vea así en /etc/nginx/conf.d/default.conf
dentro del contenedor:
La siguiente adición establece la variable ext_ldap_auth
si la variable LDAP_EXT_AUTH se acopló en un determinado contenedor de servicios.
Además, se configuran algunas variables más para configurar la autenticación.
{{/* Nginx LDAP authentication enabled */}} {{ $ext_ldap_auth := parseBool (or (first (groupByKeys $containers "Env.LDAP_EXT_AUTH")) "false") }} {{/* User need to be participated in these groups to use service */}} {{ $ldap_add_groups := or (first (groupByKeys $containers "Env.LDAP_EXT_ADD_GROUPS")) "" }} {{/* Use HTML login page or HTTP Basic authentication */}} {{ $ldap_use_login_page := parseBool (or $.Env.LDAP_USE_LOGIN_PAGE "false" ) }}
El bloque principal de adiciones se da a continuación. Se activa solo si se establece la variable ext_ldap_auth
.
Si ldap_use_login_page
establece ldap_use_login_page
la redirección a la página de autenticación; de lo contrario, se utilizará la ventana de autenticación básica HTTP.
La ruta /auth-proxy
es la redirección al servicio de autenticación.
Los parámetros se pasarán a través de los encabezados HTTP.
Qué parámetros y por qué son necesarios se describe en detalle en los comentarios.
Sección LDAP {{ if ($ext_ldap_auth) }}
Finalmente, cuando la autenticación LDAP para el servicio está habilitada, auth_request
agrega a su ubicación:
location / { {{ if ($ext_ldap_auth) }} auth_request /auth-proxy; {{ if ($ldap_use_login_page) }}
La siguiente es una lista completa de la plantilla.
nginx.tmpl {{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }} {{ define "upstream" }} {{ if .Address }} {{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}} {{ if and .Container.Node.ID .Address.HostPort }} # {{ .Container.Node.Name }}/{{ .Container.Name }} server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }}; {{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}} {{ else if .Network }}
DHE-RSA-AES128-GCM-SHA256: DHE-DSS-AES128-GCM-SHA256: kEDH + AESGCM: ECDHE-RSA-AES128-SHA256: ECDHE-ECDSA-AES128-SHA256: ECDHE- {{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }} {{ define "upstream" }} {{ if .Address }} {{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}} {{ if and .Container.Node.ID .Address.HostPort }} # {{ .Container.Node.Name }}/{{ .Container.Name }} server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }}; {{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}} {{ else if .Network }}
Modificación de configuración de Docker-compose
En docker-compose.yml
se agregaron:
- Nuevo servicio "ldap-auth", que se encarga de la autorización.
- Un bloque de variables que configuran las interacciones con el servidor LDAP.
Lo que está escrito en las variables, nginx pasará el servicio de autenticación a través de encabezados HTTP.
El propósito de los parámetros es claro a partir de los nombres de las variables, por lo que no me detendré en ellos.
Vea la configuración completa a continuación.
docker-compose.yml version: '2' networks: internal: docker0: external: name: docker0 services: ldap-auth: image: linuxserver/ldap-auth:latest container_name: ldap-auth networks: - internal - docker0 environment: - TZ=Europe/Moscow expose: - 8888 - 9000 restart: unless-stopped nginx-proxy: depends_on: - ldap-auth networks: - internal - docker0 restart: always image: jwilder/nginx-proxy ports: - "80:80" - "443:443" volumes: - ./certs:/etc/nginx/certs:ro - ./vhost.d:/etc/nginx/vhost.d - ./html:/usr/share/nginx/html - /var/run/docker.sock:/tmp/docker.sock:ro - ./local-config:/etc/nginx/conf.d - ./nginx.tmpl:/app/nginx.tmpl environment: - DEFAULT_HOST=nas.nas - LDAP_BACKEND=ldap-auth #- LDAP_BACKEND_PORT=8888 #- LDAP_LOGIN_PORT=9000 - LDAP_HOST=ldap://172.21.0.1:389 #- LDAP_METHOD=start_tls - LDAP_METHOD=plain - LDAP_UID=uid - LDAP_PASS=LDAP_PASSWORD - LDAP_BASE=ou=users,dc=nas,dc=nas - LDAP_BIND_DN=cn=readonly,dc=nas,dc=nas - LDAP_USER_FILTER=(uid=%(username)s) #- LDAP_USE_LOGIN_PAGE=true labels: - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true" letsencrypt-dns: image: adferrand/letsencrypt-dns restart: always volumes: - ./certs/letsencrypt:/etc/letsencrypt environment: - "LETSENCRYPT_USER_MAIL=MAIL@MAIL.COM" - "LEXICON_PROVIDER=cloudns" - "LEXICON_OPTIONS=--delegated NAS.cloudns.cc" - "LEXICON_PROVIDER_OPTIONS=--auth-id=CLOUDNS_ID --auth-password=CLOUDNS_PASSWORD"
Uso por servicio
La autenticación de extremo a extremo está desactivada de manera predeterminada.
Para habilitarlo, es suficiente establecer las variables en el entorno del contenedor deseado:
LDAP_EXT_AUTH=true
: habilita la autenticación.LDAP_EXT_ADD_GROUPS=(memberOf=cn=users_cloud,ou=groups,dc=nas,dc=nas)
: un filtro opcional, una lista de grupos a los que debe pertenecer el usuario para poder autenticarse. Esto proporciona soporte de autorización.
environment: - LDAP_EXT_AUTH=true - LDAP_EXT_ADD_GROUPS=(memberOf=cn=users_cloud,ou=groups,dc=nas,dc=nas)
Conclusión
En general, la solución ha funcionado durante mucho tiempo y proporciona no solo autenticación, sino también autorización.
Esto le permite utilizar cualquier servicio en contenedores en el NAS, independientemente de si son compatibles con la autenticación a través de LDAP.
Aunque hay algunos problemas:
- HTML ,
ldap_use_login_page
. . — . - . LDAP , , docker-gen .
- , . , , , . .
NAS .