Kunden fragen uns häufig, wie sie mit NGINX Plus und NGINX geschützte Ressourcen oder Anwendungen sichern können, indem sie die Benutzer authentifizieren, die diese anfordern. Heute geben wir eine Referenzimplementierung eines solchen Authentifizierungssystems bekannt und stellen sie im Repository von NGINX, Inc. auf GitHub zur Verfügung . In diesem Beitrag beschreiben wir, wie die Implementierung funktioniert, wie man sie installiert und wie man sie als Modell für Ihr eigenes Authentifizierungssystem verwendet.
Die Lösung nutzt das Modul ngx_http_auth_request_module in NGINX Plus und NGINX, das Authentifizierungsanforderungen an einen externen Dienst weiterleitet. In der Referenzimplementierung ist dieser Dienst ein Daemon, den wir ldap‑auth nennen. Es ist in Python geschrieben und kommuniziert mit einem Lightweight Directory Access Protocol (LDAP)-Authentifizierungsserver – standardmäßig OpenLDAP , aber wir haben den LDAP-Auth-Daemon auch mit Standardkonfigurationen von Microsoft® Windows® Server Active Directory (sowohl Version 2003 als auch Version 2012) getestet.
Der LDAP-Auth-Daemon dient als Modell für Ihre eigene „Connector“-App, die Sie möglicherweise in anderen Sprachen schreiben, mit anderen Authentifizierungssystemen bereitstellen oder beides. Das NGINX Professional Services -Team steht Ihnen bei solchen Anpassungen gerne zur Seite.
Hinweise:
Um die Authentifizierung durchzuführen, sendet das Modul „http_auth_request“ eine HTTP-Unteranforderung an den LDAP-Auth-Daemon, der als Vermittler fungiert und die Unteranforderung für den LDAP-Server interpretiert. Er verwendet HTTP für die Kommunikation mit NGINX Plus und die entsprechende API für die Kommunikation mit dem LDAP-Server.
Wenn Sie an der Referenzimplementierung interessiert sind, gehen wir davon aus, dass Sie bereits über eine Anwendung oder andere Ressourcen verfügen, die Sie durch eine Authentifizierungsanforderung schützen möchten. Um das Testen der Referenzimplementierung zu erleichtern, stellen wir jedoch einen Beispiel-Backend-Daemon bereit, der ebenfalls in Python geschrieben ist und auf Port 9000 lauscht. Es kann beim Testen eine tatsächliche HTTP-Anwendung ersetzen, indem es zur Eingabe der Benutzeranmeldeinformationen auffordert und auf dieser Grundlage ein Cookie erstellt.
Hier finden Sie eine schrittweise Beschreibung des Authentifizierungsprozesses in der Referenzimplementierung. Die Details werden durch Einstellungen in der Konfigurationsdatei nginx-ldap-auth.conf bestimmt, siehe „Konfigurieren der Referenzimplementierung“ weiter unten. Das Flussdiagramm unter den Schritten fasst den Vorgang zusammen.
Ein Client sendet eine HTTP-Anfrage für eine geschützte Ressource, die auf einem Server gehostet wird, für den NGINX Plus als Reverse-Proxy fungiert.
NGINX Plus (insbesondere das Modul http_auth_request) leitet die Anfrage an den LDAP-Auth-Daemon weiter, der mit dem HTTP-Code antwortet401
weil keine Zugangsdaten angegeben wurden.
NGINX Plus leitet die Anfrage an http://backend/login weiter, was dem Backend-Daemon entspricht. Es schreibt die ursprüngliche Anforderungs-URI in den X-Target
-Header der weitergeleiteten Anforderung.
Der Backend-Daemon sendet dem Client ein Anmeldeformular (das Formular ist im Python-Code für den Daemon definiert). Wie in der error_page-
Direktive konfiguriert, setzt NGINX den HTTP-Code im Anmeldeformular auf200
.
Der Benutzer füllt die Felder „Benutzername“ und „Passwort“ im Formular aus und klickt auf die Schaltfläche „Anmelden“. Gemäß dem Code im Formular generiert der Client eine an /login gerichtete HTTP- POST-
Anfrage, die NGINX Plus an den Backend-Daemon weiterleitet.
Der Backend-Daemon erstellt eine Zeichenfolge im Format Benutzername : Passwort
, wendet die Base64-Kodierung an, generiert ein Cookie namens nginxauth , dessen Wert auf die kodierte Zeichenfolge gesetzt ist, und sendet das Cookie an den Client. Es setzt das Flag „httponly“
, um die Verwendung von JavaScript zum Lesen oder Bearbeiten des Cookies zu verhindern (Schutz vor der Cross-Site-Scripting-Sicherheitslücke [XSS] ).
Der Client überträgt seine ursprüngliche Anfrage (aus Schritt 1) erneut und schließt dieses Mal das Cookie in das Cookie-
Feld des HTTP-Headers ein. NGINX Plus leitet die Anfrage an den LDAP-Auth-Daemon weiter (wie in Schritt 2).
Der LDAP-Auth-Daemon dekodiert das Cookie und sendet den Benutzernamen und das Passwort in einer Authentifizierungsanfrage an den LDAP-Server.
Die nächste Aktion hängt davon ab, ob der LDAP-Server den Benutzer erfolgreich authentifiziert:
Wenn die Authentifizierung erfolgreich ist, sendet der LDAP-Auth-Daemon den HTTP-Code200
zu NGINX Plus. NGINX Plus fordert die Ressource vom Backend-Daemon an. In der Referenzimplementierung gibt der Backend-Daemon den folgenden Text zurück:
Hallo Welt! Angeforderte URL: URL
Die Datei nginx-ldap-auth.conf enthält Anweisungen zum Zwischenspeichern der Ergebnisse des Authentifizierungsversuchs. Informationen zum Deaktivieren des Zwischenspeicherns finden Sie weiter unten unter „Zwischenspeichern“ .
Wenn die Authentifizierung fehlschlägt, sendet der LDAP-Auth-Daemon den HTTP-Code401
zu NGINX Plus. NGINX Plus leitet die Anforderung erneut an den Backend-Daemon weiter (wie in Schritt 3) und der Vorgang wiederholt sich.
Die mit der Referenzimplementierung verteilte NGINX Plus-Konfigurationsdatei nginx-ldap-auth.conf konfiguriert alle Komponenten außer dem LDAP-Server (also NGINX Plus, den Client, den LDAP-Auth-Daemon und den Backend-Daemon) so, dass sie auf demselben Host ausgeführt werden, was für Testzwecke ausreichend ist. Der LDAP-Server kann während des Tests auch auf diesem Host ausgeführt werden.
Bei einer tatsächlichen Bereitstellung werden die Back-End-Anwendung und der Authentifizierungsserver normalerweise jeweils auf einem separaten Host ausgeführt, wobei NGINX Plus auf einem dritten Host ausgeführt wird. Der LDAP-Auth-Daemon verbraucht in den meisten Situationen nicht viele Ressourcen und kann daher auf dem NGINX-Plus-Host oder einem anderen Host Ihrer Wahl ausgeführt werden.
Erstellen Sie einen Klon des GitHub-Repository .
Wenn NGINX Plus noch nicht ausgeführt wird, installieren Sie es gemäß den Anweisungen für Ihr Betriebssystem.
Wenn noch kein LDAP-Server ausgeführt wird, installieren und konfigurieren Sie einen. Standardmäßig kommuniziert der LDAP-Auth-Daemon mit OpenLDAP, aber auch Microsoft Windows Active Directory 2003 und 2012 werden unterstützt.
Wenn Sie den LDAP-Server nur zum Testen der Referenzimplementierung verwenden, können Sie das auf GitHub verfügbare Docker-Image des OpenLDAP-Servers verwenden oder einen Server mithilfe von Anweisungen wie „So installieren und konfigurieren Sie OpenLDAP und phpLDAPadmin unter Ubuntu 16.04“ einrichten.
Notieren Sie sich die Werte, die Sie für Basis-DN, Bind-DN und Bind-Passwort festgelegt haben. Sie werden sie in die NGINX-Konfigurationsdatei unter „Konfigurieren der Referenzimplementierung“ einfügen.
Installieren Sie auf dem Host, auf dem der LDAP-Auth-Daemon ausgeführt werden soll, die folgende zusätzliche Software. Wir empfehlen, die mit dem Betriebssystem verteilten Versionen zu verwenden, anstatt die Software aus einem Open-Source-Repository herunterzuladen.
Kopieren Sie die folgenden Dateien von Ihrem Repository-Klon auf die angegebenen Hosts:
Ändern Sie die NGINX Plus-Konfigurationsdatei wie unten unter „Konfigurieren der Referenzimplementierung“ beschrieben. Führen Sie nach dem Vornehmen Ihrer Änderungen den Befehl nginx
-t
aus, um zu überprüfen, ob die Datei syntaktisch gültig ist.
root# nginx -t nginx: die Syntax der Konfigurationsdatei /etc/nginx/nginx.conf ist in Ordnung nginx: der Test der Konfigurationsdatei /etc/nginx/nginx.conf war erfolgreich
Starten Sie NGINX Plus. Wenn NGINX Plus bereits ausgeführt wird, führen Sie den folgenden Befehl aus, um die Konfigurationsdatei neu zu laden:
root# nginx -s neu laden
Führen Sie die folgenden Befehle auf den entsprechenden Hosts aus, um den LDAP-Auth-Daemon und den Backend-Daemon zu starten.
root# nginx-ldap-auth-daemon-ctl.sh starte root# python backend-sample-app.py
Verwenden Sie einen Webbrowser, um auf http:// nginx-server-address :8081 zuzugreifen. Überprüfen Sie, ob der Browser das Authentifizierungsformular anzeigt. Nachdem Sie das Formular ausgefüllt und übermittelt haben, überprüfen Sie, ob der Server die erwartete Antwort auf gültige Anmeldeinformationen zurückgibt. Wie oben erwähnt, gibt der Backend-Daemon den folgenden Text zurück:
Hallo Welt! Angeforderte URL: URL
Nehmen Sie die folgenden Änderungen in der Datei nginx-ldap-auth.conf vor. Einige sind erforderlich und einige optional, wie angegeben.
Wie in nginx-ldap-auth-daemon.py implementiert, kommuniziert der LDAP-Auth-Daemon mit einem OpenLDAP-Server und übergibt Parameter, um anzugeben, welches Benutzerkonto authentifiziert werden soll. Damit der Python-Code nicht geändert werden muss, enthält die Datei nginx-ldap-auth.conf proxy_set_header-
Direktiven, die Werte im HTTP-Header festlegen, die dann zum Festlegen der Parameter verwendet werden. In der folgenden Tabelle sind die Parameter und Header abgebildet.
LDAP-Parameter | HTTP-Header |
---|---|
basierend |
X-Ldap-BaseDN |
bindn |
X-Ldap-BindDN |
bindpasswd |
X-Ldap-BindPass |
Cookie-Name |
X-CookieName |
Reich |
X-Ldap-Bereich |
Vorlage |
X-Ldap-Vorlage |
URL (URL) |
X-LDAP-URL |
(Erforderlich) Ersetzen Sie in den folgenden Anweisungen die fettgedruckten Werte durch die richtigen Werte für Ihre LDAP-Serverbereitstellung. Beachten Sie insbesondere, dass die Datei nginx-ldap-auth.conf den bekannten Port für LDAPS, 636, verwendet. Wenn Sie den Port auf 389 (den bekannten Port für LDAP) oder einen anderen LDAP-Port ändern, denken Sie daran, auch den Protokollnamen von ldaps
in ldap
zu ändern.
# URL und Port für die Verbindung zum LDAP-Server proxy_set_header X-Ldap-URL " ldaps :// example.com :636 "; # Basis-DN proxy_set_header X-Ldap-BaseDN " cn=Users,dc=test,dc=local "; # Bind-DN proxy_set_header X-Ldap-BindDN " cn=root,dc=test,dc=local "; # Bind-Passwort proxy_set_header X-Ldap-BindPass " secret ";
(Erforderlich, wenn Active Directory statt OpenLDAP verwendet wird) Entfernen Sie die Kommentarzeichen aus der folgenden Anweisung wie gezeigt:
proxy_set_header X-Ldap-Template "(SAMAccountName=%(Benutzername)s)";
(Optional) Die Referenzimplementierung verwendet eine cookiebasierte Authentifizierung. Wenn Sie stattdessen die HTTP-Basisauthentifizierung verwenden, kommentieren Sie die folgenden Anweisungen wie gezeigt aus:
# proxy_set_header X-CookieName "nginxauth"; # proxy_set_header Cookie nginxauth=$cookie_nginxauth;
(Optional) Wenn Sie den Wert für den Vorlagenparameter
ändern möchten, den der LDAP-Auth-Daemon standardmäßig an den OpenLDAP-Server übergibt, heben Sie wie gezeigt die Kommentierung der folgenden Anweisung auf und ändern Sie den Wert:
proxy_set_header X-Ldap-Vorlage " (cn=%(Benutzername)s) ";
(Optional) Wenn Sie den Realm-Namen vom Standardwert ( Restricted ) ändern möchten, heben Sie die Auskommentierung auf und ändern Sie die folgende Anweisung:
proxy_set_header X-Ldap-Realm " Eingeschränkt ";
Wenn der Backend-Daemon nicht auf demselben Host wie NGINX Plus ausgeführt wird, ändern Sie die IP-Adresse dafür im Upstream-
Konfigurationsblock:
Upstream-Backend { Server127.0.0.1 :9000; }
Wenn der LDAP-Auth-Daemon nicht auf demselben Host wie NGINX Plus ausgeführt wird, ändern Sie die IP-Adresse in dieser Proxy_pass-
Direktive:
Standort = /auth-proxy { Proxy-Passwort http://127.0.0.1 :8888; # ... }
Wenn der Client nicht auf demselben Host wie NGINX Plus ausgeführt wird, ändern Sie die IP-Adresse in dieser Abhördirektive
(oder entfernen Sie die Adresse vollständig, um Datenverkehr von jedem Client zu akzeptieren). Sie können den Port, auf dem NGINX lauscht, auch von 8081 ändern, wenn Sie möchten:
Server { hören127.0.0.1 :8081 ; # ... }
Die Datei nginx-ldap-auth.conf ermöglicht das Zwischenspeichern von Daten und Anmeldeinformationen. Optional können Sie folgende Einstellungen ändern:
Die Direktive proxy_cache_path
im http-
Konfigurationsblock erstellt ein lokales Festplattenverzeichnis namens cache und reserviert 10 MB im gemeinsam genutzten Speicher für eine Zone namens auth_cache , in der Metadaten gespeichert werden.
Proxy-Cache- Pfad Cache/ Schlüsselzone= Auth-Cache : 10 m ;
Wenn Sie den Namen der gemeinsam genutzten Speicherzone ändern, müssen Sie ihn auch in der Proxy_Cache-
Direktive ändern (im Standortblock
, der den Datenverkehr an den LDAP-Auth-Daemon weiterleitet).
Standort = /auth-proxy { Proxy-Cache Auth -Cache ; # …}
Die Direktive proxy_cache_valid
(im selben Location-
Block wie proxy_cache
) gibt an, dass zwischengespeicherte Antworten, die mit HTTP-Code markiert sind,200
oder403
sind 10 Minuten gültig.
Standort = /auth-proxy { Proxy-Cache_valid 200 403 10m ; # ... }
Um das Caching zu deaktivieren, kommentieren Sie diese drei Anweisungen sowie die Anweisung proxy_cache_key
aus.
Wie oben erwähnt, können Sie den LDAP-Auth-Daemon als Modell für Ihre eigene Anwendung verwenden, die Anfragen vom Modul http_auth_request akzeptiert. Wenn Sie eine App in Python schreiben, um mit einem anderen (nicht LDAP‑) Authentifizierungsservertyp zu kommunizieren, schreiben Sie eine neue Authentifizierungshandlerklasse, um LDAPAuthHandler
im Skript nginx‑ldap‑auth-daemon.py zu ersetzen.
Der Backend-Daemon verwendet die Base64-Kodierung für den Benutzernamen und das Passwort im Cookie. Base64 ist eine sehr schwache Form der Verschlüsselung, wodurch die Anmeldeinformationen anfällig für Diebstahl und Missbrauch sind. Damit die Authentifizierung einen wirklichen Zweck erfüllt, müssen Sie in Ihrer Backend-Anwendung eine ausgefeiltere Verschlüsselung verwenden.
„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."