Kerberos认证原理

Kerberos认证原理
去年做hadoop的时候使用kerberos,现在来整理一下它的原理,不对的地方请见谅
 
一、基本原理
Authentication解决的其实是如何证明你就是你说的那个人的问题,对于如何进行Authentication,一半采用这样的方法:如果一个秘密(Secret)仅仅存在于AB,那么有个人对B声称自己就是AB通过让A提供这个秘密来证明这个人就是他或她所声称的A,相当于局限于两个人所知道的口令一样。这个过程涉及到三个Authentication方面:
 
  Secret如何表示
  A一开始是如何向B提供这个Secret
  B又是如何识别这个Secert
 
基于这三个方面,对Kerberos Authentication进行简化,整个过程涉及到ClientServer,他们之间的SecretKeyKserver-client)来表示,Client为了让Server对自己进行有效认证,提供以下两组信息:
 
  代表Clientidentity的信息,为了简便,它以明文的形式进行传递
  Clientidentity使用Kserver-client作为公钥public key、并且采用对称加密算法进行加密
 
因为Kserver-client仅仅只被ClientServer知晓,所以被Client使用Kserver-client加密过的Client Identity只能被ClientServer解密,Server接受到这两组信息,先对后面的这条信息使用相对应的Kserver-client进行解密,然后将机密的信息与前面的一条信息进行比较,如果一致,可以证明这个Client能够提供正确的Kserver-client,而这个世界上仅仅只有这个ClientServer知道这个Kserver-client,所以对方就是他声称的那个人。

Kerberos基本上就是按照这样一种原理来进行Authencation认证的,但是kerberos远远比这个要复杂的多,为了后面更方面理解,先引入两个概念:
  Long-term Key/Master Key:在Security安全的领域中,有的Key可能长期内保持不变,比如你在密码,可能几年都不曾改变,这样的Key、以及由此派生的Key被称为Long-term Key。对于Long-term Key的使用有这样的原则:被Long-term Key加密的数据不应该在网络上传输。原因很简单,一旦这些被Long-term Key加密的数据包被恶意的网络监听者截获,在原则上,只要有充足的时间,他是可以通过计算获得你用于加密的Long-term Key——任何加密算法都不可能做到绝对保密。
 
在一般情况下,对于一个Account来说,密码往往仅仅限于该Account的所有者知晓,甚至对于任何DomainAdministrator,密码仍然应该是保密的。但是密码却又是证明身份的凭据,所以必须通过基于你密码的派生的信息来证明用户的真实身份,在这种情况下,一般将你的密码进行Hash运算得到一个Hash code, 我们一般管这样的Hash Code叫做Master Key。由于Hash Algorithm(哈希算法)是不可逆的,同时保证密码和Master Key是一一对应的,这样既保证了你密码的保密性,有同时保证你的Master Key和密码本身在证明你身份的时候具有相同的效力。
 
  Short-term Key/Session Key:由于被Long-term Key加密的数据包不能用于网络传送,所以我们使用另一种Short-term Key来加密需要进行网络传输的数据。由于这种Key只在一段时间内有效,即使被加密的数据包被黑客截获,等他把Key计算出来的时候,这个Key早就已经过期了。
 
二、引入Key Distribution(密钥分发):Kserver-client从何而来
第一节展示了Kerberos Authentication的基本原理,通过让被认证的一方提供一个仅限于他和认证方知晓的Key来鉴定对方的真实身份。而被这个Key加密的数据包需要在ClientServer之间传送,所以这个Key不能是一个Long-term Key,而只可能是Short-term Key,这个可以仅仅在ClientServer的一个Session(会话)中有效,所以我们称这个KeyClientServer之间的Session KeySServer-Client)。
 
  那么ClientServer是如何获取这个SServer-Client的,需要引入一个重要的角色:Kerberos Distribution Center-KDCKDC在整个Kerberos Authentication中作为ClientServer共同信任的第三方起着重要的作用,而Kerberos的认证过程就是通过这3方协作完成。顺便说一下,Kerberos起源于希腊神话,是一支守护着冥界长着3个头颅的神犬,在keberos Authentication中,Kerberos3个头颅代表中认证过程中涉及的3方:ClientServerKDC
 
