Kerberos problemer på webserveren?

Jeg har tidligere skrevet om problemer med kerberos´ tokenstørrelser i forhold til at logge på ADFS servere, men det gælder alle webservices der understøtter kerberos og jeg synes derfor jeg ville lave en uddybende forklaring og også give den helt rigtige opskrift på hvordan man retter sin egen http.

Problemet med et for stort kerberos token opstår når der er brugere der er medlem af så mange Active Directory grupper at deres token bliver for stort til at kunne overføres via http protokollen. Grundlæggende tillader http på en windows server at tokenet er 16384 Byte stort altså 16KB. Dette kan man rette ganske simpelt, men der er nogle overvejelser man skal gøre sig før man begiver sig ud i det. Den første er hvor meget ram man har i serveren kontra hvor mange brugere der tilgår serveren samtidig. Eksemplet i denne artikel omhandler en exchange server der reelt kun videresender brugere der leder efter deres exchange server (autodiscover) og i det tilfælde er der ingen fare ved at udvide til 64Kb altså en faktor 4 i forhold til det serveren accepterer ved installation. Men hvis ens server i forvejen er belastet eller er tæt på at være det, kan det betyde nedsatte svartider og dårligere service overfor ens brugere. Så vær varsom.

Selve tilretningen er simpel og bør ikke tage særlig lang tid, men husk på at når http servicen genstarter, afbryder den forbindelsen til alle brugere der er forbundet. Så alt efter forretningens politik for den slags, skal man nok forberede brugerne og foretage tilretningen udenfor perioder hvor serveren er tungt belastet.
For at rette størrelsen på det tilladte token skal vi have fat i nøglen HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters i registreringsdatabasen. Under denne skal vi lægge 2 nye parametre ind, mm de er der allerede så skal vi bare tilrette dem. ;) Parametrene er MaxFieldLength og MaxRequestBytes og de skal se ud som nedenstående for at øge værdien til 64K.

“MaxFieldLength”=dword:0000fffe
“MaxRequestBytes”=dword:0000fffe

Når disse er lagt ind skal vi have genstartet http servicen. Denne er ikke tilgængelig under services konsollen da det er en kernelservice. Den skal stoppes og startes fra en kommando prompt ved at skrive:

Net stop http

Bemærk at den forespørger om man nu er sikker og samtidig fortæller hvad den trækker med ned. De services den trækker med ned kommer ikke op igen når http servicen startes, de skal startes manuelt. Jeg gør det normalt fra en powershell prompt og så laver jeg et hurtigt lille script der starter de berørte services, på den måde kan jeg minimere mine nedetider til få minutter. I dette tilfælde meddeler http at den stopper 5 ekstra services:

net stop http

 

 

 

 

for at starte dem enkeltvis i powershell skrives:
start-service servicenavn

Efter gentart af http servicen og start af de 5 services er webserveren klar til at modtage brugere med token størrelser på op til 64k. Så kan man spørge sig selv hvorfor jeg ikke korrigerer for base64 encodingen og sætter grænsen til 48K? Det er fordi problemet her er hvor meget der kan overføres til serveren og der er base64 encodingen ikke et problem. Det er til gengæld meget vigtigt når man vælger MaxTokenSize på sine klienter. For hvis man tillader dem at benytte tokens der er større en 48K, risikerer de ikke at kunne logge på webservere når deres token er blevet base64 obfuskeret. ;)

Oprettelse af AD bruger fra Powershell

Nu er oprettelse af en bruger fra powershell ikke ligefrem hjernekirurgi, men der er alligevel nogle detaljer der kan besværliggøre det.

Oprettelse af en bruger er simpelt: New-Aduser “Michael Hovej”

Problemet med min nye bruger er at han ikke kan logge på, men det løser man vel ved at skrive: New-ADUser “Michael Hovej” -PassThru | Enable-ADAccount ikke?

Desværre er det ikke så simpelt. Min nye bruger har ikke fået defineret et kodeord og da AD ikke vil aktivere brugere der ikke har et kodeord, skal det sættes først. Men mon ikke det så bare er at skrive New-ADUser “Michael Hovej” -AccountPassword “Password01″ -PassThru | Enable-ADAccount? Igen nej. Powershell smider ikke et kodeord videre til AD i klar tekst. Kodeord skal skrives som såkaldte secure-strings. Der er 2 måder. Den ene måde er at samle det op i en variabel som vist her:       $Cred =  Read-Host “Indtast Password” -AsSecureString og så bruge variablen til at sætte kodeord med, som her: New-ADUser “Michael Hovej” -AccountPassword $Cred -Passthru | Enable-ADAccount Nu er brugeren oprettet og aktiveret.

