Kerberos Load Balancer SPN
Warum Kerberos hinter dem Load Balancer sporadisch versagt – und wie ein gemeinsames Dienstkonto das Problem ein für alle Mal löst.Kerberos hinter dem Load Balancer: SPNs für virtuelle Namen
Einzelner Webserver, integrierte Authentifizierung, alles läuft – und dann stellt jemand einen Load Balancer davor, verteilt auf drei Nodes, und plötzlich klemmt Kerberos. Mal geht es, mal nicht, scheinbar würfelt das System. Das ist kein Zufall und kein Bug: Es ist die direkte Folge davon, dass der virtuelle Name, den die Clients ansprechen, keinem der Nodes gehört. Wer das Prinzip einmal verstanden hat, löst es in zehn Minuten. Wer es nicht versteht, dreht tagelang an den falschen Schrauben.
Warum es überhaupt klemmt
Kerberos ist gnadenlos namensbezogen. Der Client ruft portal.contoso.de auf, der Load Balancer leitet die Anfrage an einen beliebigen Node weiter – sagen wir WEB02. Der Client hat sich aber vom KDC ein Ticket für HTTP/portal.contoso.de geholt. WEB02 kennt aber nur seinen eigenen Maschinen-SPN HOST/web02. Das Ticket ist mit einem Schlüssel verschlüsselt, den WEB02 überhaupt nicht hat. Ergebnis: WEB02 kann das Ticket nicht entschlüsseln, Kerberos scheitert, der Client fällt still auf NTLM zurück – oder bekommt eine Fehlermeldung.

Abbildung 1: Der virtuelle Name gehört keinem Node – das Ticket für HTTP/portal passt zum Maschinenschlüssel keines einzelnen Servers.
|
Das verräterische Symptom Wenn eine Anwendung hinter dem LB „manchmal“ nach Anmeldedaten fragt oder Single-Sign-On sporadisch versagt, während der Direktzugriff auf einen einzelnen Node sauber läuft – dann sind Sie fast immer hier. Das „manchmal“ entsteht, weil der LB mal den einen, mal den anderen Node trifft. |
|---|
Die Lösung: ein gemeinsames Dienstkonto
Der Trick ist, den virtuellen Namen einem Konto zu geben, das alle Nodes gemeinsam nutzen. Wenn jeder Node den App-Pool unter demselben Dienstkonto betreibt und der SPN HTTP/portal.contoso.de genau an diesem Konto hängt, dann teilen sich alle Nodes denselben Kerberos-Schlüssel. Egal, welchen Node der Load Balancer erwischt – das Ticket passt immer.

Abbildung 2: Alle Nodes betreiben den App-Pool unter demselben Dienstkonto – der SPN am gemeinsamen Konto passt zu jedem Node.
Praktisch ist dafür ein gruppen-verwaltetes Dienstkonto (gMSA) die erste Wahl: kein Passwort-Pflegeaufwand, automatische Rotation, mehrere Server dürfen es nutzen. Die Einrichtung in Kurzform:
Der SPN-Befehl selbst ist unspektakulär – wichtig ist nur, dass er ans Dienstkonto geht und nicht an ein Computer-Konto:
|
setspn -S HTTP/portal.contoso.de CONTOSO\svc-portal$ |
|---|
|
Der Klassiker, der alle erwischt Sie haben alles richtig gemacht, der App-Pool läuft unter dem Dienstkonto, der SPN sitzt – und trotzdem NTLM. Ursache: In IIS steht useKernelMode auf true, aber useAppPoolCredentials auf false. Dann entschlüsselt IIS das Ticket weiterhin mit dem Maschinen-Konto statt mit dem App-Pool-Konto. Diese eine Einstellung kostet erfahrungsgemäß die meisten Stunden. |
|---|
Die DNS-Falle: A-Record oder CNAME?
Ein zweiter, gern übersehener Stolperstein sitzt im DNS. Wie der virtuelle Name aufgelöst wird, beeinflusst, welchen SPN der Client überhaupt anfragt.

