Pozn.: Tento článek jsem napsal asi před dvěma měsicí a nyní jsme pouze změnil jeho název z původního Troubleshooting Kerberos Single Sign-On a zařadil jej do nové série o Kerberos SSO.
Pozn.: Určitě v tomto článku neřešíme všechny možnosti. Například se zde vůbec nevěnujeme síťové úrovni – jestli komunikace po síti může doputovat na správný server, tedy třeba jestli není cestou blokovaný port 88 pro Kerberos, apod.
Když chceme provádět troubleshooting nějaké oblasti, tak je většinou potřeba ji rozumět, jak funguje a jak probíhají jednotlivé operace. Oblast Kerberosu a SSO jsme si popsali v předchozích dílech seriálu a zde budeme předpokládat znalost termínů a vlastního principu.
Pozn.: Článek popisuje testy v pořadí, jak autentizace probíhá. V praxi je určitě výhodnější nejdříve ověřit, jestli klient získal Service Ticket pro službu. Pokud ne, tak hledat problém v získání ticketu, pokud ano, tak na straně aplikačního serveru.
Rozdělení SSO procesu na části
V případě protokolu Kerberos je SSO jeho nativní vlastnost, takže vlastně vždy jde o Kerberos autentizaci nebo jinak řečeno, při autentizaci se vždy využívá SSO.
Z důvodů identifikace problémů si můžeme proces SSO rozdělit na tři části.
- vyjednání Kerberos autentizace – síťová služba (server) musí vyjednat autentizaci a vyžadovat Kerberos, klient jej musí podporovat
- získání Service Ticket – klient musí získat Service Ticket pro danou službu od KDC (DC)
- odeslání a zpracování ticketu – klient pak musí odeslat autentizační údaje (včetně Service Ticket) na síťovou službu (server) a ten je musí zpracovat = dojde k přihlášení
Vyjednání Kerberos autentizace
Asi to zní jasně, že síťová služba, ke které se chceme přihlásit, musí podporovat Kerberos a mít jej nastavený. Stejně tak klient, kterým se přihlašujeme, musí mít povoleno použití Kerberosu. Přesto často bývá problém hned v tomto bodě.
Server požaduje Kerberos autentizaci
Aby server (síťová služba) mohl použít Kerberos, tak musí být buď členem AD domény, nebo se může vytvořit ruční záznam pro tuto službu v AD a vyexportovat klíč (secret key služby = keytab soubor). Tento klíč pak nastavíme aplikačnímu serveru nebo aplikaci, dle toho kdo Kerberos autentizaci provádí.
Pokud se připojujeme na webovou stránku, která vyžaduje Kerberos autentizaci, tak nám tato stránka odešle v hlavičce autentizační požadavek Negotiate (mechanizmus SPNEGO), aby se vyjednal autentizační protokol. Pro kontrolu, že tomu tak je, si můžeme prohlédnout hlavičky v prohlížeči nebo použít program Wireshark (asi nejznámější analyzátor síťového provozu Wireshark, případně použít nějaký jiný) pro zachycení celé komunikace.
Ve Wiresharku můžeme zachytit komunikaci mezi stanicí a webovým serverem (zachytávat můžeme přímo na stanici). Při požadavku prohlížeče na zobrazení určité stránky (tedy HTTP GET), by měla přijít odpověď (Response), která v hlavičce obsahuje HTTP/1.1 401 Authorization Required
a WWW-Authenticate: Negotiate
.

K podobným údajům se dostaneme i z webového prohlížeče. Internet Explorer obsahuje Developer Tools, které otevřeme stiskem F12. Přepneme se na záložku Network, začneme zachytávat komunikaci a provedeme přístup na stránku, v Details pak máme Request/Response headers (nyní nás zajímá odpověď serveru, tedy response).