Der er som sagt 2 måder og den anden muliggør at vi laver brugeren, sætter kodeord og aktiverer brugeren i en “one-liner” og det er jo så sexet som det kan blive. ;)

New-ADUser “Michael Hovej” -AccountPassword (ConvertTo-SecureString “Password01″ -AsPlainText -Force) -PassThru | Enable-ADAccount

Bemærk parameteren -PassThru som sender det objekt der lige er lavet videre til næste kommando, meget smart. Skal ovenstående bruges sammen med en csv import skal man bare køre den med en for-each som her:

Import-Csv “sti til csv fil” | ForEach-Object {New-ADUser $_.Name -AccountPassword (ConvertTo-SecureString “Password01″ -AsPlainText -Force) -PassThru | Enable-ADAccount

$_.Name er så “Michael Hovej” i csv filen og man kan selvfølgelig smide alle de variabler ind fra csv´en som det er muligt og så oprette en bunke brugere.

Voila er vist ordet. ;)

Installation af en ADFS Proxy server

Jeg har gennemsøgt nettet efter en guide til installation af en ADFS proxy server og jeg er endnu ikke lykkedes med at finde en der er komplet. Dette er så mit forsøg på at lave en guide der indeholder alle forudsætningerne for at installere en ADFS Proxy server.

Først en beskrivelse af mit miljø, da det kan være afgørende på et punkt. Jeg har et standard setup med en ADFS på et internt net og en proxy i en DMZ. Den interne Server benytter et certifikat fra mit eget PKI og den eksterne benytter (selvfølgelig) et certifikat fra en standard certifikat udbyder. Hvis man læser best practices for ADFS installationer, skulle dette være den helt rigtige og sikre måde at gøre det på.

En installation kræver følgende:

En windows server 2008 r2. Den behøver ikke være meldt ind i et domæne, men hvis det ønskes for nemmere administration af serveren, skal det være et andet domæne end det den interne ADFS server er meldt ind i.

ADFS v2 softwaren:
http://www.microsoft.com/en-us/download/details.aspx?id=10909

Update roll-up package 2.0:
http://support.microsoft.com/kb/2681584

Certifikater:
Rod CA for det certifikat der er benyttet på den interne ADFS server eller farm og det offentlige certifikat der skal benyttes på webserveren.

Trin for trin:

Installer ADFS softwaren

Installer certifikater i computerens CAPI store. (vejledning)

Installer certifikat på webserveren. (Vejledning)

Start Active Directory Federation Services Proxy Wizard. Når du kommer til establish trust delen, skal du være opmærksom på at brugeren der skal benyttes til at godkende med, er den bruger som ADFS servicen på den interne ADFS server benytter.

Dette er alt der skal til. Der hvor jeg mener der er afgørende mangler i de beskrivelser jeg har set online, er at ingen nævner Rod CA for certifikatet der er installeret på de interne ADFS servere og fejlbeskrivelsen der dukker op når det mangler, er ikke til at forstå.

Installation af Certifikat i IIS 7.0

For at installere et certifikat i IIS 7.0 og knytte det til en web side, skal man gøre som beskrevet her. Bemærk at certifikatet skal være installeret i computerens kontekst for at webserveren kan se certifikatet. Hvordan det gøres, kan man se her.

Åbn IIS Manager og højreklik på default website | Vælg Edit bindings

IIS Cert 1

 

 

 

 

 

 

 

 

Vælg certifikatet i drop-down menuen

IIS Cert 2

Bemærk at jeg har fjernet IP-Adressen og certifikat navn. ;)

 

 

 

Installation af certifikater i computerens kontekst

Ved installation af certifikater på en windows server skal man installere dem i Computerens kontekst. Dette er en kort vejledning i hvordan dette gøres.

Start en MMC

1

Bemærk at man ikke kan tage genvejen til capi-store og starte certmgr.msc, dette vil starte i brugerens kontekst og gøre at computerens services eller programmer ikke kan se certifikaterne.

 

 

 

Vælg File | Add/Remove Snap-in… eller tryk ctrl-m

 2

 

Vælg Certificates og tryk på Add >

3 

 

 

 

 

 

Vælg Computer account

4

 

 

 

 

 

 

 

 

 

 

Vælg Local computer…. og tryk på Finish

5

 

 

 

 

 

 

 

 

 

 

Tryk på OK

6 

 

 

 

 

 

Udvid Certificates | All Tasks |Import

 7

 

Herefter starter Certificate Import Wizard´en – Tryk på Next

 8

 

