Das Lightweight Directory Access Protocol (LDAP) ist ein Netzwerkprotokoll, das den Zugriff auf verteilte Verzeichnisdienste ermöglicht. Es wurde Anfang der 1990er Jahre als schlanke Alternative zum X.500-DAP-Protokoll (Directory Access Protocol) entwickelt, das auf dem OSI-Protokollstack basierte und für TCP/IP-Netzwerke zu schwergewichtig war. LDAP läuft direkt über TCP/IP und hat sich seither als de-facto-Standard für Verzeichnisdienste etabliert.
Die konzeptionelle Grundlage stammt aus dem X.500-Standard (ISO/IEC 9594), der ein hierarchisches Modell zur Organisation von Informationen definiert. Dieses Modell beschreibt einen sogenannten Directory Information Tree (DIT) – einen Baum, in dem alle Einträge hierarchisch angeordnet sind. Jeder Eintrag besitzt einen eindeutigen Distinguished Name (DN), der seinen vollständigen Pfad innerhalb des Baums beschreibt.
1.1 Directory Information Tree (DIT)
Der DIT startet an der Wurzel und verzweigt sich in Domänenkomponenten (dc=), Organisationseinheiten (ou=) und schließlich in individuelle Einträge mit einem Common Name (cn=) oder einem User-ID-Attribut (uid=). Ein typischer DN sieht wie folgt aus:
uid=alice,ou=users,dc=example,dc=com
Dieser DN wird von rechts nach links gelesen: Die Wurzel der Domäne ist dc=example,dc=com (entspricht dem DNS-Namen example.com), darunter befindet sich die Organisationseinheit ou=users, und darin der Benutzer uid=alice. Gruppen wären typischerweise unter ou=groups,dc=example,dc=com abgelegt.
Jeder Eintrag im DIT besteht aus einem oder mehreren Objektklassen (objectClass), die die erlaubten und verpflichtenden Attribute eines Eintrags definieren. Die Objektklasse inetOrgPerson erlaubt z. B. Attribute wie mail, telephoneNumber, jpegPhoto und userPassword, während posixAccount Unix-spezifische Felder wie uidNumber, gidNumber und homeDirectory definiert.
1.2 Typische Einsatzszenarien
LDAP wird heute in vielen Bereichen eingesetzt: als zentrales Benutzerverzeichnis in Unternehmen (Microsoft Active Directory basiert intern auf LDAP), als Backend für E-Mail-Clients zur Adressbuchsuche, als Authentifizierungsquelle für VPNs, WLAN-Infrastruktur und Web-Applikationen sowie als Identitätsbasis für Single-Sign-On-Systeme. Im Homelab-Kontext ermöglicht ein LDAP-Server die zentrale Verwaltung aller Benutzerkonten und eine einheitliche Anmeldung für Dienste wie Nextcloud, Gitea, Proxmox oder selbst gehostete Web-Applikationen.
2. Das LDAP-Protokoll
LDAP definiert eine Reihe von Operationen, die ein Client gegen einen LDAP-Server ausführen kann. Die Kommunikation ist nachrichtenbasiert und asynchron – mehrere Anfragen können gleichzeitig über eine Verbindung gesendet werden, jede Antwort enthält eine Message-ID zur Zuordnung. LDAP verwendet standardmäßig Port 389 (unverschlüsselt) und Port 636 für LDAPS.
2.1 Kernoperationen
Die wichtigsten LDAP-Operationen im Überblick:
Bind: Authentifiziert den Client am Server. Ein Simple Bind überträgt DN und Passwort (daher nur mit TLS verwenden). Ein SASL Bind nutzt Mechanismen wie GSSAPI (Kerberos) oder DIGEST-MD5.
Search: Sucht Einträge im DIT. Parameter sind Base-DN, Scope (base, one, sub), Suchfilter und eine Liste der zurückzugebenden Attribute.
Add: Legt einen neuen Eintrag im Verzeichnis an.
Modify: Ändert Attribute eines bestehenden Eintrags (add, delete, replace).
ModifyDN: Benennt einen Eintrag um oder verschiebt ihn innerhalb des DIT.
Delete: Entfernt einen Eintrag aus dem Verzeichnis.
Compare: Prüft, ob ein Eintrag einen bestimmten Attributwert besitzt, ohne den vollständigen Eintrag zu übertragen.
Unbind: Beendet die Verbindung zum Server.
2.2 Suchfilter
LDAP-Suchfilter folgen einer präfix-notierten Syntax in Klammerschreibweise. Typische Beispiele:
# Alle Einträge mit einer bestimmten E-Mail-Adresse
(mail=alice@example.com)
# Alle Einträge der Klasse inetOrgPerson
(objectClass=inetOrgPerson)
# Benutzer mit uid "alice" UND der Klasse posixAccount
(&(uid=alice)(objectClass=posixAccount))
# Alle Einträge mit gesetzter Mail-Adresse (Wildcard)
(mail=*)
# Alle Einträge, die KEIN userPassword-Attribut haben
(!(userPassword=*))
2.3 LDAP, LDAPS und StartTLS
Unverschlüsseltes LDAP läuft standardmäßig auf Port 389. Dabei werden Credentials und Verzeichnisinhalte im Klartext übertragen – in Produktionsumgebungen inakzeptabel. Es gibt zwei Wege zur Verschlüsselung:
LDAPS (Port 636): TLS wird sofort beim Verbindungsaufbau ausgehandelt, bevor irgendwelche LDAP-Nachrichten übertragen werden. Einfach zu konfigurieren, klare Trennung durch eigenen Port.
StartTLS (Port 389): Die Verbindung beginnt unverschlüsselt, der Client sendet eine StartTLS-Operation, um auf TLS zu upgraden. Erlaubt theoretisch Fallback auf Klartext, was in sicheren Umgebungen durch entsprechende Client-Konfiguration verhindert werden muss.
In modernen Umgebungen ist LDAPS zu bevorzugen. Clients sollten so konfiguriert werden, dass sie keine unverschlüsselten Verbindungen tolerieren (TLS_REQCERT demand in der ldap.conf).
3. OpenLDAP einrichten
OpenLDAP ist die verbreitetste Open-Source-Implementierung des LDAP-Protokolls. Der zentrale Daemon heißt slapd (Standalone LDAP Daemon). Seit Version 2.3 wird die Konfiguration nicht mehr über eine statische Datei (slapd.conf) verwaltet, sondern über ein spezielles LDAP-Verzeichnis selbst – das sogenannte cn=config-Backend (auch OLC, Online Configuration, genannt). Konfigurationsänderungen werden damit zur Laufzeit ohne Neustart wirksam.
3.1 Installation
# Debian/Ubuntu
sudo apt update
sudo apt install slapd ldap-utils
# Interaktiven Konfigurationsdialog starten
sudo dpkg-reconfigure slapd
# Dort: DNS-Domain (z. B. example.com), Admin-Passwort und Backend-Typ (MDB) festlegen
3.2 Schema und Objektklassen
OpenLDAP lädt Schemas aus dem Verzeichnis /etc/ldap/schema/. Für einen typischen Benutzer-Verzeichnisdienst werden folgende Schemas benötigt:
Daten werden in OpenLDAP über das LDAP Data Interchange Format (LDIF) importiert und exportiert. LDIF ist ein zeilenbasiertes Textformat. Jeder Eintrag beginnt mit dem DN, gefolgt von Attributen als Schlüssel-Wert-Paare. Einträge werden durch eine Leerzeile getrennt:
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example Organisation
dc: example
3.4 Organisationseinheiten anlegen
# Datei: base.ldif
dn: ou=users,dc=example,dc=com
objectClass: top
objectClass: organizationalUnit
ou: users
dn: ou=groups,dc=example,dc=com
objectClass: top
objectClass: organizationalUnit
ou: groups
# Import durchführen
ldapadd -x -D "cn=admin,dc=example,dc=com" -W -f base.ldif
Ein zentrales LDAP-Verzeichnis ist besonders wertvoll, wenn sich Linux-Systeme direkt damit für den Benutzer-Login authentifizieren. Die gängige Lösung dafür ist die Kombination aus NSS (Name Service Switch) und PAM (Pluggable Authentication Modules) mit LDAP-Unterstützung. NSS löst dabei Benutzer- und Gruppeninformationen auf, PAM übernimmt den Authentifizierungsvorgang selbst.
4.1 nss-pam-ldapd installieren
Das Paket nss-pam-ldapd stellt den Daemon nslcd (Name Service LDAP Connection Daemon) bereit, der als Vermittler zwischen dem Betriebssystem und dem LDAP-Server fungiert. NSS-Anfragen nach Benutzern, Gruppen und Passwörtern werden an nslcd weitergereicht, der sie gegen LDAP auflöst.
# Installation auf Debian/Ubuntu
sudo apt install libnss-ldapd libpam-ldapd nslcd
# Konfigurationsdatei des Daemons: /etc/nslcd.conf
uri ldaps://ldap.example.com
base dc=example,dc=com
binddn cn=readonly,dc=example,dc=com
bindpw LesePasswortFuerBindDN
tls_cacertfile /etc/ssl/certs/ca-certificates.crt
tls_reqcert demand
Sudo-Regeln können ebenfalls im LDAP-Verzeichnis hinterlegt werden. Dafür wird das sudo-ldap-Schema benötigt, das die Objektklasse sudoRole einführt. Damit lassen sich sudo-Berechtigungen zentral verwalten und ohne lokale Änderungen an /etc/sudoers auf allen Systemen gleichzeitig ausrollen.
# sudo-Schema laden (Pfad je nach Distribution)
sudo ldapadd -Y EXTERNAL -H ldapi:/// \
-f /usr/share/doc/sudo-ldap/schema.OpenLDAP
# sudoRole: Alice darf alle Befehle auf allen Hosts ausführen
dn: cn=alice-sudo,ou=sudoers,dc=example,dc=com
objectClass: sudoRole
cn: alice-sudo
sudoUser: alice
sudoHost: ALL
sudoCommand: ALL
# Einbindung in sudo: /etc/sudo-ldap.conf
uri ldaps://ldap.example.com
sudoers_base ou=sudoers,dc=example,dc=com
binddn cn=readonly,dc=example,dc=com
bindpw LesePasswortFuerBindDN
# /etc/nsswitch.conf – sudo-Quelle ergänzen
sudoers: files ldap
5. Single Sign-On im Homelab
Für ein komfortables Homelab reicht ein reiner LDAP-Server oft nicht aus: Moderne Applikationen setzen auf OpenID Connect (OIDC) oder SAML für die Authentifizierung, da diese Protokolle sicherer, flexibler und breiter standardisiert sind als direktes LDAP-Bind. Die Lösung ist ein Identity Provider (IdP), der LDAP als Benutzerbackend nutzt und nach außen OIDC/SAML anbietet. Der Benutzer meldet sich einmal beim IdP an und erhält Zugang zu allen verbundenen Diensten – das ist Single Sign-On.
5.1 Authentik als Identity Provider
Authentik ist ein moderner, in Python geschriebener Identity Provider, der sich hervorragend für Homelabs eignet. Er bietet eine übersichtliche Web-UI, unterstützt LDAP, OIDC, SAML, OAuth2, SCIM und Proxy-Authentifizierung. Authentik kann OpenLDAP als Benutzerverzeichnis einbinden (LDAP Source) oder selbst als LDAP-Server fungieren (LDAP Provider), sodass ältere Applikationen, die nur LDAP sprechen, ebenfalls integriert werden können.
Nach dem Start ist Authentik unter https://<host>:9443/if/flow/initial-setup/ erreichbar. Unter Directory → Federation & Social login → Sources kann ein vorhandener OpenLDAP-Server als LDAP-Source eingebunden werden. Unter Applications → Providers wird ein OAuth2/OIDC-Provider für jede Applikation erstellt.
5.2 Keycloak als Alternative
Keycloak ist die Enterprise-Alternative von Red Hat, deutlich umfangreicher, aber auch ressourcenhungriger (empfohlen: mind. 2 GB RAM). Es bietet ähnliche Features wie Authentik: OIDC, SAML, User Federation über LDAP, Social Login und feingranulare Rollen- und Rechteverwaltung über sogenannte Realms.
# Keycloak mit Docker starten (Entwicklungsmodus)
docker run -p 8080:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest \
start-dev
In Keycloak wird unter Realm → User Federation → Add LDAP provider der OpenLDAP-Server eingebunden. Wichtige Parameter sind Connection URL (ldaps://ldap.example.com), Bind DN, Bind Credential sowie Users DN (ou=users,dc=example,dc=com). Keycloak kann LDAP-Benutzer bei Bedarf in seine eigene Datenbank synchronisieren und Cache-Strategien für schnelle Zugriffszeiten verwenden.
5.3 OIDC-Integration für Applikationen
Sobald ein IdP eingerichtet ist, können Dienste wie Nextcloud, Gitea, Proxmox, Grafana oder Portainer über OIDC angebunden werden. Das Grundprinzip: Die Applikation registriert sich als Client beim IdP und erhält eine Client ID und ein Client Secret. Bei der Anmeldung leitet die Applikation den Benutzer zum IdP weiter (Authorization Code Flow), der Benutzer authentifiziert sich dort, und die Applikation erhält ein signiertes ID-Token mit den Benutzerinformationen.
RADIUS (Remote Authentication Dial-In User Service, RFC 2865) ist das Standardprotokoll zur Authentifizierung in Netzwerkinfrastrukturen: WLANs mit WPA2/WPA3-Enterprise, VPN-Gateways, Switches mit 802.1X-Port-Authentifizierung und Einwahlserver nutzen alle RADIUS. FreeRADIUS ist die verbreitetste Open-Source-Implementierung und lässt sich über ein Modul direkt mit einem LDAP-Verzeichnis verbinden.
Bei WPA2-Enterprise mit EAP-TTLS oder PEAP-MSCHAPv2 authentifiziert sich der WLAN-Client gegenüber dem Access Point, der die Credentials an den RADIUS-Server weiterleitet. Der RADIUS-Server prüft diese gegen LDAP. Der Vorteil gegenüber einem gemeinsam genutzten Pre-Shared Key (PSK): Jeder Benutzer hat eigene Zugangsdaten, der Entzug des LDAP-Kontos entzieht sofort den WLAN-Zugang.
# FreeRADIUS neu starten
sudo systemctl restart freeradius
# Testweise Authentifizierung prüfen
radtest alice MeinPasswort 127.0.0.1 0 testing123
Nach der Konfiguration können WLAN-Clients mit ihren LDAP-Benutzerdaten am WPA2-Enterprise-Netzwerk angemeldet werden. Der EAP-Tunnel ist TLS-verschlüsselt, sodass Passwörter niemals im Klartext über die Luftschnittstelle übertragen werden.
7. Sicherheitshinweise
Ein LDAP-Server verwaltet zentrale Identitätsdaten – er ist ein hochsensibles Ziel und muss entsprechend abgesichert werden. Die folgenden Punkte sind keine optionalen Empfehlungen, sondern Mindestanforderungen für einen produktiv eingesetzten Verzeichnisdienst.
7.1 LDAP-Traffic verschlüsseln
Unverschlüsseltes LDAP auf Port 389 darf ausschließlich auf dem Loopback-Interface (127.0.0.1) oder in vollständig isolierten Segmenten betrieben werden. Alle externen Verbindungen müssen über LDAPS (Port 636) abgesichert sein. Clients sind so zu konfigurieren, dass sie unverschlüsselte Verbindungen explizit ablehnen:
# /etc/ldap/ldap.conf (systemweit auf allen LDAP-Clients)
URI ldaps://ldap.example.com
BASE dc=example,dc=com
TLS_CACERT /etc/ssl/certs/ca-certificates.crt
TLS_REQCERT demand
7.2 Bind-DN mit minimalen Rechten
Applikationen, die LDAP nur zum Suchen und Authentifizieren benötigen, erhalten einen dedizierten Read-Only Bind-DN mit ausschließlichem Lesezugriff. Der Admin-DN (cn=admin) darf niemals in Applikationskonfigurationen verwendet werden. Access Control Lists (ACLs) in OpenLDAP werden über das olcAccess-Attribut im cn=config-Backend definiert:
# Read-Only-Konto anlegen
dn: cn=readonly,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: readonly
description: LDAP read-only bind account
userPassword: {SSHA}...
# ACL: readonly darf alles lesen, Benutzer sich selbst ändern
# Datei: acl.ldif
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcAccess
olcAccess: to attrs=userPassword
by dn.exact="cn=admin,dc=example,dc=com" write
by anonymous auth
by self write
by * none
olcAccess: to *
by dn.exact="cn=admin,dc=example,dc=com" write
by dn.exact="cn=readonly,dc=example,dc=com" read
by self read
by * none
ldapmodify -Y EXTERNAL -H ldapi:/// -f acl.ldif
7.3 LDAP-Injection verhindern
Applikationen, die Benutzereingaben ungeprüft in LDAP-Suchfilter einbauen, sind anfällig für LDAP-Injection. Durch manipulierte Eingaben kann ein Angreifer den Filter verändern, Authentifizierungsprüfungen umgehen oder unberechtigte Daten auslesen. Die Sonderzeichen (, ), *, \ und NUL müssen als \XX (Hex) in Filter-Strings kodiert werden.
# Unsicher – Benutzereingabe direkt im Filter:
filter = f"(uid={benutzername})" # NIEMALS SO!
# Sicher – Sonderzeichen escapen mit ldap3 (Python):
from ldap3.utils.conv import escape_filter_chars
sicherer_name = escape_filter_chars(benutzername)
filter = f"(uid={sicherer_name})"
# Sicher – mit java.naming.ldap (Java):
// LdapName normalisiert und escaped Eingaben automatisch
LdapName ln = new LdapName("uid=" + uid.replace("\\", "\\\\"));
7.4 Weitere Härtungsmaßnahmen
Anonymen Zugriff deaktivieren:olcDisallows: bind_anon in cn=config verhindert unauthentifizierte Lesezugriffe auf das Verzeichnis.
Sicheres Passwort-Hashing: Passwörter niemals im Klartext speichern. OpenLDAP unterstützt {SSHA} nativ; über das slapo-ppolicy-Overlay sind modernere Algorithmen möglich. Für neue Deployments empfiehlt sich der Einsatz eines IdP (Authentik/Keycloak), der bcrypt/Argon2 verwendet.
Password Policy Overlay:slapo-ppolicy ermöglicht Passwortrichtlinien, Account-Sperrung nach Fehlversuchen und Passwortablauf direkt im LDAP-Server.
Firewall: Ports 389 und 636 dürfen ausschließlich für explizit erlaubte IP-Bereiche geöffnet sein. Kein direkter Internetzugang zum LDAP-Server.
Regelmäßige Backups: Das Verzeichnis mit slapcat in LDIF exportieren und versioniert sichern.
Ein sorgfältig konfigurierter LDAP-Server bildet das Fundament einer sicheren und wartbaren Identitätsinfrastruktur – ob im Homelab oder in einem kleinen Unternehmensnetz. Die Kombination aus OpenLDAP als zentralem Verzeichnis, Authentik oder Keycloak als Identity Provider und FreeRADIUS für die Netzwerkauthentifizierung deckt nahezu alle Anforderungen einer modernen Infrastruktur ab, ohne auf proprietäre Produkte angewiesen zu sein.