Abbildung 3: Beim A-Record fragt der Client genau den erwarteten SPN ab – ein CNAME kann den Client dazu bringen, den SPN des CNAME-Ziels zu verlangen.
Ein A-Record ist die berechenbare Variante: Der Client fragt nach genau dem Namen, den er aufgerufen hat, und damit nach HTTP/portal.contoso.de. Ein einziger SPN reicht. Ein CNAME kann dagegen – je nach Client-Verhalten und Konfiguration – dazu führen, dass der SPN auf das CNAME-Ziel aufgelöst wird, also etwa HTTP/web-cluster.contoso.de. Dann fehlt plötzlich der erwartete SPN, obwohl Sie ihn doch gesetzt haben.
|
Pragmatische Empfehlung Nutzen Sie nach Möglichkeit einen A-Record für den virtuellen Namen. Wenn ein CNAME unvermeidlich ist, tragen Sie sicherheitshalber beide SPNs am Dienstkonto ein – den für den aufgerufenen Namen und den für das CNAME-Ziel. Das deckt beide Client-Verhalten ab und kostet nichts außer zwei Zeilen. |
|---|
Schnelle Diagnose am laufenden System
Drei Handgriffe sagen Ihnen, ob die Sache greift. Erst am Client den Cache leeren und die Seite aufrufen, dann nachsehen, welches Ticket gezogen wurde:
|
klist purge REM … portal.contoso.de im Browser aufrufen … klist | findstr portal |
|---|
Erscheint ein Ticket für HTTP/portal.contoso.de, greift Kerberos. Erscheint keines, fragen Sie den SPN gegen (setspn -Q HTTP/portal.contoso.de) und prüfen, ob er am richtigen Dienstkonto hängt und nicht doppelt vergeben ist.
Häufige Fragen
Muss der SPN an jedem Node einzeln gesetzt werden?
Nein – und das ist genau der Punkt. Der SPN für den virtuellen Namen wird genau einmal am gemeinsamen Dienstkonto gesetzt, nicht an den einzelnen Computer-Konten. Weil alle Nodes den App-Pool unter diesem einen Konto betreiben, teilen sie sich den Schlüssel automatisch. Würden Sie den SPN an mehreren Konten setzen, hätten Sie sofort ein Duplikat – und damit das nächste Problem.
Funktioniert das auch ohne gMSA, mit einem normalen Dienstkonto?
Ja. Ein klassisches Domänen-Benutzerkonto als Dienstkonto tut es ebenso – Sie müssen dann nur das Passwort selbst verwalten und bei Rotation auf allen Nodes aktualisieren. Das gMSA nimmt Ihnen genau diese Pflege ab und ist deshalb die bequemere Wahl, technisch funktioniert beides identisch. Wichtig ist nur: ein gemeinsames Konto für alle Nodes, nicht die Maschinen-Konten.
Warum funktioniert der Zugriff auf einen einzelnen Node direkt, aber über den LB nicht?
Weil beim Direktzugriff der Client genau den Node-Namen anspricht, dessen HOST/-SPN auf dem Maschinen-Konto vorhanden ist – das passt. Über den LB ruft er aber den virtuellen Namen auf, und der gehört keinem Maschinen-Konto. Dieser Unterschied ist das beste Diagnose-Indiz: Geht es direkt, aber nicht über den LB, ist es fast immer die SPN-Zuordnung des virtuellen Namens.
Spielt die SSL-Terminierung am Load Balancer eine Rolle?
Indirekt ja. Terminiert der LB SSL und reicht nur HTTP an die Nodes weiter, müssen Sie darauf achten, dass die Authentifizierung trotzdem konsistent läuft und der erwartete Host-Header durchgereicht wird. Für den SPN selbst zählt der Name, den der Client aufruft – die Terminierung ändert daran nichts, kann aber Header und damit das Verhalten der integrierten Authentifizierung beeinflussen. Prüfen Sie, dass der LB den ursprünglichen Host-Header erhält.
Was ist mit useKernelMode – an oder aus?
Kernel-Mode-Authentifizierung (useKernelMode = true) ist performant und kann angeschaltet bleiben – entscheidend ist die Kombination mit useAppPoolCredentials = true. Erst diese zweite Einstellung sorgt dafür, dass IIS das Kerberos-Ticket mit den Anmeldedaten des App-Pools (also Ihres Dienstkontos) entschlüsselt statt mit dem Maschinen-Konto. Beide zusammen sind die richtige Konfiguration für ein gemeinsames Dienstkonto hinter dem LB.