前幾天在給人解釋Windows是如何經過Kerberos進行Authentication的時候,講了半天也別把那位老兄講明白,還差點把本身給繞進去。後來想一想緣由有如下兩點:對於一個沒有徹底不瞭解Kerberos的人來講,Kerberos的整個Authentication過程確實很差理解——一下子以這個Key進行加密、一下子又要以另外一個Key進行加密,確實很容易把人給弄暈;另外一方面是我講解方式有問題,一開始就從Kerberos的3個Sub-protocol全面講述整個Authentication 過程,對於一個徹底不瞭解Kerberos的人來講要求也忒高了點。爲此,我花了一些時間寫了這篇文章,儘可能以由淺入深、層層深刻的方式講述我所理解的基於Kerberos的Windows Network Authentication,但願這篇文章能幫助那些對Kerberos不明就裏的人帶來一絲幫助。對於一些不對的地方,歡迎你們批評指正。算法
1、 基本原理緩存
Authentication解決的是「如何證實某我的確確實實就是他或她所聲稱的那我的」的問題。對於如何進行Authentication,咱們採用這樣的方法:若是一個祕密(secret)僅僅存在於A和B,那麼有我的對B聲稱本身就是A,B經過讓A提供這個祕密來證實這我的就是他或她所聲稱的A。這個過程實際上涉及到3個重要的關於Authentication的方面:安全
基於這3個方面,咱們把Kerberos Authentication進行最大限度的簡化:整個過程涉及到Client和Server,他們之間的這個Secret咱們用一個Key(KServer-Client)來表示。Client爲了讓Server對本身進行有效的認證,向對方提供以下兩組信息:網絡
因爲KServer-Client僅僅被Client和Server知曉,因此被Client使用KServer-Client加密過的Client Identity只能被Client和Server解密。同理,Server接收到Client傳送的這兩組信息,先經過KServer-Client對後者進行解密,隨後將機密的數據同前者進行比較,若是徹底同樣,則能夠證實Client能過提供正確的KServer-Client,而這個世界上,僅僅只有真正的Client和本身知道KServer-Client,因此能夠對方就是他所聲稱的那我的。併發
Keberos大致上就是按照這樣的一個原理來進行Authentication的。可是Kerberos遠比這個複雜,我將在後續的章節中不斷地擴充這個過程,知道Kerberos真實的認證過程。爲了使讀者更加容易理解後續的部分,在這裏咱們先給出兩個重要的概念:分佈式
在通常狀況下,對於一個Account來講,密碼每每僅僅限於該Account的全部者知曉,甚至對於任何Domain的Administrator,密碼仍然應該是保密的。可是密碼卻又是證實身份的憑據,因此必須經過基於你密碼的派生的信息來證實用戶的真實身份,在這種狀況下,通常將你的密碼進行Hash運算獲得一個Hash code, 咱們通常管這樣的Hash Code叫作Master Key。因爲Hash Algorithm是不可逆的,同時保證密碼和Master Key是一一對應的,這樣既保證了你密碼的保密性,有同時保證你的Master Key和密碼自己在證實你身份的時候具備相同的效力。性能
2、引入Key Distribution: KServer-Client從何而來加密
上面咱們討論了Kerberos Authentication的基本原理:經過讓被認證的一方提供一個僅限於他和認證方知曉的Key來鑑定對方的真實身份。而被這個Key加密的數據包須要在Client和Server之間傳送,因此這個Key不能是一個Long-term Key,而只多是Short-term Key,這個能夠僅僅在Client和Server的一個Session中有效,因此咱們稱這個Key爲Client和Server之間的Session Key(SServer-Client)。spa
如今咱們來討論Client和Server如何獲得這個SServer-Client。在這裏咱們要引入一個重要的角色:Kerberos Distribution Center-KDC。KDC在整個Kerberos Authentication中做爲Client和Server共同信任的第三方起着重要的做用,而Kerberos的認證過程就是經過這3方協做完成。順便說一下,Kerberos起源於希臘神話,是一支守護着冥界長着3個頭顱的神犬,在keberos Authentication中,Kerberos的3個頭顱表明中認證過程當中涉及的3方:Client、Server和KDC。翻譯
對於一個Windows Domain來講,Domain Controller扮演着KDC的角色。KDC維護着一個存儲着該Domain中全部賬戶的Account Database(通常地,這個Account Database由AD來維護),也就是說,他知道屬於每一個Account的名稱和派生於該Account Password的Master Key。而用於Client和Server相互認證的SServer-Client就是有KDC分發。下面咱們來看看KDC分發SServer-Client的過程。
經過下圖咱們能夠看到KDC分發SServer-Client的簡單的過程:首先Client向KDC發送一個對SServer-Client的申請。這個申請的內容能夠簡單歸納爲「我是某個Client,我須要一個Session Key用於訪問某個Server 」。KDC在接收到這個請求的時候,生成一個Session Key,爲了保證這個Session Key僅僅限於發送請求的Client和他但願訪問的Server知曉,KDC會爲這個Session Key生成兩個Copy,分別被Client和Server使用。而後從Account database中提取Client和Server的Master Key分別對這兩個Copy進行對稱加密。對於後者,和Session Key一塊兒被加密的還包含關於Client的一些信息。
KDC如今有了兩個分別被Client和Server 的Master Key加密過的Session Key,這兩個Session Key如何分別被Client和Server得到呢?也許你 立刻會說,KDC直接將這兩個加密過的包發送給Client和Server不就能夠了嗎,可是若是這樣作,對於Server來講會出現下面 兩個問題:
爲了解決這個問題,Kerberos的作法很簡單,將這兩個被加密的Copy一併發送給Client,屬於Server的那份由Client發送給Server。
可能有人會問,KDC並無真正去認證這個發送請求的Client是否真的就是那個他所聲稱的那我的,就把Session Key發送給他,會不會有什麼問題?若是另外一我的(好比Client B)聲稱本身是Client A,他一樣會獲得Client A和Server的Session Key,這會不會有什麼問題?實際上不存在問題,由於Client B聲稱本身是Client A,KDC就會使用Client A的Password派生的Master Key對Session Key進行加密,因此真正知道Client A 的Password的一方纔會經過解密得到Session Key。
3、引入Authenticator - 爲有效的證實本身提供證據
經過上面的過程,Client實際上得到了兩組信息:一個經過本身Master Key加密的Session Key,另外一個被Sever的Master Key加密的數據包,包含Session Key和關於本身的一些確認信息。經過第一節,咱們說只要經過一個雙方知曉的Key就能夠對對方進行有效的認證,可是在一個網絡的環境中,這種簡單的作法是具備安全漏洞,爲此,Client須要提供更多的證實信息,咱們把這種證實信息稱爲Authenticator,在Kerberos的Authenticator實際上就是關於Client的一些信息和當前時間的一個Timestamp(關於這個安全漏洞和Timestamp的做用,我將在後面解釋)。
在這個基礎上,咱們再來看看Server如何對Client進行認證:Client經過本身的Master Key對KDC加密的Session Key進行解密從而得到Session Key,隨後建立Authenticator(Client Info + Timestamp)並用Session Key對其加密。最後連同從KDC得到的、被Server的Master Key加密過的數據包(Client Info + Session Key)一併發送到Server端。咱們把經過Server的Master Key加密過的數據包稱爲Session Ticket。
當Server接收到這兩組數據後,先使用他本身的Master Key對Session Ticket進行解密,從而得到Session Key。隨後使用該Session Key解密Authenticator,經過比較Authenticator中的Client Info和Session Ticket中的Client Info從而實現對Client的認證。
爲何要使用Timestamp?
到這裏,不少人可能認爲這樣的認證過程完美無缺:只有當Client提供正確的Session Key方能獲得Server的認證。可是在現實環境中,這存在很大的安全漏洞。
咱們試想這樣的現象:Client向Server發送的數據包被某個惡意網絡監聽者截獲,該監聽者隨後將數據包座位本身的Credential冒充該Client對Server進行訪問,在這種狀況下,依然能夠很順利地得到Server的成功認證。爲了解決這個問題,Client在Authenticator中會加入一個當前時間的Timestamp。
在Server對Authenticator中的Client Info和Session Ticket中的Client Info進行比較以前,會先提取Authenticator中的Timestamp,並同當前的時間進行比較,若是他們之間的誤差超出一個能夠接受的時間範圍(通常是5mins),Server會直接拒絕該Client的請求。在這裏須要知道的是,Server維護着一個列表,這個列表記錄着在這個可接受的時間範圍內全部進行認證的Client和認證的時間。對於時間誤差在這個可接受的範圍中的Client,Server會從這個這個列表中得到最近一個該Client的認證時間,只有當Authenticator中的Timestamp晚於經過一個Client的最近的認證時間的狀況下,Server採用進行後續的認證流程。
Time Synchronization的重要性
上述 基於Timestamp的認證機制只有在Client和Server端的時間保持同步的狀況纔有意義。因此保持Time Synchronization在整個認證過程當中顯得尤其重要。在一個Domain中,通常經過訪問同一個Time Service得到當前時間的方式來實現時間的同步。
雙向認證(Mutual Authentication)
Kerberos一個重要的優點在於它可以提供雙向認證:不但Server能夠對Client 進行認證,Client也能對Server進行認證。
具體過程是這樣的,若是Client須要對他訪問的Server進行認證,會在它向Server發送的Credential中設置一個是否須要認證的Flag。Server在對Client認證成功以後,會把Authenticator中的Timestamp提出出來,經過Session Key進行加密,當Client接收到並使用Session Key進行解密以後,若是確認Timestamp和原來的徹底一致,那麼他能夠認定Server正式他試圖訪問的Server。
那麼爲何Server不直接把經過Session Key進行加密的Authenticator原樣發送給Client,而要把Timestamp提取出來加密發送給Client呢?緣由在於防止惡意的監聽者經過獲取的Client發送的Authenticator冒充Server得到Client的認證。
4、引入Ticket Granting Service
經過上面的介紹,咱們發現Kerberos實際上一個基於Ticket的認證方式。Client想要獲取Server端的資源,先得經過Server的認證;而認證的先決條件是Client向Server提供從KDC得到的一個有Server的Master Key進行加密的Session Ticket(Session Key + Client Info)。能夠這麼說,Session Ticket是Client進入Server領域的一張門票。而這張門票必須從一個合法的Ticket頒發機構得到,這個頒發機構就是Client和Server雙方信任的KDC, 同時這張Ticket具備超強的防僞標識:它是被Server的Master Key加密的。對Client來講, 得到Session Ticket是整個認證過程當中最爲關鍵的部分。
上面咱們只是簡單地從大致上說明了KDC向Client分發Ticket的過程,而真正在Kerberos中的Ticket Distribution要複雜一些。爲了更好的說明整個Ticket Distribution的過程,我在這裏作一個類比。如今的股事很火爆,上海基本上是全民炒股,我就舉一個認股權證的例子。有的上市公司在股票配股、增發、基金擴募、股份減持等狀況會向公衆發行認股權證,認股權證的持有人能夠憑藉這個權證認購必定數量的該公司股票,認股權證是一種具備看漲期權的金融衍生產品。
而咱們今天所講的Client得到Ticket的過程也和經過認股權證購買股票的過程相似。若是咱們把Client提供給Server進行認證的Ticket比做股票的話,那麼Client在從KDC那邊得到Ticket以前,須要先得到這個Ticket的認購權證,這個認購權證在Kerberos中被稱爲TGT:Ticket Granting Ticket,TGT的分發方仍然是KDC。
咱們如今來看看Client是如何從KDC處得到TGT的:首先Client向KDC發起對TGT的申請,申請的內容大體能夠這樣表示:「我須要一張TGT用以申請獲取用以訪問全部Server的Ticket」。KDC在收到該申請請求後,生成一個用於該Client和KDC進行安全通訊的Session Key(SKDC-Client)。爲了保證該Session Key僅供該Client和本身使用,KDC使用Client的Master Key和本身的Master Key對生成的Session Key進行加密,從而得到兩個加密的SKDC-Client的Copy。對於後者,隨SKDC-Client一塊兒被加密的還包含之後用於鑑定Client身份的關於Client的一些信息。最後KDC將這兩份Copy一併發送給Client。這裏有一點須要注意的是:爲了免去KDC對於基於不一樣Client的Session Key進行維護的麻煩,就像Server不會保存Session Key(SServer-Client)同樣,KDC也不會去保存這個Session Key(SKDC-Client),而選擇徹底靠Client本身提供的方式。
當Client收到KDC的兩個加密數據包以後,先使用本身的Master Key對第一個Copy進行解密,從而得到KDC和Client的Session Key(SKDC-Client),並把該Session 和TGT進行緩存。有了Session Key和TGT,Client本身的Master Key將再也不須要,由於此後Client可使用SKDC-Client向KDC申請用以訪問每一個Server的Ticket,相對於Client的Master Key這個Long-term Key,SKDC-Client是一個Short-term Key,安全保證獲得更好的保障,這也是Kerberos多了這一步的關鍵所在。同時須要注意的是SKDC-Client是一個Session Key,他具備本身的生命週期,同時TGT和Session相互關聯,當Session Key過時,TGT也就宣告失效,此後Client不得不從新向KDC申請新的TGT,KDC將會生成一個不一樣Session Key和與之關聯的TGT。同時,因爲Client Log off也致使SKDC-Client的失效,因此SKDC-Client又被稱爲Logon Session Key。
接下來,咱們看看Client如何使用TGT來從KDC得到基於某個Server的Ticket。在這裏我要強調一下,Ticket是基於某個具體的Server的,而TGT則是和具體的Server無關的,Client可使用一個TGT從KDC得到基於不一樣Server的Ticket。咱們言歸正傳,Client在得到本身和KDC的Session Key(SKDC-Client)以後,生成本身的Authenticator以及所要訪問的Server名稱的並使用SKDC-Client進行加密。隨後連同TGT一併發送給KDC。KDC使用本身的Master Key對TGT進行解密,提取Client Info和Session Key(SKDC-Client),而後使用這個SKDC-Client解密Authenticator得到Client Info,對兩個Client Info進行比較進而驗證對方的真實身份。驗證成功,生成一份基於Client所要訪問的Server的Ticket給Client,這個過程就是咱們第二節中介紹的同樣了。
5、Kerberos的3個Sub-protocol:整個Authentication
經過以上的介紹,咱們基本上了解了整個Kerberos authentication的整個流程:整個流程大致上包含如下3個子過程:
不過上面的介紹離真正的Kerberos Authentication仍是有一點出入。Kerberos整個認證過程經過3個sub-protocol來完成。這個3個Sub-Protocol分別完成上面列出的3個子過程。這3個sub-protocol分別爲:
下圖簡單展現了完成這個3個Sub-protocol所進行Message Exchange。
1. Authentication Service Exchange
經過這個Sub-protocol,KDC(確切地說是KDC中的Authentication Service)實現對Client身份的確認,並頒發給該Client一個TGT。具體過程以下:
Client向KDC的Authentication Service發送Authentication Service Request(KRB_AS_REQ), 爲了確保KRB_AS_REQ僅限於本身和KDC知道,Client使用本身的Master Key對KRB_AS_REQ的主體部分進行加密(KDC能夠經過Domain 的Account Database得到該Client的Master Key)。KRB_AS_REQ的大致包含如下的內容:
AS(Authentication Service)經過它接收到的KRB_AS_REQ驗證發送方的是不是在Client name & realm中聲稱的那我的,也就是說要驗證發送放是否知道Client的Password。因此AS只需從Account Database中提取Client對應的Master Key對Pre-authentication data進行解密,若是是一個合法的Timestamp,則能夠證實發送放提供的是正確無誤的密碼。驗證經過以後,AS將一份Authentication Service Response(KRB_AS_REP)發送給Client。KRB_AS_REQ主要包含兩個部分:本Client的Master Key加密過的Session Key(SKDC-Client:Logon Session Key)和被本身(KDC)加密的TGT。而TGT大致又包含如下的內容:
Client經過本身的Master Key對第一部分解密得到Session Key(SKDC-Client:Logon Session Key)以後,攜帶着TGT即可以進入下一步:TGS(Ticket Granting Service)Exchange。
2. TGS(Ticket Granting Service)Exchange
TGS(Ticket Granting Service)Exchange經過Client向KDC中的TGS(Ticket Granting Service)發送Ticket Granting Service Request(KRB_TGS_REQ)開始。KRB_TGS_REQ大致包含如下的內容:
TGS收到KRB_TGS_REQ在發給Client真正的Ticket以前,先得整個Client提供的那個TGT是不是AS頒發給它的。因而它不得不經過Client提供的Authenticator來證實。可是Authentication是經過Logon Session Key(SKDC-Client)進行加密的,而本身並無保存這個Session Key。因此TGS先得經過本身的Master Key對Client提供的TGT進行解密,從而得到這個Logon Session Key(SKDC-Client),再經過這個Logon Session Key(SKDC-Client)解密Authenticator進行驗證。驗證經過向對方發送Ticket Granting Service Response(KRB_TGS_REP)。這個KRB_TGS_REP有兩部分組成:使用Logon Session Key(SKDC-Client)加密過用於Client和Server的Session Key(SServer-Client)和使用Server的Master Key進行加密的Ticket。該Ticket大致包含如下一些內容:
Client收到KRB_TGS_REP,使用Logon Session Key(SKDC-Client)解密第一部分後得到Session Key(SServer-Client)。有了Session Key和Ticket,Client就能夠之間和Server進行交互,而無須在經過KDC做中間人了。因此咱們說Kerberos是一種高效的認證方式,它能夠直接經過Client和Server雙方來完成,不像Windows NT 4下的NTLM認證方式,每次認證都要經過一個雙方信任的第3方來完成。
咱們如今來看看 Client若是使用Ticket和Server怎樣進行交互的,這個階段經過咱們的第3個Sub-protocol來完成:CS(Client/Server )Exchange。
3. CS(Client/Server )Exchange
這個已經在本文的第二節中已經介紹過,對於重複發內容就再也不累贅了。Client經過TGS Exchange得到Client和Server的Session Key(SServer-Client),隨後建立用於證實本身就是Ticket的真正全部者的Authenticator,並使用Session Key(SServer-Client)進行加密。最後將這個被加密過的Authenticator和Ticket做爲Application Service Request(KRB_AP_REQ)發送給Server。除了上述兩項內容以外,KRB_AP_REQ還包含一個Flag用於表示Client是否須要進行雙向驗證(Mutual Authentication)。
Server接收到KRB_AP_REQ以後,經過本身的Master Key解密Ticket,從而得到Session Key(SServer-Client)。經過Session Key(SServer-Client)解密Authenticator,進而驗證對方的身份。驗證成功,讓Client訪問須要訪問的資源,不然直接拒絕對方的請求。
對於須要進行雙向驗證,Server從Authenticator提取Timestamp,使用Session Key(SServer-Client)進行加密,並將其發送給Client用於Client驗證Server的身份。
6、User2User Sub-Protocol:有效地保障Server的安全
經過3個Sub-protocol的介紹,咱們能夠全面地掌握整個Kerberos的認證過程。實際上,在Windows 2000時代,基於Kerberos的Windows Authentication就是按照這樣的工做流程來進行的。可是我在上面一節結束的時候也說了,基於3個Sub-protocol的Kerberos做爲一種Network Authentication是具備它本身的侷限和安全隱患的。我在整篇文章一直在強調這樣的一個原則:以某個Entity的Long-term Key加密的數據不該該在網絡中傳遞。緣由很簡單,全部的加密算法都不能保證100%的安全,對加密的數據進行解密只是一個時間的過程,最大限度地提供安全保障的作法就是:使用一個Short-term key(Session Key)代替Long-term Key對數據進行加密,使得惡意用戶對其解密得到加密的Key時,該Key早已失效。可是對於3個Sub-Protocol的C/S Exchange,Client攜帶的Ticket倒是被Server Master Key進行加密的,這顯現不符合咱們提出的原則,下降Server的安全係數。
因此咱們必須尋求一種解決方案來解決上面的問題。這個解決方案很明顯:就是採用一個Short-term的Session Key,而不是Server Master Key對Ticket進行加密。這就是咱們今天要介紹的Kerberos的第4個Sub-protocol:User2User Protocol。咱們知道,既然是Session Key,僅必然涉及到兩方,而在Kerberos整個認證過程涉及到3方:Client、Server和KDC,因此用於加密Ticket的只多是Server和KDC之間的Session Key(SKDC-Server)。
咱們知道Client經過在AS Exchange階段得到的TGT從KDC那麼得到訪問Server的Ticket。原來的Ticket是經過Server的Master Key進行加密的,而這個Master Key能夠經過Account Database得到。可是如今KDC須要使用Server和KDC之間的SKDC-Server進行加密,而KDC是不會維護這個Session Key,因此這個Session Key只能靠申請Ticket的Client提供。因此在AS Exchange和TGS Exchange之間,Client還得對Server進行請求已得到Server和KDC之間的Session Key(SKDC-Server)。而對於Server來講,它能夠像Client同樣經過AS Exchange得到他和KDC之間的Session Key(SKDC-Server)和一個封裝了這個Session Key並被KDC的Master Key進行加密的TGT,一旦得到這個TGT,Server會緩存它,以待Client對它的請求。咱們如今來詳細地討論這一過程。
上圖基本上翻譯了基於User2User的認證過程,這個過程由4個步驟組成。咱們發現較之我在上面一節介紹的基於傳統3個Sub-protocol的認證過程,此次對了第2部。咱們從頭至尾簡單地過一遍:
這就是整個過程。
7、Kerberos的優勢
分析整個Kerberos的認證過程以後,咱們來總結一下Kerberos都有哪些優勢:
1.較高的Performance
雖然咱們一再地說Kerberos是一個涉及到3方的認證過程:Client、Server、KDC。可是一旦Client得到用過訪問某個Server的Ticket,該Server就能根據這個Ticket實現對Client的驗證,而無須KDC的再次參與。和傳統的基於Windows NT 4.0的每一個徹底依賴Trusted Third Party的NTLM比較,具備較大的性能提高。
2.實現了雙向驗證(Mutual Authentication)
傳統的NTLM認證基於這樣一個前提:Client訪問的遠程的Service是可信的、無需對於進行驗證,因此NTLM未曾提供雙向驗證的功能。這顯然有點理想主義,爲此Kerberos彌補了這個不足:Client在訪問Server的資源以前,能夠要求對Server的身份執行認證。
3.對Delegation的支持
Impersonation和Delegation是一個分佈式環境中兩個重要的功能。Impersonation容許Server在本地使用Logon 的Account執行某些操做,Delegation需用Server將logon的Account帶入到另過一個Context執行相應的操做。NTLM僅對Impersonation提供支持,而Kerberos經過一種雙向的、可傳遞的(Mutual 、Transitive)信任模式實現了對Delegation的支持。
4.互操做性(Interoperability)
Kerberos最初由MIT獨創,如今已經成爲一行被普遍接受的標準。因此對於不一樣的平臺能夠進行普遍的互操做。