Ve Firefoxu můžeme obdobně využít Add-on Live http Headers nebo mnohem rozsáhlejší Firebug.
Pokud chceme přistoupit k nějaké síťové službě, tak v rámci daného protokolu (třeba SMB) přijde odpověď, kde je zabalená komunikace GSS-API a dojde k vyjednání autentizace. Princip je stejný jako u webové aplikace.
Klient podporuje Kerberos autentizaci
Klient dostane požadavek na autentizaci, v případě webové aplikace na vyjednání autentizace. Musí být splněno několik podmínek, aby mohl správně odpovědět. Nejprve si uvedeme trochu teorie.
Microsoft používá Integrated Windows Authentication (IWA), jinak řečeno také HTTP Negotiate Authentication, hlavně pro webové aplikace. IWA podporuje protokoly SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism), Kerberos v5 a NTLM (NT LAN Manager). Na webu se používá SPNEGO, tedy Negotiate, kde se vyjedná použití buď upřednostněného Kerberosu nebo NTLM (pokud se Kerberos nepovede). Windows poskytují API pro bezpečnostní operace SSPI (Security Support Provider Interface), což je proprietární varianta standardního GSSAPI (Generic Security Service Application Program Interface). SSPI používá NTLMSSP nebo Kerberos SSP. Autentizaci uživatele ve Windows zajišťuje Local Security Authority (LSA), která volá SSPI.
Kerberos v5 požaduje, aby měl klient přímé připojení do Active Directory. Při autentizaci vůči službě se vždy využije SSO, nikdy se nezadává jméno a heslo. Pokud není DC dostupný, tak se použije (jinak nedoporučovaný) protokol NTLM, který využívá jména a hesla (při autentizaci se odesílá hash). Že na klientovi neproběhla Kerberos autentizace, můžeme poznat dle toho, že se zobrazí modální okno pro zadání jména a hesla (případně můžeme na serveru vidět, pokud logujeme proces autentizace, že se provádí NTLM a ne Kerberos).
Pozn.: V určitých situacích se může přihlašovací dialog zobrazit, i když Kerberos autentizace proběhla. Je to v situaci, kdy přihlášený uživatel nemá oprávnění přistoupit ke službě (neprošel autorizací), takže máme možnost zadat credentials jiného uživatele. Ve webových aplikacích se většinou ošetřuje jinak, takže se případně zobrazí přihlašovací formulář a ne modální okno.