个人打个比方,你钥匙忘记在了家里,这时候你叫来了一个开锁工人,开锁工人需要你提供相关证件证明这个房子就是你的才会去开门,可是你身上只有一张身份证,开锁工人可以肯定你是你所声明的那个人,但是并不能证明这个房子是你的,这时候你拿着身份证去你们两个人都信任的警察局,警察局根据你提供的身份证,先确认你是你声明的那个人,然后通过公安系统去查询你声明的那套房子是否是你的(这一步相当于解开根据你身份证所隐藏的其他信息),如果一致,这时候开锁工人就会帮你去开门。
 
对于一个Windows Domain来说,Domain Controller扮演着KDC的角色。KDC维护着一个存储着该Domain中所有帐户的Account Database(一般地,这个Account DatabaseAD来维护),也就是说,他知道属于每个Account的名称和派生于该Account PasswordMaster Key。而用于ClientServer相互认证的SServer-Client就是有KDC分发。下面我们来看看KDC分发SServer-Client的过程。
 
通过下图我们可以看到KDC分发SServer-Client的简单的过程:首先ClientKDC发送一个对SServer-Client的申请。这个申请的内容可以简单概括为“我是某个Client,我需要一个Session Key用于访问某个Server ”KDC在接收到这个请求的时候,生成一个Session Key,为了保证这个Session Key仅仅限于发送请求的Client和他希望访问的Server知晓,KDC会为这个Session Key生成两个Copy,分别被ClientServer使用。然后从Account database中提取ClientServerMaster Key分别对这两个Copy进行对称加密。对于后者,和Session Key一起被加密的还包含关于Client的一些信息。
 
KDC现在有了两个分别被ClientServer Master Key加密过的Session Key,这两个Session Key如何分别被ClientServer获得呢?也许你 马上会说,KDC直接将这两个加密过的包发送给ClientServer不就可以了吗,但是如果这样做,对于Server来说会出现下面 两个问题:
  由于一个Server会面对若干不同的Client, 而每个Client都具有一个不同的Session Key。那么Server就会为所有的Client维护这样一个Session Key的列表,这样做对于Server来说是比较麻烦而低效的
 
  由于网络传输的不确定性,可能出现这样一种情况:Client很快获得Session Key,并将这个Session Key作为Credential随同访问请求发送到Server,但是用于ServerSession Key确还没有收到,并且很有可能承载这个Session Key的永远也到不了Server端,Client将永远得不到认证。
 
为了解决这个问题,Kerberos的做法很简单,将这两个被加密的Copy一并发送给Client,属于Server的那份由Client转发送给Server,就相当于java中的一次会话同一个进程。

可能有人会问,KDC并没有真正去认证这个发送请求的Client是否真的就是那个他所声称的那个人,就把Session Key发送给他,会不会有什么问题?如果另一个人(比如Client B)声称自己是Client A,他同样会得到Client AServerSession Key,这会不会有什么问题?实际上不存在问题,因为Client B声称自己是Client AKDC就会使用Client APassword派生的Master KeySession Key进行加密,所以真正知道Client A Password的一方才会通过解密获得Session Key。如果你假装一个人去获取了他的密码,但是你是解不开的还是没用的
 
三、引入Authenticator - 为有效的证明自己提供证据
通过上面的过程,Client实际上获得了两组信息:一个通过自己Master Key加密的Session Key,另一个被SeverMaster Key加密的数据包,包含Session Key和关于自己的一些确认信息。通过第一节,我们说只要通过一个双方知晓的Key就可以对对方进行有效的认证,但是在一个网络的环境中,这种简单的做法是具有安全漏洞,为此,Client需要提供更多的证明信息,我们把这种证明信息称为Authenticator,在KerberosAuthenticator实际上就是关于Client的一些额外信息当前时间的一个Timestamp
 
