
Eines der lästigen Probleme, die beim Erstellen eines NAS auftreten, ist, dass nicht alle Software mit LDAP arbeiten kann und einige keine Authentifizierungsmechanismen enthalten.
Die Lösung ist die End-to-End-Authentifizierung über einen Reverse-Proxy.
Ein Beispiel dafür wird beispielsweise in diesem Artikel ausführlich beschrieben .
Da dieser Artikel Teil des NAS-Zyklus ist ,
Hier werde ich mich darauf konzentrieren, wie diese Lösung an Dienste in Docker-Containern angepasst werden kann.
Die Lösung basiert auf dem Beispiel der Implementierung der Authentifizierung über einen externen Nginx LDAP Auth- Agenten. Ich verwende jedoch die containerisierte Version von LinuxServer.io, da es sich um ein fertiges Image handelt, das bestimmte Standards erfüllt.
Das einzige Problem war, dass die LinuxServer.io-Patches die grundlegende HTTP-Authentifizierung brachen, aber nachdem der Bugfix hochgeladen wurde , wurde es möglich, diese wieder zu verwenden.
Allgemeine Authentifizierung
Wie in den Artikeln gezeigt, wird die Authentifizierung wie folgt durchgeführt:
- Der Client greift auf den Dienst zu.
- Der Reverse-Proxy leitet um, wenn ein Cookie gesetzt ist.
- Wenn kein Cookie vorhanden ist, wird eine Anfrage an den Authentifizierungsdienst gestellt.
- Der Authentifizierungsdienst fordert einen Benutzernamen und ein Kennwort an, die er durch Zugriff auf den LDAP-Server überprüft.
- Wenn die Überprüfung erfolgreich ist, wird ein Cookie gesetzt und an den Dienst weitergeleitet.

Eine alternative Option könnte darin bestehen, ein kompiliertes Modul für Nginx zu verwenden, aber ich werde diese Option hier aufgrund einiger Probleme mit diesem Modul und seiner geringeren Flexibilität nicht berücksichtigen.
Ein modifiziertes Image für den OpenLDAP-Server finden Sie hier .
Containerauthentifizierung
Innerhalb von NAS arbeiten Dienste in Containern, daher besteht der Wunsch, dies so zu gestalten, dass der Authentifizierungsmodus durch einfaches Festlegen der Variablen im Container geändert werden kann.
Ein solcher Mechanismus ist bereits im verwendeten ngingx-Proxy-Image enthalten und wird durch Vorlagen implementiert, die Docker-Gen- Prozesse ausführen .
Es fügt Metadaten in die Vorlage ein, die eine Beschreibung der aktuell ausgeführten Docker-Container enthält.
Daher muss lediglich die Reverse-Proxy-Konfigurationsvorlage so verfeinert werden, dass bei einer bedingten Variablen im Container die Umleitung zum End-to-End-Authentifizierungsdienst enthalten ist, der auch im Container funktioniert.
Nehmen Sie dann die entsprechenden Anpassungen an der Docker-Compose-Konfiguration vor.
Implementierung der Authentifizierung
Änderung der Nginx-Proxy-Konfigurationsvorlage
Zunächst wird ein neuer Upstream hinzugefügt, mit dem Sie in der Konfiguration auf den Authentifizierungsdienst zugreifen können:
proxy_cache_path cache/ keys_zone=auth_cache:10m; upstream ldap-backend { server {{ $.Env.LDAP_BACKEND }}:{{ or $.Env.LDAP_LOGIN_PORT "9000" }}; }
Es ist ersichtlich, dass der Authentifizierungsdienst auf Host ${LDAP_BACKEND}
und Port ${LDAP_LOGIN_PORT }
wird. Der Standardwert ist 9000.
Die Werte der Variablen werden durch Docker-Gen ersetzt, sodass dieser Teil der Konfiguration in /etc/nginx/conf.d/default.conf
im Container folgendermaßen /etc/nginx/conf.d/default.conf
:
Der folgende Zusatz legt die Variable ext_ldap_auth
, wenn die Variable LDAP_EXT_AUTH in einem bestimmten Dienstcontainer gespannt wurde.
Außerdem werden einige weitere Variablen festgelegt, um die Authentifizierung zu konfigurieren.
{{/* 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" ) }}
Der Hauptblock der Ergänzungen ist unten angegeben. Es wird nur aktiviert, wenn die Variable ext_ldap_auth
.
Wenn ldap_use_login_page
, wird die Umleitung zur Authentifizierungsseite aktiviert, andernfalls wird das HTTP-Basisauthentifizierungsfenster verwendet.
Der Pfad /auth-proxy
ist die Umleitung zum Authentifizierungsdienst.
Parameter werden über HTTP-Header übergeben.
Welche Parameter und warum benötigt werden, wird in den Kommentaren ausführlich beschrieben.
LDAP-Abschnitt {{ if ($ext_ldap_auth) }}
Wenn die LDAP-Authentifizierung für den Dienst aktiviert ist, wird auth_request
an seinem Speicherort hinzugefügt:
location / { {{ if ($ext_ldap_auth) }} auth_request /auth-proxy; {{ if ($ldap_use_login_page) }}
Das Folgende ist eine vollständige Liste der Vorlage.
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 }}
GCM-SHA256: ECDHE-RSA-AES128-GCM-SHA256: ECDHE-ECDSA-AES128-SHA256: ECDHE-RSA-AES128-SHA256: ECDHE-ECDSA-AES128-SHA: ECDHE-RSA- {{ $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 }}
GCM-SHA256: ECDHE-RSA-AES128-GCM-SHA256: ECDHE-ECDSA-AES128-SHA256: ECDHE-RSA-AES128-SHA256: ECDHE-ECDSA-AES128-SHA: ECDHE-RSA- {{ $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 }}
Konfigurationsänderung von Docker-Compose
In docker-compose.yml
wurden hinzugefügt:
- Neuer Dienst "ldap-auth", der für die Autorisierung verantwortlich ist.
- Ein Block von Variablen, die Interaktionen mit dem LDAP-Server konfigurieren.
Was in den Variablen geschrieben ist, leitet nginx den Authentifizierungsdienst über HTTP-Header weiter.
Der Zweck der Parameter ergibt sich aus den Variablennamen, daher werde ich nicht weiter darauf eingehen.
Siehe die vollständige Konfiguration unten.
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"
Verwendung durch Service
Die End-to-End-Authentifizierung ist standardmäßig deaktiviert.
Um es zu aktivieren, reicht es aus, die Variablen in der Umgebung des gewünschten Containers festzulegen:
LDAP_EXT_AUTH=true
- Authentifizierung aktivieren.LDAP_EXT_ADD_GROUPS=(memberOf=cn=users_cloud,ou=groups,dc=nas,dc=nas)
- ein optionaler Filter, eine Liste von Gruppen, bei denen der Benutzer Mitglied sein muss, um authentifiziert zu werden. Dies bietet Autorisierungsunterstützung.
environment: - LDAP_EXT_AUTH=true - LDAP_EXT_ADD_GROUPS=(memberOf=cn=users_cloud,ou=groups,dc=nas,dc=nas)
Fazit
Im Allgemeinen funktioniert die Lösung seit langem und bietet nicht nur Authentifizierung, sondern auch Autorisierung.
Auf diese Weise können Sie alle Dienste in Containern im NAS verwenden, unabhängig davon, ob sie die Authentifizierung über LDAP unterstützen.
Obwohl es einige Probleme gibt:
- HTML ,
ldap_use_login_page
. . — . - . LDAP , , docker-gen .
- , . , , , . .
NAS .