
创建NAS时出现的烦人问题之一是,并非所有软件都可以使用LDAP,并且某些软件不包含身份验证机制。
解决方案是通过反向代理进行端到端身份验证。
例如,在本文中详细讨论了如何执行此操作的示例。
由于本文是NAS周期的一部分,
在这里,我将重点介绍如何使该解决方案适应Docker容器中的服务。
该解决方案基于通过外部Nginx LDAP Auth代理实现身份验证的示例,但是我使用LinuxServer.io的容器化版本,因为它是符合某些标准的现成映像。
唯一的问题是LinuxServer.io补丁破坏了基本的HTTP身份验证,但是在错误修正上传后 ,便可以再次使用它。
通用认证
如文章中所示,认证的执行方式如下:
- 客户端访问服务。
- 如果设置了cookie,则反向代理将重定向。
- 如果没有cookie,则会向身份验证服务发出请求。
- 身份验证服务请求用户名和密码,并通过访问LDAP服务器进行验证。
- 如果验证成功,它将设置一个cookie并重定向到该服务。

一种替代方法是对nginx使用已编译的模块,但是由于该模块存在一些问题且灵活性较差,因此我在这里不考虑此选项。
OpenLDAP服务器的修改后的映像在此处 。
容器认证
在NAS内部,服务在容器中工作,因此希望通过简单地在容器内设置变量来切换身份验证模式。
这样的机制已经在使用的ngingx-proxy映像中,并且通过docker -gen进程的模板来实现。
它将元数据插入包含当前运行的Docker容器描述的模板中。
因此,所有需要做的就是完善反向代理配置模板,以便在容器中存在条件变量的情况下,包括重定向到也在容器中起作用的端到端身份验证服务。
然后,对docker-compose配置进行适当的调整。
认证实施
修改nginx-proxy配置模板
首先,添加了一个新的上游,使您可以在配置中访问身份验证服务:
proxy_cache_path cache/ keys_zone=auth_cache:10m; upstream ldap-backend { server {{ $.Env.LDAP_BACKEND }}:{{ or $.Env.LDAP_LOGIN_PORT "9000" }}; }
可以看出,身份验证服务在主机${LDAP_BACKEND}
和端口${LDAP_LOGIN_PORT }
,默认值为9000。
变量的值将被docker-gen替换,以便配置的这一部分在容器内的/etc/nginx/conf.d/default.conf
看起来像这样:
如果LDAP_EXT_AUTH变量被锁定在某个服务容器中,则以下添加项将设置ext_ldap_auth
变量。
此外,还设置了一些其他变量来配置身份验证。
{{/* 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" ) }}
主要增加的功能如下。 仅当ext_ldap_auth
了ext_ldap_auth
变量时才激活它。
如果设置了ldap_use_login_page
,则将启用到身份验证页面的重定向,否则将使用HTTP基本身份验证窗口。
路径/auth-proxy
是到身份验证服务的重定向。
参数将通过HTTP标头传递。
注释中详细描述了哪些参数以及为什么需要。
LDAP部分 {{ if ($ext_ldap_auth) }}
最后,启用服务的LDAP身份验证后, auth_request
添加到其位置:
location / { {{ if ($ext_ldap_auth) }} auth_request /auth-proxy; {{ if ($ldap_use_login_page) }}
以下是模板的完整列表。
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 }}
Docker-compose配置修改
在docker-compose.yml
中添加了:
- 新服务“ ldap-auth”,负责授权。
- 一组变量,用于配置与LDAP服务器的交互。
变量中写入的内容是,nginx将通过HTTP标头传递身份验证服务。
从变量名可以清楚地看到参数的用途,因此我不再赘述。
请参阅下面的完整配置。
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"
按服务使用
默认情况下,端到端身份验证处于关闭状态。
要启用它,只需在所需容器的环境中设置变量即可:
LDAP_EXT_AUTH=true
启用身份验证。LDAP_EXT_ADD_GROUPS=(memberOf=cn=users_cloud,ou=groups,dc=nas,dc=nas)
-可选过滤器,用户必须是要进行身份验证的组的列表。 这提供了授权支持。
environment: - LDAP_EXT_AUTH=true - LDAP_EXT_ADD_GROUPS=(memberOf=cn=users_cloud,ou=groups,dc=nas,dc=nas)
结论
通常,该解决方案已经使用了很长时间,不仅提供身份验证,还提供授权。
这使您可以使用NAS容器中的任何服务,而无论它们是否支持通过LDAP进行身份验证。
尽管存在一些问题:
- HTML ,
ldap_use_login_page
. . — . - . LDAP , , docker-gen .
- , . , , , . .
NAS .