在这个基础上,我们再来看看Server如何对Client进行认证:Client通过自己的Master KeyKDC加密的Session Key进行解密从而获得Session Key,随后创建AuthenticatorClient Info + Timestamp并用Session Key对其加密。最后连同从KDC获得的、被ServerMaster Key加密过的数据包Client Info + Session Key一并发送到Server端。我们把通过ServerMaster Key加密过的数据包称为Session Ticket
 
 
Server接收到这两组数据后,先使用他自己的Master KeySession Ticket进行解密,从而获得Session Key。随后使用该Session Key解密Authenticator,通过比较Authenticator中的Client InfoSession Ticket中的Client Info从而实现对Client的认证。
 
 
为什么要使用Timestamp
到这里,很多人可能认为这样的认证过程天衣无缝:只有当Client提供正确的Session Key方能得到Server的认证。但是在现实环境中,这存在很大的安全漏洞。
 
我们试想这样的现象:ClientServer发送的数据包被某个恶意网络监听者截获,该监听者随后将数据包座位自己的Credential冒充该ClientServer进行访问,在这种情况下,依然可以很顺利地获得Server的成功认证。为了解决这个问题,ClientAuthenticator中会加入一个当前时间的Timestamp
 
ServerAuthenticator中的Client InfoSession Ticket中的Client Info进行比较之前,会先提取Authenticator中的Timestamp,并同当前的时间进行比较,如果他们之间的偏差超出一个可以接受的时间范围(一般是5mins),Server会直接拒绝该Client的请求。在这里需要知道的是,Server维护着一个列表,这个列表记录着在这个可接受的时间范围内所有进行认证的Client和认证的时间。对于时间偏差在这个可接受的范围中的ClientServer会从这个这个列表中获得最近一个该Client的认证时间,只有Authenticator中的Timestamp晚于通过一个Client的最近的认证时间的情况下Server采用进行后续的认证流程。
 
Time Synchronization的重要性
 
上述 基于Timestamp的认证机制只有在ClientServer端的时间保持同步的情况才有意义。所以保持Time Synchronization在整个认证过程中显得尤为重要。在一个Domain中,一般通过访问同一个Time Service获得当前时间的方式来实现时间的同步。
 
