Zrovna včera jsem řešil problém s počítačem, jehož účet do domény se nějak "poškodil" a on přestal s doménou komunikovat. Jedná se vcelku běžný problém, který si každý nejspíš několikrát zažil. Včera to bylo ještě trošku speciálnější, protože šlo o řadič té domény (DC - domain controller). Projevilo se to tak, že jeho služby běžící pod účtem SYSTEM a Network Service prostě nedokázaly komunikovat s jeho vlastním, lokálně běžícím, Active Directory. Například nenabíhal DNS server a hlásil, že se nemůže dostat do domény, i když Active Directory normálně běžela.
O účtech počítačů jsem tu už psal, takže to se rozepisovat nebudu kromě malého připomenutí a shrnutí. Ale chtěl bych vysvětlit, proč a kdy se tyto chyby občas dějí, a že to není vlastně nic divného.
Fakta o účtu počítače
Počítače mají svoje heslo v registrech ve formě LSA secret v klíči MACHINE$.ACC. Tam je v plné formě. Toto heslo se uloží na účet počítače v Active Directory při připojení počítače do domény a poté si ho počítače každých 30 dnů samy mění. V Active Directory je heslo uloženo normálně ve formě hash, stejně jako všechno ostatní hesla.
Po změně má v registrech počítač svoje aktuální heslo a pro hladkost běhu ještě i heslo předchozí, aby ještě dokázal přijímat dříve vydané Kerberos TGS tickety svých klientů (pokud je to server pro nějaké klienty). Sám používá hned a pouze jen to nové heslo při komunikaci s DC - AD replikační prodlevy tu nehrají roli, protože máte PDC, a tudíž se to chová stejně jako v případě normálních uživatelských účtů.
Hesla počítačových účtů nikdy nevyprší. To znamená, že počítače si hesla mění samy dobrovolně. Pokud si heslo z nějakého důvodu počítač nezmění, prostě používá i nadále to původní. Například není problém, abyste měli stroj třeba rok vypnutý, po startu se s doménou spojí v pořádku. I když bude počítač několik měsíců mimo vnitřní síť (bez VPN), tak se zase nic neděje, i když celou dobu jede. V průběhu své nepřítomnosti se pokouší heslo změnit, nemůže kontaktovat AD, tak si ho samozřejmě nezmění.
Heslo počítače používají služby běžící pod účtem SYSTEM, Network Service, IIS APPPOOL a NT SERVICE pro přístup do sítě. Pokud by se heslo nějak poškodilo, tak nebude počítači fungovat například:
- dynamická aktualizace vlastních DNS A záznamů v DNS, pokud to obvykle vyžaduje secure dynamic update
- vydávání certifikátů počítače z AD CS
- aktualizace zásad skupin (group policy) počítačového účtu. Zatímco uživatelské zásady se dříve stahovaly pod účtem uživatele, dnes už se nebudou stahovat ani ty
- lokální interaktivní přihlašování (ctrl-alt-del) uživatelů, kteří nejsou nakešovaní. Účty uživatelů, které jsou na počítači nakešované od předchozích přihlášení se normálně přihlásí a dokonce se mohou pohybovat po síti, protože jejich účet je v pořádku. Lidé to sami moc tedy nepoznají, takže to bývá mnohdy dost dlouho neviditelné
- ze sítě se na počítač s ověřením nedostanete a je jedno, jestli to je Kerberos, nebo NTLM
- tím pádem nelze na počítač nic vzdáleně instalovat, ani se k němu nepřipojí žádný manadžovací server typu SCCM, SCOM, antivirový server apod.
- na počítač se nedostanete ani přes RDP, protože NLA vás dál nepustí (to je to stejné, jako že se tam nedá dostat ze sítě na sdílené adresáře ani do WMI, PS Remoting apod.)
Obvyklé chybové hlášky při pokaženém hesle jsou:
Trust relationship between this workstation and primary domain failed
Target principal name is incorrect
Event ID: 5722
Source: NETLOGON
Event Type: Error
The session setup from the computer ComputerName failed to authenticate. The name of the account referenced in the security database is Computer$.
Oprava hesla se provede odpojením a opětovným připojením počítače do domény, nebo pomocí NETDOM RESETPWD, nebo pomocí Reset-ComputerMachinePassword. Samozřejmě pouze lokálně, protože vzdáleně se na mašinu nedostanete.
Proč se to proboha děje?
A dostáváme se konečně k jádru článku :-) Jak se to stane? Jak se to staně i DC samotnému? Jednoduše. Změna hesla není transakčně bezpečná.
Uvědomte si, o co se jedná při změně hesla počítače. Jde o distribuovanou transakci mezi dvěma mašinami. Vstupuje do toho počítač a DC. Počítač si vytvoří TCP spojení na DC a uvnitř nechá provést změnu hesla (ověří se, provede změnu buď přes SMB, DCOM nebo Kerberos). DC provede kontrolu kvality hesla a případně ho pomocí nějakého password filteru odešle do dalších připojených systémů. Následně si DC vypočítá jeho hash a tuto si uloží do Active Directory.
Když je heslo uloženo v AD, tak se po tom stejném TCP spojení pošle klientovi informace, že všechno je ok. Až tuto informaci klient dostane, uloží si nové heslo do registrů a původní heslo si pošoupne v registrech do zálohy. A je hotovo.
Jenže co se stane, když třeba:
- data na disk se z Active Directory zapisují asynchronně, takže pokud DC zrovna klekne/zdechne/spadne/vypadne elektřina, tak se nové heslo do AD ve skutečnosti neuloží. Po příštím náběhu je v AD stále ještě heslo staré, zatímco stanice už chce používat jen to novější. V tomto případě se třeba i nadále dá na stanici dostat ze sítě, zatímco stanice si už nedokáže stahovat sama politiku.
- co když upadne TCP spojení zrovna v okamžiku, kdy si AD uložilo heslo u sebe? V ADčku je heslo nové, stanice ale nedostala potvrzení o změně. Stanice tedy nové heslo u sebe neuloží a bude používat i nadále heslo starší. Což už použít nejde, protože AD má heslo novější, které ovšem stanice nezná. A šmitec.
- stejně tak registry na stanici, ty se také zapisují na disk asynchronně. Takže pokud hned po změně dojde k výpadku proudu na počítači, tak se registry neuloží a opět stanice nové heslo nezná, zatímco na DC je přepsané.
A tak bych nmohl pokračovat. Nicméně síťové výpadky jsou nejspíš ten nejčastější důvod. Uvědomte si, jak často lidé přechází s notebookem z kabelu na wifi a na jinou wifi, a která také často padá. Síťová zařízení jsou občas přetížena atd.
Je to jen občas, ale ochrana proti tomu není žádná. Samozřejmě by mohl Microsoft vyvinout nějaký robustní transakční systémy, kdy se jak na AD, tak na počítačích tyto změny dokázaly roll-backnout v případě výpadků, ale to je tak složité a přitom neúspěch tak málo pravděpodobný, že to prostě řešit nechtěli.
Jednoduše si heslo resetnete, když se to projeví a hotovo.
Zajímavé je samozřejmě, že se to děje i na DC samotných. DC má také svůj účet, heslo v registrech a heslo v AD. Sice oboje na jedné mašině lokálně, ale procedura je stejná. I lokálně můžete mít výpadky proudu, pády služeb, nebo výpadek síťového spojení (zakvedlejte kabelem, nebo vypněte switch, uvidíte).
Snapshot, imidž, checkpoint
Prosím vás, i tohle je jeden z důvodů, proč nepoužívat virtualizační snapshoty, checkpointy, nebo diskové image, a jak je to nejisté. Možná vám virtualizace nabízí různé ochrany typu GenerationID, ale pokud vrátíte staré heslo, tak není cesta, jak to "samo"opravit a musíte stejně zasáhnout ručně.