Skriv stien til certifikat filen og tryk på Next

9 

 

 

 

 

 

 

 

 

 

 

Vælg Automatically select the……. og tryk på Next

10

 

 

 

 

 

 

 

 

 

 

 

Tryk på Finish og glæd dig over at du nu har installeret et certifikat som dine web-servere og andre computer services kan se ;)

11 

 

 

 

 

Osso Buco

Ingredienser:

  • 4  skiver skank, ca. 2 cm tykke
  • hvedemel
  • groft salt
  • peber
  • 50 g fedtstof
  • 250 g små løg
  • 250 g gulerødder
  • 250 g knoldselleri
  • 1 dl rødvin
  • 250 ml cremefine
  • 2 dl oksebouillon
  • 1 dåse flåede tomater
  • 140 g tomatpure
  • 2 tsk merian
  • 3 laurbærblade

osso buco

Fremgangsmåde

Mel, salt og peber blandes i en dyb tallerken. Løg, gulerødder og knoldselleri skæres i grove tern. Vend kødet i melblandingen og brun dem kort i en stor gryde. Når kødet er brunet tages det op. Løgene smides i den stadig varme gryde. Når løgene begynder at blive lidt bløde (5 min), smides gulerødder og knoldselleri i og skal have ca 5 min sammen med løgene på jævn varme. Rødvin i, skru lidt op og lad det koge lidt under omrøring. Cremefine i sammmen med tomatpure og rør det godt igennem. Oksebouillon, flåede tomater, merian og laurbærblade røres i. Når det er kommet op i kog igen, tilsættes salt og peber. Læg kødstykkerne i og sørg for de er dækket af væde. Jeg plejer at røre lidt i hele gryden så det hele bliver blandet godt.

Skru ned på laveste blus og lad det stå og simre i 3-4 timer.

Serveres med kartoffelmos eller ris.

ADFS fejlfinding

Jeg har brugt det meste af 2 dage på at finde en fejl i et ADFS system hvor enkelte brugere, ikke får lov at logge på systemer der ellers er federede med ADFS farmen.

Problem:

Når brugeren tilgår en side hos en federationspartner, bliver han som forventet sendt videre til ADFS serverens webside sts.domænenavn.dk. Men istedet for at blive logget på eller bedt om brugernavn/password, får han en 400 error.

Hurtigt tænkte jeg at dette kunne være et problem med brugerens token størrelse. Husk på at antallet af grupper en bruger er medlem af, øger størrelsen på det token han bruger til at opnå godkendelse med, når kerberos benyttes. Jeg talte hans grupper ved at bruge repadmin til at vise hans grupper.

repadmin /showobjmeta DCBrugerens DN” /nocache /linked >c:\temp\objectmeta.txt

Åbn objectmeta.txt i excel og så har du et overblik over hvor mange grupper han har. Dette burde kunne gøres i powershell med measure-object eller count, men jeg brugte en quick and dirty, da problemets omfang ikke tillod tid til at lege! ;)

Brugeren havde 400 grupper og alt efter hvilken type grupper det er kan hans token udemærket være ude over grænsen på 12KB som er standard i windows. Jeg øgede derfor MaxTokenSize på serverne og genstartede services, dette hjalp ikke. Her gjorde jeg noget dumt og troede at hans token ikke var en del af problemet.

Næste step var at undersøge om brugeren havde specielle settings vedr. kerberos delegation. Men heller ikke her var der noget at komme efter.

Jeg loggede også på med brugeren og tjekkede loggen på den DC han kom via og så at han benyttede kerberos mod andre systemer uden problemer.

Tjekkede at brugeren ikke havde nogle politikker enablet der kunne forårsage dette, ved at køre RSOP og tjekke network security settings, heller intet at se.

Til sidst benyttede jeg Microsoft Network monitor 3.4 til at se trafikken når brugeren loggede på. Umiddelbart var der intet at bemærke, men når han ramte webserveren kunne jeg se at han rent faktisk begyndte at overføre sit token, men at webserveren så til sidst smed ham af og meldte fejl 400. Altså nægter webserveren ham ikke at logge på men kan ikke modtage hele hans token.

Forvirringen i hele dette er at MaxTokenSize indstillingen giver os lov til at benytte tokens der er større end default og det burde vel have løst dette problem? NEJ for problemet er ikke kun størrelsen af tokenet der må benyttes. Problemet er derimod hvor stort et token der må overføres i request headeren til serverens http service. Husk på at tokenet bliver overført, base 64 encoded til http servicen i request headeren. Denne tillader også kun 12KB standard. Efter at have rettet MaxFieldLength og MaxRequestBytes, genstartet http servicen og startet alle de andre services igen manuelt, på alle serverne, virkede det!