双向认证(Mutual Authentication
 
Kerberos一个重要的优势在于它能够提供双向认证:不但Server可以对Client 进行认证,Client也能对Server进行认证
 
具体过程是这样的,如果Client需要对他访问的Server进行认证,会在它向Server发送的Credential中设置一个是否需要认证的FlagServer在对Client认证成功之后,会把Authenticator中的Timestamp提出出来,通过Session Key进行加密,当Client接收到并使用Session Key进行解密之后,如果确认Timestamp和原来的完全一致,那么他可以认定Server正式他试图访问的Server
那么为什么Server不直接把通过Session Key进行加密的Authenticator原样发送给Client,而要把Timestamp提取出来加密发送给Client呢?原因在于防止恶意的监听者通过获取的Client发送的Authenticator冒充Server获得Client的认证。
 
四、引入Ticket Granting  Service
通过上面的介绍,我们发现Kerberos实际上一个基于Ticket的认证方式。Client想要获取Server端的资源,先得通过Server的认证;而认证的先决条件是ClientServer提供从KDC获得的一个有ServerMaster Key进行加密的Session TicketSession Key + Client Info。可以这么说,Session TicketClient进入Server领域的一张门票。而这张门票必须从一个合法的Ticket颁发机构获得,这个颁发机构就是ClientServer双方信任的KDC 同时这张Ticket具有超强的防伪标识:它是被ServerMaster Key加密的。对Client来说, 获得Session Ticket是整个认证过程中最为关键的部分。
 
如果我们把Client提供给Server进行认证的Ticket比作股票的话,那么Client在从KDC那边获得Ticket之前,需要先获得这个Ticket的认购权证,这个认购权证在Kerberos中被称为TGTTicket Granting TicketTGT的分发方仍然是KDC
ClientKDC获取TGT
我们现在来看看Client是如何从KDC处获得TGT的:首先ClientKDC发起对TGT的申请,申请的内容大致可以这样表示:需要一张TGT用以申请获取用以访问所有ServerTicketKDC在收到该申请请求后,生成一个用于该ClientKDC进行安全通信的Session KeySKDC-Client。为了保证该Session Key仅供该Client和自己使用,KDC使用ClientMaster Key和自己的Master Key对生成的Session Key进行加密,从而获得两个加密的SKDC-ClientCopy。对于后者,随SKDC-Client一起被加密的还包含以后用于鉴定Client身份的关于Client的一些信息。最后KDC将这两份Copy一并发送给Client。这里有一点需要注意的是:为了免去KDC对于基于不同ClientSession Key进行维护的麻烦,就像Server不会保存Session KeySServer-Client一样,KDC也不会去保存这个Session KeySKDC-Client),而选择完全靠Client自己提供的方式。

 
Client获取SKDC-Client之后处理
Client收到KDC的两个加密数据包之后,先使用自己的Master Key对第一个Copy进行解密,从而获得KDCClientSession KeySKDC-Client,并把该Session TGT进行缓存。有了Session KeyTGTClient自己的Master Key将不再需要,因为此后Client可以使用SKDC-ClientKDC申请用以访问每个ServerTicket,相对于ClientMaster Key这个Long-term KeySKDC-Client是一个Short-term Key,安全保证得到更好的保障,这也是Kerberos多了这一步的关键所在。同时需要注意的是SKDC-Client是一个Session Key,他具有自己的生命周期,同时TGTSession相互关联,当Session Key过期,TGT也就宣告失效,此后Client不得不重新向KDC申请新的TGTKDC将会生成一个不同Session Key和与之关联的TGT。同时,由于Client Log off也导致SKDC-Client的失效,所以SKDC-Client又被称为Logon Session Key
 
 
Client使用TGTKDC获取ServerTicket
接下来,我们看看Client如何使用TGT来从KDC获得基于某个ServerTicket。在这里我要强调一下,Ticket是基于某个具体的Server的,而TGT则是和具体的Server无关的,Client可以使用一个TGTKDC获得基于不同ServerTicket。我们言归正传,Client在获得自己和KDCSession KeySKDC-Client之后,生成自己的Authenticator以及所要访问的Server名称的并使用SKDC-Client进行加密。随后连同TGT一并发送给KDCKDC使用自己的Master KeyTGT进行解密,提取Client InfoSession KeySKDC-Client,然后使用这个SKDC-Client解密Authenticator获得Client Info,对两个Client Info进行比较进而验证对方的真实身份。验证成功,生成一份基于Client所要访问的ServerTicketClient,这个过程就是我们第二节中介绍的一样了。
 
 
五、Kerberos3Sub-protocol:整个Authentication
通过以上的介绍,我们基本上了解了整个Kerberos Authentication的整个流程:整个流程大体上包含以下3个子过程:
  ClientKDC申请TGTTicket Granting Ticket
  Client通过获取TGTKDC申请获取访问ServerTicket
  Client最终向对自己认证的Server提交Ticket
 
上面的只是简单的原理,并不是真正的Kerberos AuthenticationKerberos的认证过程通过3sub-protocal。这3sub-protocal分别完成上面的3个子过程。这3sub-protocal分别是:
1、Authentication Service Exchange
2、Ticket Granting Service Exchange
3、Client/Server Exchange
 
下图简单展示了完成这个3Sub-protocol所进行Message Exchange
 
 
 
1、Authentication Service Exchange
通过这个Sub-ProtocalKDCKDC中的Authentication Service)实现对Client的身份进行认证,并且颁发给Client一个TGT,步奏如下:
ClientKDCAuthentication Service发送Authentication Service RequestKRB_AS_REQ),为了确保KRB_AS_REQ仅限与自己和KDC知道,Client使用自己的Master Key进行对KRB_AS_REQ的主体部分进行加密(KDC可以通过Domain Account Database获得该ClientMaster Key),KRB_AS_REQ的大体包含以下的内容
 
  Pre-authentication data:包含用以证明自己身份的信息。说白了,就是证明自己知道自己声称的那个accountPassword。一般地,它的内容是一个被ClientMaster key加密过的Timestamp
 
  Client name & realm:简单地说就是Domain name\Client
 
  Server Name:注意这里的Server Name并不是Client真正要访问的Server的名称,而我们也说了TGT是和Server无关的。(Client只能使用Ticket,而不是TGT去访问Server),这里的Server Name实际上是KDCTicket Granting Server name
 
