
🌐 Auch auf: English · Français · Español
Mein Homelab hat drei Domain Controller, zwei Clients, drei iLO-Management-Boards und bis letzte Woche exakt null Zertifikate, denen irgendjemand Grund hatte zu vertrauen. Jede RDP-Sitzung begann mit einer Warnung, jedes iLO begrüßte mich mit „Ihre Verbindung ist nicht privat“ (Aussteller: Default Issuer (Do not trust), was immerhin ehrlich ist), und die Domain Controller sprachen überhaupt kein LDAPS.
Ich betreibe kaum interne Webdienste, also hielt ich eine private PKI eine Weile für eine Lösung auf der Suche nach einem Problem. Falsch gedacht. Eine Windows-Domäne hat jede Menge Stellen, an denen Zertifikate die Dinge leise besser machen. Der Trick ist, Active Directory sie selbstständig verteilen zu lassen, damit ich nie wieder über ihre Erneuerung nachdenken muss.
Gleicher Ablauf wie in den bisherigen Windows-Beiträgen: Ich entscheide, und mein KI-Co-Admin (Claude, der PowerShell über WinRM und die iLOs über Redfish steuert) baut es und prüft jeden Schritt. Diesmal gehörte zur Prüfung auch, unsere eigenen TLS-Handshakes von einer Linux-Kiste aus mit openssl s_client zu kontrollieren.
🎯 Wem Zertifikate tatsächlich etwas bringen
- Domain Controller: Mit einem „Kerberos Authentication“-Zertifikat sprechen sie LDAPS auf Port 636 und beherrschen zertifikatsbasiertes Kerberos (Voraussetzung für Dinge wie Windows Hello for Business).
- Remotedesktop: RDP nutzt pro Rechner ein selbstsigniertes Zertifikat. Mit einem von der CA ausgestellten verschwindet der Dialog „Die Identität des Remotecomputers kann nicht überprüft werden“, und eine echte Man-in-the-Middle-Warnung hätte wieder Bedeutung.
- WinRM über HTTPS (5986): Meine Automatisierung lief über HTTP mit NTLM-Nachrichtenverschlüsselung. Funktioniert, aber echtes TLS mit überprüfbarer Serveridentität ist besser.
- iLO-Weboberflächen: die klassischen „Warnung wegklicken“-Seiten.
- Codesignatur: ein Zertifikat für mich, damit meine PowerShell-Startskripte signiert werden können und irgendwann nur noch signierte Skripte laufen dürfen.
Nicht auf der Liste: alles Öffentliche. Nextcloud und der Blog bleiben bei Let’s Encrypt, denn einer privaten Root vertrauen nur meine eigenen Geräte, und genau darum geht es ja.
🏛️ Design: einstufig, auf einem DC, und warum das ein Kompromiss ist
Die Lehrbuch-PKI hat zwei Stufen: eine Offline-Root-CA, die ausgeschaltet in einer Schublade liegt und nur die ausstellende CA signiert, plus eine ausstellende CA (Issuing CA), die die tägliche Arbeit erledigt. Wird die ausstellende CA kompromittiert, widerruft man sie, und die Root überlebt.
Ich habe eine einstufige Enterprise Root CA gebaut: „Muench Homelab Root CA“, RSA 4096, SHA-256, 10 Jahre gültig, auf HP3. Das ist ein bewusster Kompromiss. Alle drei meiner Server sind Domain Controller, und eine CA auf einem DC hat echte Nachteile: Der Server lässt sich nicht mehr umbenennen, und ihn herabzustufen wird kompliziert. Ohne Member-Server und ohne Hypervisor gibt es gerade kein besseres Zuhause dafür. Sobald ein Hypervisor kommt, ist ein zweistufiger Aufbau mit einer Offline-Root-VM der natürliche nächste Schritt.
Drei Entscheidungen vor dem ersten Klick:
CAPolicy.infmitLoadDefaultTemplates=0. Ohne das veröffentlicht eine frische Enterprise CA sofort ein Dutzend Standardvorlagen mit großzügigen Registrierungsrechten. Genau in diesen Standards stecken die meisten bekannten AD-CS-Angriffspfade. Meine CA startete mit null veröffentlichten Vorlagen.- Sperrlisten und CA-Zertifikat nur per LDAP. Die Standard-CDP/AIA-Erweiterungen zeigen zusätzlich auf
http://<ca>/CertEnroll/, einen Webserver, den es hier nicht gibt. Clients würden es versuchen und in einen Timeout laufen. Jeder Client in dieser Domäne kann LDAP lesen, also fliegt HTTP raus. - Keine Webregistrierung. Die alten
/certsrv-Seiten sind das Ziel des NTLM-Relay-Angriffs namens ESC8. Nicht installiert, nicht gebraucht.
Dazu die langweilige Hygiene: CA-Überwachung an, ausgestellte Zertifikate auf maximal zwei Jahre begrenzt. Und die CA-Datenbank ist Teil der nächtlichen Systemstatus-Sicherung von HP3, die es seit dem letzten Beitrag gibt.
📜 Vorlagen: klein, eng und explizit
Eine Zertifikatvorlage legt fest, was ein Zertifikat kann und wer es beantragen darf. Beim „Wer“ danebenzuliegen ist der Weg, auf dem Domänen übernommen werden: Das berühmte ESC1 ist eine Vorlage, bei der ein Benutzer mit wenig Rechten jeden beliebigen Namen in den Antrag schreiben darf, auch den eines Domänen-Admins. Also gibt es vier Vorlagen, jede mit den engsten Rechten, die noch funktionieren:
| Vorlage | Zweck | Antragsteller (Subject) | Wer registrieren darf |
|---|---|---|---|
| Kerberos Authentication (integriert) | DC-Zertifikate: LDAPS, Kerberos | aus AD | Domain Controllers (automatisch) |
| HomelabComputer | RDP, WinRM HTTPS | aus AD (CN + DNS-SAN = FQDN) | Domain Computers + DCs (automatisch) |
| HomelabWebServer | iLO, später Windows Admin Center | im Antrag angegeben | nur Domain Admins, manuell |
| HomelabCodeSigning | PowerShell-Skripte signieren | aus AD | ich (automatisch, bei der Anmeldung) |
Die WebServer-Vorlage ist die gefährliche, weil der Antragsteller den Namen wählt. Genau deshalb dürfen nur Domain Admins sie benutzen. Und das CA-Flag EDITF_ATTRIBUTESUBJECTALTNAME2 (ESC6, „Antragsteller dürfen beliebige SANs als Antragsattribut hinzufügen“) bleibt aus. Die Namen kommen aus dem CSR selbst, und das reicht für die iLOs.
Vorlagen ohne GUI anlegen (und drei Stolperfallen)
PowerShell hat kein New-CATemplate. Das „Vorlage duplizieren“ der MMC ist in Wahrheit nur das Kopieren eines AD-Objekts: ein pKICertificateTemplate unter CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration, plus ein passendes msPKI-Enterprise-Oid-Objekt mit einer frischen OID unterhalb der OID-Basis der Gesamtstruktur. Also haben wir genau das gemacht, Attribut für Attribut: Schemaversion 2, Namensflags, Registrierungsflags, EKUs, dann die ACL mit den erweiterten Rechten Enroll und AutoEnroll. Unterwegs:
- PowerShell-Variablen unterscheiden keine Groß-/Kleinschreibung.
$Eenthielt die Enroll-GUID,$ewar die Schleifenvariable. Rate mal, wer gewonnen hat. - PowerShell entpackt Arrays mit nur einem Element.
@(@('512','manual'))ist keine Liste mit einem Paar, sondern das Paar selbst, also versuchte die Schleife fröhlich, den Benutzer „5“ aufzulösen. Die Lösung ist das unäre Komma:@(,@('512','manual')). Add-CATemplatebeharrte darauf, die brandneuen Vorlagen „existieren nicht in der Domäne“, währendcertutil -templatesie problemlos auflistete.certutil -SetCATemplates +HomelabComputer,…veröffentlichte sie beim ersten Versuch.
Und der Dauerbrenner: WinRM überträgt Skripte als Base64-UTF-16 auf einer Kommandozeile, die bei 8191 Zeichen gedeckelt ist. Ein Vorlagenskript wuchs von 2.970 auf 3.170 Zeichen und hörte stillschweigend auf, überhaupt irgendetwas zu tun. Kein Fehler, keine Ausgabe. Mein Co-Admin zählt jetzt Zeichen, bevor er sendet. Ich auch.
🤖 Automatische Registrierung: der Teil, in dem AD die Arbeit macht
Eine GPO, homelab – PKI Auto-Enrollment, verknüpft an der Domänenwurzel: automatische Registrierung für Computer und Benutzer, mit aktiviertem „Abgelaufene Zertifikate erneuern“ und „Ausstehende Zertifikate aktualisieren“. Nach einem gpupdate und certutil -pulse hatte jeder DC innerhalb einer Minute zwei neue Zertifikate: Kerberos Authentication und HomelabComputer, mit korrektem FQDN, ein Jahr gültig. Die Erneuerung passiert sechs Wochen vor Ablauf, und niemand muss an irgendwas denken.
Die DCs haben das Kerberos-Zertifikat für LDAPS automatisch übernommen, ganz ohne Konfiguration: Sobald ein passendes Zertifikat im Computerspeicher liegt, antwortet Port 636.
RDP: die Richtlinie, die nichts tat
Es gibt eine Gruppenrichtlinie, die genau dafür gemacht ist: Vorlage für Serverauthentifizierungszertifikat. RDP soll aus dieser Vorlage ein Zertifikat registrieren und verwenden. Sie war gesetzt, in der Registry überprüft, SessionEnv neu gestartet, TermService auf den Servern ohne Sitzungen neu gestartet, und RDP präsentierte weiter sein selbstsigniertes Zertifikat. Kein einziges Ereignis in irgendeinem Log erklärte, warum.
Statt einen unsichtbaren Mechanismus zu debuggen, haben wir den deterministischen Weg genommen: ein kleines Startskript in derselben GPO. Bei jedem Boot sucht es das neueste gültige HomelabComputer-Zertifikat heraus und bindet es an RDP (Win32_TSGeneralSetting.SSLCertificateSHA1Hash). Dasselbe Skript legt den WinRM-HTTPS-Listener mit diesem Zertifikat an oder aktualisiert ihn, und die GPO ergänzt eine Firewall-Regel für 5986, nur LAN. Die Maschinen booten monatlich für Patches neu, und die Erneuerung beginnt sechs Wochen vorher, also ist ein erneuertes Zertifikat immer rechtzeitig gebunden. Das Skript loggt nach %ProgramData%\homelab\pki-bind.log, denn „wird schon gelaufen sein“ ist kein Status.
🔌 iLO-Zertifikate per Redfish
iLOs sind keine Domänenmitglieder, also keine automatische Registrierung. Aber iLO 5 kann seinen eigenen Schlüssel samt CSR erzeugen, und das alles lässt sich über Redfish skripten:
POST …/SecurityService/HttpsCert/Actions/HpeHttpsCert.GenerateCSRmit dem FQDN als Common Name undIncludeIP: true. Zehn bis dreißig Sekunden später taucht der CSR inCertificateSigningRequestauf. Er enthält einen 2048-Bit-Schlüssel und SANs für den DNS-Namen und die IP-Adresse. Der private Schlüssel verlässt das iLO nie.- Auf der CA:
certreq -submit -attrib "CertificateTemplate:HomelabWebServer". …/HpeHttpsCert.ImportCertificatemit dem PEM. Das iLO setzt sich selbst zurück; der Host merkt nichts davon.
Tschüss, Default Issuer (Do not trust). Da das Zertifikat sowohl den Namen als auch die IP enthält, ist das iLO auf beiden Wegen vertrauenswürdig. Das zählt, wenn ausgerechnet DNS das ist, was man gerade reparieren will.
✅ Vertrauen ist gut, OpenSSL ist besser
Domänenmitglieder vertrauen der neuen Root automatisch: Eine Enterprise CA veröffentlicht ihr Zertifikat im AD, und die Gruppenrichtlinie verteilt es. Für den Beweis habe ich die Root auf die Linux-Backup-Kiste exportiert und jeden Endpunkt so geprüft, wie es ein strenger Client tun würde, mit Namensprüfung:
openssl s_client -connect 192.168.10.30:636 -CAfile muench-homelab-root-ca.crt
\
-verify_hostname HP1-dc01.muench.home.arpa # Verify return code: 0 (ok)| Endpunkt | HP1 | HP2 | HP3 |
|---|---|---|---|
| LDAPS :636 | ✅ | ✅ | ✅ |
| WinRM HTTPS :5986 | ✅ | ✅ | ✅ |
| RDP-Zertifikat von der CA ausgestellt | ✅ | ✅ | ✅ |
| iLO :443 per Name und per IP | ✅ | ✅ | ✅ |
Bisher neun ausgestellte Zertifikate: drei für Kerberos, drei für die Computer, drei für die iLOs. Die beiden Clients folgen beim nächsten Boot, mein Codesignaturzertifikat bei meiner nächsten Anmeldung.
🧭 Wie es weitergeht
- LDAP-Signierung und Channel Binding erzwingen. Mit LDAPS ist die letzte Ausrede weg. Es ist eine einzige Sicherheitsoption in der Default Domain Controllers Policy, und diese Option überschreibt stillschweigend jeden Registry-Wert, den man auf die „clevere“ Art setzt.
- Die Startskripte signieren mit dem neuen Codesignaturzertifikat, dann die Ausführungsrichtlinie von Bypass auf AllSigned umstellen.
- Windows Admin Center auf der Admin-Workstation, mit einem Zertifikat aus der WebServer-Vorlage statt seines selbstsignierten Standardzertifikats.
- Zwei Stufen, sobald es einen Hypervisor gibt: eine Offline-Root-VM, die eine neue ausstellende CA signiert und sich dann wieder schlafen legt.
🎯 Fazit
Eine private PKI klang nach Enterprise-Overkill für ein Homelab mit kaum internen Webdiensten. In der Praxis war die Domäne selbst der Kunde: DCs, RDP, WinRM, iLOs. Das Beste daran: Nach der Einrichtung braucht nichts davon Aufmerksamkeit. Zertifikate tauchen auf, erneuern sich und werden von selbst gebunden. Das Schwierige ist nicht, eine CA zu installieren; es ist das, was man nicht veröffentlicht, wen man nicht registrieren lässt, und die Flags, die man weglässt. Sicherheit ist, wie üblich, vor allem die Kunst, Nein zu sagen. 🔏