Sammenligning af tekstfiler

Jeg trækker ofte større lister ud af forskellige systemer og skal sammenligne listerne. Sålænge det er sammenlignelige data, eks brugernavne, burde det vel være en simpel sag..? Ja, sålænge det drejer sig om et lille antal. Men jeg sammenligner ofte tusindvis af eks brugernavne. Til det benytter jeg compare-object i Powershell.
Først skal man sikre sig at ens data grundlag er ens, altså har man 2 komma-separerede dokumenter der indeholder brugernavne, skal de enten KUN indeholde brugernavne eller også skal man kopiere brugernavnene over i en fil, så de er for sig selv. Jeg laver ofte 2 txt filer, lad os kalde dem compare1 og compare2. For at disse kan sammenlignes skal man hente indholdet af dem over i en variabel. Sammenligner man dem ved at skrive filnavnene som compare objekter, fortæller Compare-Object dig at filerne ikke er ens og det er jo i grunden korrekt. Men da det er indholdet vi vil have sammenlignet henter vi dem altså først ind i en variabel ved at skrive:

$Comparefile1 = Get-Content “sti”\compare1.txt

og ligeså for næste fil

$Comparefile1 = Get-Content “sti”\compare2.txt

Nu har vi altså 2 variabler der indeholder vores brugernavne (hvis det er det der er i filerne) og disse sammenligner man så ved at skrive:

Compare-Object $Comparefile1 $Comparefile2

Outputtet ligner dette:
User1 <=
User2 =>
Hvilket betyder at User1 er i comparefile1, User2 er i comparefile2.

Ønsker man også at have de brugere der er ens med, skal man bruge parameteren -includeequal og så bliver kommandoen:

Compare-Object $Comparefile1 $Comparefile2 -IncludeEqual

Outputtet ligner så dette:
User1 <=
User2 =>
User3==
Hvilket betyder at User1 er i comparefile1, User2 er i comparefile2 og User3 er i begge filer.

Ovenstående giver output til skærm og det er måske godt nok, men hvis det skal bruges efterfølgende kan man selvfølgelig også sende det til en komma-separeret fil ved at skrive følgende:

Compare-Object $Comparefile1 $Comparefile2 -IncludeEqual | Export-Csv C:\temp\csvfil.csv

Ekstern tidskilde på Domæne Controller

Det er essentielt for et domæne at tiden på de respektive servere og klienter er ens. Derfor synkroniserer domænecontrollere deres tid med den domænecontroller der ejer rollen som PDC Emulator. For at sikre at tiden går korrekt, vil det derfor være anbefalelsesværdigt at PDC Emulatoren benytter sig af en tidskilde der er sikker. Og det er IKKE det interne ur i serveren.. :)

Proceduren er som følger:

Først og fremmest plejer jeg at tjekke forskellen mellem den nuværende tid og den tiddserver jeg vil benytte. Dette gør jeg både før og efter for at sikre mig at det virker.

I en kommandoprompt skrives w32tm /stripchart /COMPUTER:<tiddserver>

Dette vil give følgende output til skærmen:

10:05:22 d:-00.0000279s o:+00.0208820s  [                           *
                ]
10:05:24 d:-00.0000342s o:+00.0202181s  [                           *
                ]
Indtil man breaker det.  D: er delay og O: er off-set mellem urene. Bemærk at jeg har taget output fra en server der er synkroniseret med den tidskilde jeg også tester imod og der er derfor ikke de store afvigelser. I et normalt miljø hvor der endnu ikke er angivet eksterne tidskilder vil der være en større afvigelse.

For at sætte tidskilden skrives følgende:

w32tm /config /manualpeerlist:”<tidsserver1>,0×01 <tidsserver2>,0×01″ /Syncfromflags:MANUAL /update

0×01 angivet efter serveren betyder at serveren skal benytte poll-interval som angivet i reg-nøglen:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\
NtpClient\SpecialPollInterval

Som default er denne sat til 3600 og synkroniserer altså hver time. De poll-intervaller man kan benytte er:

0×01 SpecialInterval

0×02 Use As FallbackOnly

0×04 SymmetricActive

0×08 Client

I langt de fleste tilfælde benytter man 0×01.

Når så en eller flere tidsservere er angivet, kan man bede serveren synkronisere med det samme ved at skrive:

w32tm /resync /rediscover /nowait

Dette er alt der skal gøres for at indstille en server til at benytte en ekstern tidskilde.