ASAuthentication Service)通过接收KRB_AS_REQ验证发送方是否是Client name & realm中声明的那个Client其实就是要验证发送方是否知道ClientPassword,所以AS只需从Account Database中提取Client对应的Master KeyPre-authentication data进行解密,如果是一个合法的Timestamp,则可以证明发送方提供的是正确无误的密码。验证通过之后,AS将一份Authentication Service ResponseKRB_AS_REP)发送给ClientKRB_AS_REQ主要包含两个部分:本ClientMaster Key加密过的Session KeySKDC-ClientLogon Session Key)和被自己(KDC)加密的TGT。而TGT大体又包含以下的内容:
 
  Session Key/SKDC-Client/Logon Session Key
 
  Client name & realm: 简单地说就是Domain name\Client
 
  End time: TGT到期的时间。
 
Client通过自己的Master Key对第一部分解密获得Session KeySKDC-ClientLogon Session Key)之后,携带着TGT便可以进入下一步:TGSTicket Granting ServiceExchange
 
2、TGSTicket Granting ServiceExchange
TGSTicket Granting ServiceExchange通过ClientKDC中的TGS发送Ticket Granting Service RequestKRB_TGS_REQ)开始,KRB_TGS_REQ大体包含以下内容:
 
  TGTClient通过AS Exchange获得的Ticket Granting TicketTGTKDCMaster Key进行加密。(也就是上一个sub-protocal
 
  Authenticator:用以证明当初TGT的拥有者是否就是自己,所以它必须以TGT的提供方(也就是KDC)和自己的Session KeySKDC-ClientLogon Session Key)来进行加密。
 
  Client name & realm:简单地说就是Domain name\Client
 
  Server Name & realm:简单地说就是Domain name\Server,这回是Client试图访问的那个Server(例如hadoophdfsyarn等等)。
 
TGS收到KRB_TGS_REQ之后在发给Client真正的Ticket之前,先对整个Client提供的那个判断TGT是否是AS颁发给它的。于是它不得不通过Client提供的Authenticator来证明。但是Authentication是通过Logon Session KeySKDC-Client)进行加密的,而自己并没有保存这个Session Key。所以TGS先得通过自己的Master KeyClient提供的TGT进行解密,从而获得这个Logon Session KeySKDC-Client),再通过这个Logon Session KeySKDC-Client)解密Authenticator进行验证。验证通过向对方发送Ticket Granting Service ResponseKRB_TGS_REP)。这个KRB_TGS_REP有两部分组成:使用Logon Session KeySKDC-Client)加密过用于ClientServerSession KeySServer-Client和使用ServerMaster Key进行加密的Ticket。该Ticket大体包含以下一些内容:
 
Session KeySServer-ClientServerClientkey
 
Client name & realm:简单地说就是Domain name\Client
 
End TimeTicket的到期时间。
 
Client收到KRB_TGS_REP,使用Logon Session KeySKDC-Client解密第一部分后获得Session KeySServer-Client。有了Session KeyTicketClient就可以之间和Server进行交互,而无须再通过KDC作中间人了。所以我们说Kerberos是一种高效的认证方式,它可以直接通过ClientServer双方来完成。
 
最后,Client如果使用TicketServer怎样进行交互的,这个阶段通过我们的第3Sub-protocol来完成:CSClient/Server Exchange
 
3、CSClient/ServerExchange
这个已经第二节中已经介绍过,对于重复发内容就不再累赘了。Client通过TGS Exchange获得ClientServerSession KeySServer-Client),随后创建用于证明自己就是Ticket的真正所有者的Authenticator,并使用Session KeySServer-Client)进行加密。最后将这个被加密过的AuthenticatorTicket作为Application Service RequestKRB_AP_REQ)发送给Server。除了上述两项内容之外,KRB_AP_REQ还包含一个Flag用于表示Client是否需要进行双向验证(Mutual Authentication)。
Server接收到KRB_AP_REQ之后,通过自己的Master Key解密Ticket,从而获得Session KeySServer-Client)。通过Session KeySServer-Client)解密Authenticator,进而验证对方的身份。验证成功,让Client访问需要访问的资源,否则直接拒绝对方的请求。
对于需要进行双向验证,ServerAuthenticator提取Timestamp,使用Session KeySServer-Client)进行加密,并将其发送给Client用于Client验证Server的身份。
 