Aby mohla proběhnout Kerberos autentizace, tak klient musí být přihlášený k DC a tedy mít platný TGT. V případě webového prohlížeče musí být pro danou adresu serveru povolen Kerberos. To u Internet Exploreru znamená zařazení adresy nebo celé domény mezi Local Intranet, u Firefoxu nastavení proměnné network.negotiate-auth.trusted-uris
. To jsme podrobněji popsali v článku Kerberos SSO - nastavení Internet Exploreru a Firefoxu. Důležitá je i forma zápisu domén či adresy (pokud třeba nakonec zadáme navíc znak /, tak nám nebude fungovat).
Můžeme zkusit několik testů na klientovi. Například ověřit, jestli klient získá adresu doménového řadiče.
C:>nltest /dsgetdc:firma.local DC: \\dc.firma.local Address: \\10.0.0.10 Dom Guid: a9c7691a-3cf9-41dd-a35d-6bbf0316c84c Dom Name: firma.local Forest Name: firma.local Dc Site Name: Praha Our Site Name: Praha Flags: PDC GC DS LDAP KDC TIMESERV WRITABLE DNS_DC DNS_DOMAIN DNS_FOREST CLOSE_SITE FULL_SECRET WS The command completed successfully
C:\>nltest /dclist:firma.local Get list of DCs in domain firma.local' from '\\dc.firma.local' DC.firma.local [PDC] [DS] Site: Praha DC2.firma.local [DS] Site: Praha DC3.firma.local [DS] Site: Plzen The command completed successfully
Informace o uživatelském Kerberos Realm a tedy nastavení přihlášení do domény (druhý příklad ukazuje stanici mimo doménu).
C:>ksetup /dumpstate default realm = firma.local (NT Domain) No user mappings defined.
C:>ksetup /dumpstate Machine is not configured to log on to an external KDC. Probably a workgroup member Failed to create Kerberos key: 5 (0x5)
Nebo rovnou ověřit, že klient získal TGT a je tedy korektně ověřen u DC.
C:>klist tgt Current LogonId is 0:0x4c976 Cached TGT: ServiceName : krbtgt TargetName (SPN) : krbtgt ClientName : bouska DomainName : FRIMA.LOCAL TargetDomainName : FRIMA.LOCAL AltTargetDomainName: FRIMA.LOCAL ...
Získání Service Ticket
Když klient korektně vyjedná, že má použít Kerberos autentizaci, tak se obrátí na svoje KDC (tedy doménový řadič) a snaží se získat Service Ticket pro SPN serveru.
Kontrola Kerberos ticketů
Můžeme provést jednoduchou kontrolu, jestli klient získal požadovaný Service Ticket nebo ne. Pokud jej má, tak bude problém buď v předání na server, nebo zpracování serverem. Pokud ticket v cachi není, tak musíme zkoumat proces získání. Pomůže nám příkaz klist
, který vypíše všechny tickety, které klient získal. Jednotlivé tickety jsou číslovány a u každého je uvedena položka Server, která obsahuje SPN, a Client, kde je identita pro kterou byl ticket vystaven.
C:\>klist Current LogonId is 0:0x4c2b5 Cached Tickets: (10) #2> Client: bouska @ FIRMA.LOCAL Server: HTTP/www.firma.local @ FIRMA.LOCAL KrbTicket Encryption Type: RSADSI RC4-HMAC(NT) Ticket Flags 0x40a00000 -> forwardable renewable pre_authent Start Time: 4/25/2014 12:53:44 (local) End Time: 4/25/2014 22:18:52 (local) Renew Time: 5/2/2014 12:18:52 (local) Session Key Type: RSADSI RC4-HMAC(NT) Cache Flags: 0 Kdc Called: dc.firma.local
Případně můžeme cache tiketů vymazat, abychom viděli, že jsme jej opravdu získali při našem pokusu o přihlášení.
C:\>klist purge Current LogonId is 0:0x4c956 Deleting all tickets: Ticket(s) purged
Porovnání šifrování v ticketu
Pokud jsme získali správný tiket, tak ještě můžeme zkontrolovat jeho šifrovací algoritmus (třeba v příkladu výše jde o RC4-HMAC-NT
) s šifrou použitou u keytab souboru. Pokud nevíme, jaká šifra se při vytváření keytab souboru použila, tak ji můžeme vypsat (příklad obsahuje opět RC4-HMAC-NT
).
C:\>ktpass -in server.keytab Existing keytab: Keytab version: 0x502 keysize 75 HTTP/www.firma.local@FIRMA.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 0 etype 0x17 (RC4-HMAC) keylength 16 (0x2ceaf8e1e3e9bd18967c1fb09bb0b8da) WARNING: No principal name specified.
Kontrola SPN záznamu
Pokud se nepodařilo získat Service Ticket, tak můžeme ověřit, že v doméně existuje požadovaný SPN záznam.
C:\>setspn -Q HTTP/server.firma.local Checking domain DC=firma,DC=local CN=Server SSO,OU=Objekty,DC=firma,DC=local HTTP/server.firma.local Existing SPN found!
Případně můžeme hledat pomocí různých filtru.
setspn -Q HTTP/* setspn -Q */server.firma.local
Standardně setspn
hledá pouze v rámci lokální domény, pokud chceme hledat v celém lese, tak musíme přidat přepínač -f
, případně -t domain
pro hledání v určité doméně.
C:\>setspn -F -Q HTTP/* Checking forest DC=firma,DC=local ...
Příkaz setspn
nám takto může zjistit informace o existujících SPN v doméně, ale jeho primární funkce je nastavení SPN na nějaký účet v AD. Dále je příklad, jak SPN nastavit.
setspn –S HTTP/server.firma.local firma\účet
Pozn.: Pro webové aplikace, které neběží na IIS, bychom neměli potřebovat tento příkaz, protože používáme ktpass
pro vytvoření keytab souboru a ten zároveň nastaví SPN.
Získání ticketu z DC
Ve chvíli, když se připojujeme k síťové službě a má se získat Service Ticket, můžeme zachytit komunikaci mezi stanicí a DC pomocí Wiresharku. Do filtru zadáme slovo kerberos
a tím se nám vyfiltruje komunikace, která nás zajímá. V komunikaci bychom měli vidět packet Kerberos TGS-REQ
a případně TGS-REP
. Když se podíváme do požadavku, tak vidíme pro jaký server Server Name (Service and Instance) a v jakém Realm se požaduje ticket. Musí to odpovídat SPN, které máme v AD. Při určitém použití DNS aliasů zde můžeme vidět jinou adresu a pak se nenalezne SPN.

Odeslání a zpracování ticketu
Dostali jsme se do fáze, že klient získal správný Service Ticket a přesto neproběhne autentizace. Pak musíme ověřit, že se odesílají správné údaje na server a případně, že on správně data zpracovává.
Odeslání autentizace na server
Tak jak jsme zachytávali komunikaci, jestli přichází požadavek na Kerberos autentizaci, tak můžeme ověřit, jestli z klienta odchází Kerberos AP-REQ packet. U webové aplikace je zabalen do HTTP a je součástí hlavičky. Pokud si zobrazíme hlavičky v prohlížeči, tak pouze uvidíme, že v hlavičce je hodnota Authorization: Negotiate
a pokračuje šifrovaný text. Wireshark jej umí rozkódovat a detailně zobrazit.

Celý proces SSO pro webovou stránku vidíme na zachycené komunikaci níže.
- klient odeslal GET požadavek na zobrazení stránky, vrátila se mu odpověď, že je třeba vyjednat autentizaci (
HTTP/1.1 401 Authorization Required
) - protože byla vymazána cache ticketů, tak nejprve proběhlo získání TGT od DC (požadavek
KRB-AS-REQ
, odpověďKRB-AS-REP
) - následně získání Service Ticketu od DC (požadavek
KRB-TGS-REQ
, odpověďKRB-TGS-REP
) - v dalším GET požadavku na server se odeslaly autentizační údaje (byla tam zabalen požadavek
KRB-AP-REQ
) - tím došlo k přihlášení a byla zobrazena (vrácena) stránka

Testování Keytab souboru
Pokud řešíme autentizaci pro webovou aplikaci běžící na ne-MS webovém serveru, tak patrně využíváme Keytab soubor. Ve chvíli, kdy se ticket odešle na server, ale ten jej nedokáže zpracovat, může být problém právě v Keytab souboru. Na serveru se může zalogovat třeba chyba GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
. V takové situaci můžeme otestovat Keytab soubor a jeho fungování pro dané SPN.
K tomu slouží příkaz kinit
, který nalezneme v Linuxu nebo i na Windows, pokud nainstalujeme JRE (je součástí Javy). Dopředu si ale musíme připravit konfigurační soubor krb5.ini
a nahrát jej do C:\Windows
(nejjednodušší způsob). Jeho obsah může být různý, ale asi minimální konfigurace je následující.
[libdefaults] default_realm = FIRMA.LOCAL default_tkt_enctypes = rc4-hmac default_tgs_enctypes = rc4-hmac [realms] FIRMA.LOCAL = { kdc = dc.firma.local:88 } [domain_realm] .firma.local = FIRMA.LOCAL firma.local = FIRMA.LOCAL
Následně můžeme použít příkaz kinit
, kde zadáme náš Keytab soubor a SPN včetně Realmu (domény). Pokud je vše v pořádku, dostaneme následující odpověď.
C:\>kinit -k -t server.keytab -f "HTTP/www.firma.local@FIRMA.LOCAL" New ticket is stored in cache file C:\Users\bouska\krb5cc_bouska
V případě, že ne, tak dostaneme chybu.
C:\>kinit -k -t server.keytab -f "HTTP/www.firma.local@FIRMA.LOCAL" Exception: krb_error 0 No supported key found in keytab for principal HTTP/www.firma.local@FIRMA.LOCAL No error KrbException: No supported key found in keytab for principal HTTP/www.firma.local@FIRMA.LOCAL at sun.security.krb5.internal.tools.Kinit.<init>(Unknown Source) at sun.security.krb5.internal.tools.Kinit.main(Unknown Source)
Pokud bychom neměli k dispozici soubor krb5.ini
, tak dostaneme chybu, která o tom informuje.
Exception: krb_error 0 Could not load configuration file C:\WINDOWS\krb5.ini (The system cannot find the file specified) No error
Kontrola serveru
Pokud ověříme, že celý proces autentizace korektně funguje až k poslání údajů na server, tak zbývá jediná možnost, hledat problém při zpracování ticketu serverem. Pokud jde o webovou aplikaci, tak se můžeme podívat do logu aplikačního serveru (případně nastavit podrobnější logování) či aplikace (pokud provádí autentizaci přímo ona). Pokud jde o nějakou službu Windows, tak můžeme hledat v Event Logu systému, případně debugovat Kerberos.
Jedna z chyb, která může nastat, je také překročení velikosti autentizačního ticketu. V něm se odesílají informace o uživateli, které obsahují seznam jeho skupin. U webové aplikace může dojít k překročení velikosti http hlavičky, u síťové služby velikosti bufferu pro token. Více informací je v článku Kerberos autentizace a členství ve skupinách.
Debuging Kerberosu
Jenom jako poznámku na okraj si zmíníme možnost, zapnout debugování či podrobnější logování protokolu Kerberos.
Kerberos Event Logging zapneme vytvořením hodnoty LogLevel = 1
typu REG_DWORD v registrech HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters
. Popis je v KB How to enable Kerberos event logging. Na stejném místě můžeme vytvořit další dvě REG_DWORD hodnoty LogToFile = 1
a KerbDebugLevel = c0000043
(nebo c3). Nějaké informace nalezneme Users experience authentication issues nebo zajímavém videu Kerberos Troubleshooting.
Komentáře
Skvělý článek, díky