LDAP ist eine ganz normale Sache in der IT-Welt, obwohl es nicht so bequem ist wie OAuth oder OpenID Connect. Trotzdem wird es immer noch weitgehend genutzt. Darum lohnt es sich, etwas Erfahrung mit LDAP zu sammeln. In diesem Artikel zeige ich euch, wie man eine Webseite mit Active-Directory- oder LDAP-Authentifizierung auf einem Nginx-Server schützen kann.
Ihr könnt das fertige Projekt hier herunterladen/klonen:
github.com/ppabis/nginx-ldap-simplead.
Erstes Verzeichnis
Um LDAP mit Nginx zu verwenden, brauchen wir zuerst einen Verzeichnisserver. Amazons Simple AD ist eine gute Wahl für unseren Prototyp. Es ist günstig und einfach zu konfigurieren. Ich habe ein neues Terraform-Projekt erstellt, um einen Verzeichnisserver zu starten.
Erstens, macht ein neues OpenTofu-Projekt mit diesem Provider. Wählt eure Region ebenfalls aus. Für die Authentifizierung könnt ihr entweder Umgebungsvariablen oder die AWS CLI-Konfiguration verwenden.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">=5.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.0"
}
}
}
provider "aws" {
region = "eu-west-1" # Achte auf Region, nicht alle Regionen unterstützen Simple AD
}
Wir brauchen auch eine VPC. Wir können die Standard-VPC benutzen, aber für eine bessere Kontrolle empfehle ich euch, eine neue VPC zu erstellen. Ich werde ein Modul benutzen, sodass es einfacher und schneller zu schreiben ist. In einer neuen Datei vpc.tf
schreibt:
module "vpc" {
source = "aws-ia/vpc/aws"
version = ">= 4.2.0"
name = "mein-ldap-vpc"
cidr_block = "10.10.0.0/16" # oder eure IP-Cidr Wahl
az_count = 2
subnets = {
public = { netmask = 24 }
private = { netmask = 24 }
}
}
Dieser Code baut eine neue VPC mit zwei öffentlichen Subnets und zwei privaten Subnets auf. Die öffentlichen Subnets haben natürlich Zugriff auf das Internet über ein Internet Gateway. Um diesen Code auszuführen, schreibt in eurer Konsole:
$ tofu init # oder terraform falls euch nutzt Terraform
$ tofu apply
Danach können wir das Simple-AD-Verzeichnis erstellen. Das Passwort kann von einer “random_string”-Ressource generiert werden. Wir werden darauf als Output zugreifen. Ihr müsst euch auch einen Domänennamen ausdenken. Hier habe ich auth.company.internal
ausgewählt. Schreibt diesen Terraform-Code.
resource "random_password" "directory_password" {
length = 20
special = true
override_special = "-_.!"
min_special = 2
min_upper = 2
min_lower = 2
min_numeric = 2
}
resource "aws_directory_service_directory" "simple_ad" {
name = "auth.company.internal" # richtige DNS-Name
password = random_password.directory_password.result
size = "Small"
type = "SimpleAD"
vpc_settings {
vpc_id = module.vpc.vpc_attributes.id
subnet_ids = slice([for _, subnet in module.vpc.private_subnet_attributes_by_az : subnet.id], 0, 2)
}
tags = { Name = "simple-ad" }
}
output "ldap_password" {
value = random_password.directory_password.result
sensitive = true
}
Um das Passwort zu sehen, könnt ihr tofu output
oder terraform output
ausführen. Das ist ein Passwort für den Administrator-Benutzer. Wir brauchen es, um dieses Verzeichnis zu verwalten.
$ tofu output ldap_password
Windows Instance für Verzeichnis-Management
Um Gruppen und Benutzer anzulegen, müssen wir Windows benutzen. In diesem Schritt werden wir in Terraform nur die Sicherheitsgruppe und die IAM-Rolle erstellen. Danach starten wir unsere EC2-Instanz über die AWS-Konsole. Es wäre dort viel einfacher, sich mit der Domäne zu verbinden. Wir brauchen diese Instanz nur für die Verwaltung des Verzeichnisses. Ihr könnt auch ein neues Schlüsselpaar generieren. Um das zu schaffen, brauchen wir noch einen Provider – nämlich hashicorp/tls
.
terraform {
required_providers {
... # aws und random
tls = {
source = "hashicorp/tls"
version = "~> 4.0"
}
}
}
Jetzt können wir die IAM-Rolle und das Profil vorbereiten. Diese Rolle muss mit zwei Richtlinien verbunden sein: AmazonSSMManagedInstanceCore
und AmazonSSMDirectoryServiceAccess
. AWS erlaubt die Verbindung zwischen einer Maschine und dem Verzeichnis nur mit diesen Berechtigungen.
# IAM-Rolle
resource "aws_iam_role" "windows_domain_rolle" {
name = "WindowsDomainRolle"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [ {
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = { Service = "ec2.amazonaws.com" }
} ]
})
}
# Instanz-Profil
resource "aws_iam_instance_profile" "windows_domain_profil" {
name = "WindowsDomainProfil"
role = aws_iam_role.windows_domain_rolle.name
}
# Berechtigungen
resource "aws_iam_role_policy_attachment" "ssm_managed_instance" {
role = aws_iam_role.windows_domain_rolle.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
resource "aws_iam_role_policy_attachment" "directory_service_access" {
role = aws_iam_role.windows_domain_rolle.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMDirectoryServiceAccess"
}
Dann erstellen wir eine Sicherheitsgruppe, die uns erlaubt, mit der Instanz per Remote Desktop zu verbinden. Sei vorsichtig mit dem CIDR-Block – ihr solltet eure eigene IP-Adresse hier einfügen.
# Sicherheitsgruppe
resource "aws_security_group" "rdp" {
name = "rdp-access"
description = "Zugang mit RDP zu der Instance"
vpc_id = module.vpc.vpc_attributes.id
ingress {
description = "RDP from specified CIDR"
from_port = 3389
to_port = 3389
protocol = "tcp"
cidr_blocks = ["89.19.0.0/16"] # Mach es eure IP-Subnetz!
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
Und schließlich generieren wir ein Schlüsselpaar. Der private Schlüssel lässt uns das Passwort des Administrator-Benutzers der Instanz entschlüsseln. Dieses Passwort ist nicht notwendig, außer wenn etwas mit der Instanz schiefgeht. Für das Management des Verzeichnisses werden wir den Administrator-Benutzer des LDAP-Servers benutzen.
resource "tls_private_key" "windows_key" {
algorithm = "RSA"
rsa_bits = 2048
}
resource "aws_key_pair" "windows_key" {
key_name = "windows-key"
public_key = tls_private_key.windows_key.public_key_openssh
}
output "windows_private_key" {
value = tls_private_key.windows_key.private_key_pem
sensitive = true
}
Alle diese drei Teile – die Rolle, die Sicherheitsgruppe und das Schlüsselpaar – brauchen wir nur vorläufig. Wir werden sie später löschen. Jetzt können wir eine neue EC2-Instanz starten. Geht zur AWS-Konsole, wählt EC2 und „Instances starten“. Wählt „Windows Server 2025 Base“ als Betriebssystembild aus. Als Instanztyp empfehle ich mindestens t3.small, aber etwas Größeres macht alles bequemer. Im nächsten Schritt wählt euer Schlüsselpaar aus. In den Netzwerkeinstellungen klickt auf „Bearbeiten“, wählt die erwähnte VPC, das öffentliche Subnetz und die Sicherheitsgruppe. Aktiviert auch die automatische Zuweisung einer öffentlichen IP.
In den erweiterten Details am Ende der Seite müsst ihr auch noch zwei Einstellungen ändern. Wählt eure Domäne, um euch zu verbinden, und das IAM-Profil mit den Namen, die ihr zuvor im Terraform-Code gewählt hattet.
Remote Desktop Verbindung
Es kann dauern, bis die Instanz bereit ist. Die Domänen-Verbindung kann ebenfalls bis zu fünf Minuten dauern. Falls euer aktuelles Betriebssystem Windows ist, könnt ihr einfach Remote Desktop im Startmenü suchen. Für Linux empfehle ich Remmina und für Mac Microsoft Remote Desktop. Da ich einen Mac habe, sind die folgenden Screenshots von Microsoft Remote Desktop. Man kann es hier herunterladen. Die Beta-Version heißt aktuell "Windows App".
Zuerst erstellt ihr einen neuen PC. Wählt die Option, um ein neues Konto hinzuzufügen. Gebt das Passwort des Verzeichnis-Administrators ein. Als Benutzernamen verwendet ihr Administrator
, gefolgt von einem Klammeraffen und dem Namen eurer Domäne, z. B. administrator@auth.company.internal
. Kopiert den öffentlichen IPv4-DNS von der AWS-Konsole und fügt ihn in das Feld "PC-Name" ein.
Wenn ihr euch eingeloggt habt, öffnet das Startmenü und dann den "Server Manager". Es kann etwas dauern, bis er bereit ist, um fortzufahren. Anschließend klickt auf "Add roles and features", lasst alles wie es ist, und klickt auf "Next", bis ihr zu "Features" kommt. Sucht in der Liste nach "AD DS and AD LDS Tools" sowie "DNS Server Tools". Klickt auf "Next" und dann auf "Install". Wartet, bis alle Werkzeuge installiert sind. Nachdem alles fertig ist, sucht im Startmenü nach "Active Directory Users and Computers".
Öffnet die App und klickt mit der rechten Maustaste auf "Users". Wählt "New" und dann "User". Gebt ein neues Passwort ein. Vergesst nicht, die Option zu markieren, dass das Passwort nie abläuft. Erstellt mindestens zwei Benutzer für diese Übung. Anschließend öffnet ihr die Eigenschaften der beiden Benutzer und aktiviert die Option, das Konto zu entsperren. Jetzt erstellt ihr eine neue Gruppe. Klickt mit der rechten Maustaste auf den Benutzer und wählt die Option, ihn zur Gruppe hinzuzufügen. Gebt euren Gruppennamen ein und klickt auf "Check Names", um den Namen zu überprüfen. Fügt den anderen Benutzer nicht hinzu! Prüft die Eigenschaften der Gruppe, um sicherzustellen, dass der Benutzer wirklich in der Gruppe ist.
Web Instanz Vorbereitung
Wir werden unseren Nginx auf Docker laufen lassen, aber nicht auf ECS oder Kubernetes. Ich möchte es einfach halten, darum werden wir Docker auf einer EC2-Instanz installieren. Wir werden auch Docker Compose verwenden, weil Nginx mit LDAP einen Sidecar-Container mit einem speziellen LDAP-Daemon benötigt. Aber zuerst brauchen wir eine EC2-Instanz. Ich habe mich für Amazon Linux 2023 entschieden. Schreibe in einer neuen Datei in deinem Terraform/OpenTofu-Projekt:
data "aws_ssm_parameter" "amazon_linux_2023" {
name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64"
}
module "instance_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "5.3.0"
name = "instance-sg"
vpc_id = module.vpc.vpc_attributes.id
description = "Die Sicherheitsgruppe für die Nginx-Instanz"
ingress_rules = ["ssh-tcp", "http-80-tcp", "https-443-tcp"]
ingress_cidr_blocks = ["0.0.0.0/0"]
egress_rules = ["all-all"]
}
resource "aws_key_pair" "instance_key" {
key_name = "ldap-instance-key"
public_key = file("~/.ssh/id_rsa.pub")
}
resource "aws_iam_role" "instance_role" {
name = "ldap-instance-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [ {
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = { Service = "ec2.amazonaws.com" }
} ]
})
}
resource "aws_iam_role_policy_attachment" "ssm_policy" {
role = aws_iam_role.instance_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
resource "aws_iam_instance_profile" "instance_profile" {
name = "ldap-instance-profile"
role = aws_iam_role.instance_role.name
}
resource "aws_instance" "ldap_web" {
ami = data.aws_ssm_parameter.amazon_linux_2023.value
instance_type = "t4g.nano"
subnet_id = [for _, subnet in module.vpc.public_subnet_attributes_by_az : subnet.id][0]
key_name = aws_key_pair.instance_key.key_name
associate_public_ip_address = true
vpc_security_group_ids = [module.instance_sg.security_group_id]
iam_instance_profile = aws_iam_instance_profile.instance_profile.name
tags = { Name = "web-instance" }
lifecycle { ignore_changes = [ami] }
}
Falls ihr die Instanz mit dem Systems Manager verbinden möchtet, könnt ihr kein Schlüsselpaar angeben. Hier nutze ich es, damit ich mich per SSH verbinden kann. Meldet euch bei der Instanz an und installiert Docker und Docker Compose. Mit dem folgenden Kommando könnt ihr Docker und Compose auf Amazon Linux 2023 installieren.
$ sudo yum install docker git -y
$ sudo systemctl enable --now docker
$ # Achtung: du brauchts IPv4 um etwas von GitHub zu herunterladen
$ sudo curl -L \
"https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo usermod -aG docker $(whoami) # Verbinde dich zur Instanz nochmals
AD Server Attributen speichern und teilen
Um die erfolgreiche Verbindung zwischen Nginx und LDAP zu erreichen, brauchen wir alle notwendigen Attribute des Verzeichnisses, z. B. die IP-Adresse und das Passwort. Da unsere Instanz durch die IAM-Rolle die Erlaubnis hat, die Parameter von Systems Manager zu lesen, können wir dort die Attribute speichern. Weil es einfach ist, das in Terraform umzusetzen, benötigen wir auch eine Datenquelle des gleichen Directory-Service-Verzeichnisses, da nicht alle Attribute der Ressource enthalten sind – nämlich die DNS-IP-Adresse.
resource "aws_ssm_parameter" "ad_admin_password" {
name = "/nginx-ldap/ad-admin-password"
type = "SecureString"
value = random_password.directory_password.result
}
resource "aws_ssm_parameter" "ad_server_name" {
name = "/nginx-ldap/ad-server-name"
type = "String"
value = aws_directory_service_directory.simple_ad.name
}
data "aws_directory_service_directory" "simple_ad" {
directory_id = aws_directory_service_directory.simple_ad.id
}
resource "aws_ssm_parameter" "ad_dns_ip" {
name = "/nginx-ldap/ad-dns-ip"
type = "String"
value = tolist(data.aws_directory_service_directory.simple_ad.dns_ip_addresses)[0]
}
Alle diese Werte könnt ihr mit der AWS-CLI abrufen. Später bereiten wir ein neues Startskript vor, das alle diese Werte in Umgebungsvariablen speichert und den Docker-Compose-Stack startet.
LDAP Server Konfiguration
Jetzt können wir den LDAP-Daemon für Nginx konfigurieren. Ich habe ein Projekt auf GitHub gefunden und geforkt, sodass es mit dem SimpleAD-Verzeichnis nutzbar ist. Ihr findet es hier: ppabis/nginx-ldap-auth-service. Ihr müsst dieses Projekt auf eure Instanz klonen. Dann könnt ihr die Docker-Compose-Datei hinzufügen und die Vorgaben festlegen, um das Projekt zu bauen. In dieser Datei richten wir auch ein neues Netzwerk ein. Alle Umgebungsvariablen sind noch nicht definiert. Bevor wir den Stack starten, müssen wir sie vom Systems Manager abrufen. Docker Compose wird in der Datei docker-compose.yml
erstellt. Als Ordner benutze ich /opt/ldap
. Dort müsst ihr auch das Projekt aus GitHub mit dem LDAP-Plugin kopieren.
networks:
app_network:
driver: bridge
services:
ldap:
build:
context: nginx-ldap-auth-service # oder andere Name wenn ihr es umbenannt habt
dockerfile: Dockerfile
hostname: ldap
container_name: ldap
ports:
- "8888:8888"
environment:
- LDAP_URI=${LDAP_URI}
- LDAP_BASEDN=${LDAP_BASEDN}
- LDAP_BINDDN=${LDAP_BINDDN}
- LDAP_PASSWORD=${LDAP_PASSWORD}
- LDAP_USERNAME_ATTRIBUTE=sAMAccountName
- SECRET_KEY=nichtWichtig
- LDAP_AUTHORIZATION_FILTER=(&(memberOf=${LDAP_GROUP}) ({username_attribute}={username}))
networks:
- app_network
Was bedeuten diese Umgebungsvariablen? Die ersten vier enthalten einfach die Daten für die Verbindung mit dem Verzeichnis. In der Umgebungsvariable LDAP_USERNAME_ATTRIBUTE
definieren wir, welches Attribut als Benutzername verwendet wird. Der Authorisierungsfilter ermöglicht es uns, die Bedingungen für die Berechtigung festzulegen. In diesem Beispiel muss der Benutzer in der Gruppe sein, die wir als Umgebungsvariable definieren können. SECRET_KEY
ist ein Wert, der im Plugin erforderlich ist, aber nicht verwendet wird.
Die Variablen können aus dem Parameter Store abgerufen werden. Da das Passwort verschlüsselt ist, müsst ihr den Befehl mit der Option --with-decryption
ausführen.
# Ruf SSM-Parameter ab
AD_DNS_IP=$(aws ssm get-parameter --name "/nginx-ldap/ad-dns-ip" --query "Parameter.Value" --output text)
AD_NAME=$(aws ssm get-parameter --name "/nginx-ldap/ad-server-name" --query "Parameter.Value" --output text)
export LDAP_PASSWORD=$(aws ssm get-parameter --name "/nginx-ldap/ad-admin-password" --with-decryption --query "Parameter.Value" --output text)
# Formatte die Umgebungsvariablen
export LDAP_URI="ldap://${AD_DNS_IP}"
export LDAP_BASEDN="DC=$(echo ${AD_NAME} | sed 's/\./,DC=/g')"
export LDAP_BINDDN="CN=Administrator,CN=Users,$LDAP_BASEDN"
export LDAP_GROUP="CN=webservice,CN=Users,$LDAP_BASEDN"
Um diese Werte zu prüfen, könnt ihr das Werkzeug ldapsearch
benutzen. Es ermöglicht euch, das Verzeichnis zu durchsuchen und zu sehen, ob die Ausgabe wie erwartet ist. Auch den Filter kann man testen. Zuerst prüft ihr die Verbindung. Danach sucht ihr nach allen Benutzern mit der Klasse person
. Im letzten Schritt prüft ihr, ob der Filter richtig ist – zuerst mit dem Benutzer, der in der Gruppe ist, und dann mit dem Benutzer, der nicht in der Gruppe ist.
$ ldapsearch -x -H $LDAP_URI -D $LDAP_BINDDN -w $LDAP_PASSWORD -b $LDAP_BASEDN
-# extended LDIF
-#
-# LDAPv3
-# base <DC=auth,DC=company,DC=internal> with scope subtree
...
$ ldapsearch -x -LLL -H $LDAP_URI -D $LDAP_BINDDN -w $LDAP_PASSWORD -b $LDAP_BASEDN "(objectClass=person)" "sAMAccountName"
dn: CN=Generic,CN=Users,DC=auth,DC=company,DC=internal
sAMAccountName: generic
dn: CN=Karol Krawczyk,CN=Users,DC=auth,DC=company,DC=internal
sAMAccountName: tramwaj18
dn: CN=Administrator,CN=Users,DC=auth,DC=company,DC=internal
sAMAccountName: Administrator
...
$ ldapsearch -LLL -H $LDAP_URI -D $LDAP_BINDDN -w $LDAP_PASSWORD -b $LDAP_BASEDN \
"(&(memberOf=${LDAP_GROUP}) (sAMAccountName=tramwaj18))" \
"sAMAccountName"
dn: CN=Karol Krawczyk,CN=Users,DC=auth,DC=company,DC=internal
sAMAccountName: tramwaj18
-# refldap://auth.furfel.internal/CN=Configuration,DC=auth,DC=company,DC=internal
...
$ ldapsearch -LLL -H $LDAP_URI -D $LDAP_BINDDN -w $LDAP_PASSWORD -b $LDAP_BASEDN \
"(&(memberOf=${LDAP_GROUP}) (sAMAccountName=generic))" \
"sAMAccountName"
-# refldap://auth.furfel.internal/CN=Configuration,DC=auth,DC=company,DC=internal
...
Nachdem wir alles geprüft haben, können wir jetzt den Docker-Compose-Stack starten, nur mit diesem einen Service. Wenn die Konfiguration richtig ist, wird der Service starten. Andernfalls werden wir einige Fehler in den Logs sehen. Es ist möglich, dass der Service abbricht, wenn wir ihn von Nginx aus aufrufen.
$ docker-compose up -d
$ docker-compose logs
ldap | 2025-01-26T17:54:48.183974Z [info ] session.store [nginx_ldap_auth] backend=memory
ldap | 2025-01-26T17:54:48.184803Z [info ] session.setup.complete [nginx_ldap_auth] backend=memory cookie_domain=None cookie_name=nginxauth max_age=0 rolling=False
ldap | 2025-01-26T17:54:48.187028Z [info ] Started server process [1] [uvicorn.error]
ldap | 2025-01-26T17:54:48.187150Z [info ] Waiting for application startup. [uvicorn.error]
ldap | 2025-01-26T17:54:48.294225Z [info ] Application startup complete. [uvicorn.error]
ldap | 2025-01-26T17:54:48.301033Z [info ] Uvicorn running on https://ldap:8888 (Press CTRL+C to quit) [uvicorn.error]
Ich empfehle euch auch, ein Skript zu schreiben, in dem ihr die Umgebungsvariablen ladet und Docker Compose nur startet, falls es noch nicht läuft.
Nginx Konfiguration
Zuerst erstellen wir eine Entwurfskonfiguration ohne Locations. Wir brauchen einen Cache, in dem wir die Authentifizierungsdaten speichern können. Unser Cache wird auf maximal 32 MB vergrößert, hält 10 MB Daten im Arbeitsspeicher und löscht inaktive Schlüssel nach 60 Minuten. Dann konfigurieren wir die Verbindung zum LDAP-Authentifizierungsdienst. Hier nenne ich ihn einfach ldap
– wie in unserer docker-compose.yml
-Datei. server_name
sollte eure Domäne sein. Falls du keine Domäne hast, denke dir einen Namen aus und füge ihn in eure /etc/hosts
-Datei zusammen mit der IP-Adresse des Webservers ein.
events { worker_connections 1024; }
http {
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=auth_cache:10m max_size=32m inactive=60m use_temp_path=off;
upstream auth_backend {
server ldap:8888;
}
server {
listen 80;
server_name meine.domane.org;
# Hier kommen die Locations
}
}
In dieser Beispielkonfiguration verstecken wir die gesamte Website hinter LDAP. Wir brauchen drei Locations: eine für unsere Seite, eine für das LDAP-Anmeldeformular und eine für die Authentifizierung. Die letzte Location ist internal
, sodass man sie nicht direkt aufrufen kann – nur Nginx kommuniziert mit ihr, um die Daten zu überprüfen. In jedem dieser Abschnitte achtet auf die Domäne. Ihr solltet sie neben X-Cookie-Domain
ändern.
Authentifizierung
location /check-auth {
internal;
proxy_pass https://auth_backend/check;
proxy_pass_request_headers off;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_ignore_headers "Set-Cookie";
proxy_hide_header "Set-Cookie";
proxy_cache auth_cache;
proxy_cache_valid 200 10m;
proxy_set_header X-Cookie-Name "nginxauth";
proxy_set_header X-Cookie-Domain "meine.domane.org";
proxy_set_header Cookie nginxauth=$cookie_nginxauth;
proxy_cache_key "$http_authorization$cookie_nginxauth";
}
Das Anmeldeformular
location /auth {
proxy_pass https://auth_backend/auth;
proxy_set_header X-Cookie-Name "nginxauth";
proxy_set_header X-Cookie-Domain "meine.domane.org";
proxy_set_header X-Auth-Realm "Autentifizierung";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Die Hauptseite
location / {
auth_request /check-auth;
root /usr/share/nginx/html;
index index.html index.htm;
# Falls man erhaltet 401, redirect zum Anmeldeformular.
error_page 401 =200 /auth/login?service=$request_uri;
}
Wenn ihr die fertige Konfiguration habt, fügt einen neuen Service in die Docker-Compose-Datei ein. Mountet die Konfigurationsdatei in den Container und versucht, den Stack erneut zu starten. Vergesst nicht, die Umgebungsvariablen zu laden, sodass sich nichts am LDAP-Service ändert. Die neue Website wäre über die IP-Adresse der Instanz erreichbar. Aber ohne SSH-Tunnel oder VPN ist es eine schlechte Idee, die Passwörter über das Internet zu senden. Lest weiter.
networks:
app_network:
driver: bridge
services:
nginx:
image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
networks:
- app_network
depends_on:
- ldap
ldap:
...
TLS-geschützte Verbindung
Wenn ihr HTTPS nutzen möchtet, braucht ihr eine Domäne, damit ihr ein neues Zertifikat bekommt. Alternativ könnt ihr auch ein selbstsigniertes Zertifikat verwenden und die IP der Instanz in eure /etc/hosts
-Datei einfügen. Da ich eine Domäne habe, nutze ich Let’s Encrypt und Caddy. Caddy macht es vollkommen automatisch und einfach. Erstellt diese Konfiguration für Caddy in einer neuen Datei Caddyfile
. Dann legt einen neuen Service in eurem docker-compose.yml
an.
meine.domane.org {
tls {
issuer acme
}
reverse_proxy nginx:80
}
networks:
app_network:
driver: bridge
volumes:
caddy_data:
caddy_config:
services:
caddy:
image: caddy:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
networks:
- app_network
depends_on:
- nginx
nginx:
# Entferne ports aus nginx Service
...
Wie sieht es aus
Hier ist eine Demo dieses Projekts. Ihr könnt zuerst falsche Anmeldedaten versuchen, um zu sehen, ob der Filter funktioniert. Dann versucht es erneut mit den richtigen Daten. Ihr solltet die Beispielseite von Nginx sehen.
Top comments (0)