六、User2User Sub-Protocal:有效保障Server的安全
通过3Sub-protocol的介绍,我们可以全面地掌握整个Kerberos的认证过程。实际上,在Windows 2000时代,基于KerberosWindows Authentication就是按照这样的工作流程来进行的。但是,基于3Sub-protocolKerberos作为一种Network Authentication是具有它自己的局限和安全隐患的。必须注意一个原则:以某个EntityLong-term Key加密的数据不应该在网络中传递。原因很简单,所有的加密算法都不能保证100%的安全,对加密的数据进行解密只是一个时间的过程,最大限度地提供安全保障的做法就是:使用一个Short-term keySession Key)代替Long-term Key对数据进行加密,使得恶意用户对其解密获得加密的Key时,该Key早已失效。但是对于3Sub-ProtocolC/S ExchangeClient携带的Ticket却是被Server Master Key进行加密的,这显现不符合我们提出的原则,降低Server的安全系数。
 
所以我们必须寻求一种解决方案来解决上面的问题。这个解决方案很明显:就是采用一个Short-termSession Key,而不是Server Master KeyTicket进行加密。这就是Kerberos的第4Sub-protocolUser2User Protocol我们知道,既然是Session Key,仅必然涉及到两方,而在Kerberos整个认证过程涉及到3方:ClientServerKDC,所以用于加密Ticket的只可能是ServerKDC之间的Session KeySKDC-Server)。
 
我们知道Client通过在AS Exchange阶段获得的TGTKDC那里获得访问ServerTicket。原来的Ticket是通过ServerMaster Key进行加密的,而这个Master Key可以通过Account Database获得。但是现在KDC需要使用ServerKDC之间的SKDC-Server进行加密,而KDC是不会维护这个Session Key,所以这个Session Key只能靠申请TicketClient提供所以在AS ExchangeTGS Exchange之间,Client还得对Server进行请求以便获得ServerKDC之间的Session KeySKDC-Server。而对于Server来说,它可以像Client一样通过AS Exchange获得他和KDC之间的Session KeySKDC-Server和一个封装了这个Session Key并被KDCMaster Key进行加密的TGT,一旦获得这个TGTServer会缓存它,以待Client对它的请求。我们现在来详细地讨论这一过程。
 
 
上图基本上翻译了基于User2User的认证过程,这个过程由4个步骤组成。从头到尾简单地过一遍:
 
1、AS ExchangeClient通过此过程获得了属于自己的TGT,有了此TGTClient可凭此向KDC申请用于访问某个ServerTicket
 
2、这一步的主要任务是获得封装了ServerKDCSession KeySKDC-Server)的属于ServerTGT。如果该TGT存在于Server的缓存中,则Server会直接将其返回给Client。否则通过AS ExchangeKDC获取。
 
3、TGS ExchangeClient通过向KDC提供自己的TGTServerTGT以及AuthenticatorKDC申请用于访问ServerTicketKDC用自己的Master Key解密ClientTGT获得SKDC-Client,通过SKDC-Client解密Authenticator验证发送者是否是TGT的真正拥有者,验证通过再用自己的Master Key解密ServerTGT获得KDCServer Session KeySKDC-Server),并用该Session Key加密Ticket返回给Client
 
4C/S ExchangeClient携带者通过KDCServer Session KeySKDC-Server)进行加密的Ticket和通过ClientServerSession KeySServer-Client)的Authenticator访问ServerServer通过SKDC-Server解密Ticket获得SServer-Client,通过SServer-Client解密Authenticator实现对Client的验证。
 
 
 
展开阅读全文

没有更多推荐了,返回首页