Kerberos认证
Kerberos是诞生于上个世纪90年代的计算机认证协议,被广泛应用于各大操作系统和Hadoop生态系统中。了解Kerberos认证的流程将有助于结局Hadoop集群中的安全配置过程中的问题。
Kerberos解决什么问题?
简单的说,Kerberos提供了一种单点登录(SSO)的方法。考虑这样一个场景,在一个网络中有不同的服务器,比如,打印服务器、邮件服务器和文件服务器。这些服务器都有认证的需求。很自然的,不可能让每个服务器自己实现一套认证系统,而是提供了一个中心认证服务器(AS-Authentication Server)供这些服务器使用。这样任何客户端就只需维护一个密码就能登录所有服务器。
因此,在Kerberos系统中至少有三个角色:认证服务器(AS),客户端(Client)和普通服务器(Server)。客户端和服务器将在AS的帮助下完成相互认证。
在Kerberos系统中,客户端和服务器都有一个唯一的名字,叫做Principal。同时,客户端和服务器都有自己的密码,并且它们的密码只有自己和认证服务器AS知道。
Kerberos认证流程
client_principal, server_principal: 分别表示客户端和服务器的名字。
Tc,s: 表示AS发给客户端c的票据,该票据包含有⽤于和服务器s通信认证的相关信息。
{Kc,s; server_principal,…}Kc: 表示票据的内容,{}⾥⾯的为具体内容。Kc为客户端的密码,表示该票据由客户端的密码加密。其它的类似。
1.客户端向服务器端发起请求,请求的内容是:我是谁(客户端的principal),我要和谁通信(服务器的principal)
2.AS收到请求以后,随机生成一个密码Kc,s(Session Key),并且生成了以下两个票据(Ticket)返回给客户端:
Tc,s={Kc,s; server_principal,…}Kc:该票据是给客户端的,大括号里面为票据中的内容,后面的Kc为客户端的密码,表示该票据用客户端的密码加倍了。
Ts,c={Kc,s;client_principal,…}KS 大括号里面为票据中的内容,后面的Ks为服务器的密码,表示该票据用服务器的密码加密了。该票据是给服务器的,但是AS并不直接给服务器,而是交给了客户端再由客户端交给服务器。因为该票据由服务器的密码加密了,所以客户端无法伪造和篡改。
3.客户端拿到了第二步中的两个票据后,首先用自己的密码解开票据Tc,s得到Kc,s,然后生成一个认证因子(Authenticator),其内容如下:
1 | Authenticator:{time_stamp,Ts,c_checksum,...}Kc,s |
其中主要包括当前时间和Ts,c的校验码,并且用SessionKey(Kc,s)加密。客户端将Authenticator和Ts,c同时发给服务器。
4.服务器首先用自己的密码解开Ts,c,拿到SessionKey(kc,s),然后用Kc,s解开Authenticator,并做如下检查:检查Authenticator中的时间戳是不是在当前时间上下5分钟以内,并且检查该时间戳是否首次出现。如果该时间戳不是第一次出现,那说明有人截获了之前客户端发送的内容,进行Replay攻击。检查Checksum是否正确。如果都正确,客户端就通过了认证。服务器端可选择性地给客户端回复一条消息来完成双向认证,内容如下:
1 | (time_stamp)Kc,s |
其中包括客户端发送过去的时间戳,并且由SessionKey(Kc,s)加密。
完整认证流程
比较不方便的是每次认证都需要客户端输入自己的密码。如何解决这个问题,我们再来看一个生活中的例子。某些电影院发行联票,客户只需在花一次钱买张联票(在一定期限内可以兑换一定数量的电影票)。在想看电影的时候,只需要出示联票就可以取一张电影票。这样的好处一是方便,二是相对安全,因为用户无需每次买票的时候都出示信用卡,从而减少了暴露密码的机会。
类似的,在Kerberos系统中,引入了一个新的角色叫做:票据授权服务(TGS-Ticket Granting Service),它的地位类似于一个普通的服务器,只是它提供的服务是为客户端发放用于和其他服务器认证的票据。
这样,Kerberos系统中就有四个角色:认证服务器(AS),客户端(Client),普通服务器(Server)和票据授权服务(TGS)。
1.客户端向AS发起请求,请求内容是:我是谁(客户端的principal),我要和票据授权服务通信(TGS的principal)等
2.AS收到请求后,随机生成一个密码SessionKey(Kc,tgs),并生成以下两个Ticket返回给客户端:
Tc,tgs={Kc,tgs; tgs_principal; …} Kc - 该票据是给客户端的,⼤括号⾥⾯为票据中的内容,后⾯的Kc为客户端 的密码,表示该票据⽤客户端的密码加密了。
Ttgs,c={Kc,tgs; client_principal;…} Ktgs - 该票据是给TGS,⼤括号⾥⾯为票据中的内容,后⾯的Ktgs为TGS的密码,表示该票据⽤TGS的密码加密了,只有TGS能解开。
上述两步和上面简化的认证流程的前两步时一致的,唯一的不一样是与客户端通信的另一端是票据授权服务(TGS)。该步骤中得到的Ttgs,c就类似于例子中的联票,后面将会通过它来得到一张和其他服务器通信认证的票据。
3.客户端用自己的密码解开Tc,tgs,得到Kc,tgs,生成一个Authenticator,并给TGS发送请求,请求内容是包括:
Authenticator={time_stamp,Ttgs,c_check_sum,…}Kc,tgs
Ttgs,c:第二步从AS返回的票据
server_principal, …
在这个步骤中,Authenticator和Ttgs,c是⽤于客户端向TGS证明⾃⼰身份的,server_principal是客户端需要 访问的服务器的名字。
4.TGS收到客户端发送的Authenticator和Ttgs,c后,先用自己的密码解开Ttgs,c,得到SessionKey(Kc,tgs),然后解开Authenticator,对客户端进行认证,这与简化的认证流程的第四步是一致的。如果客户端通过了认证,TGS生成一个客户端和服务器的SesssionKey(Kc,s),同时将组装下面两个票据返回给客户端:
Tc,s={Kc,s,sever_principal,…}Kc,tgs:这是给客户端的票据,Kc,s是客户端与服务器之间的SessionKey,用客户端和TGS之间的SessionKey(Kc,Tgs)加密。区别就在这里了,给客户端的票据不再用客户端的密码加密,而是用客户端和Tgs之间的SessionKey加密。
Ts,c={Kc,s,client_principal,…}Ks:这是给服务器的票据,用服务器的密码加密。
5.客户端收到上述两个票据后,用Kc,tgs解开Tc,s得到Kc,s,然后生成一个Authenticator并发送请求给服务器,内容包括:
1 | Authenticator={time_stamp,Ts,c_checksum,...}Kc,S |
6.服务器收到请求后,用自己的密码解开Ts,c得到Kc,s,然后用Kc,s解开Authenticator对客户端进行认证。服务器也可选择性的返回如下信息给客户端来完成双向认证:
1 | {time_stamp}Kc,s |
1.AS-REQ
域内用户访问域中的服务,输入用户名和密码,本机Kerberos服务会向KDC的AS认证服务,发送AS-REQ认证请求。
请求包:用户名、主机名、加密类型和Authenticator以及一些其他信息。
1 | 用户名+主机名+authenticator(用户hash(timestamp)) |
2.AS-REP
KDC接收到请求后,通过AD活动目录查询得到该用户的密码Hash,用该密码HASH对请求包的Authenticator进行解密,如果解密成功,则证明请求者提供的密码正确,而且需要时间戳范围在五分钟内,于是预认证(preauth)成功,校验时间是为了防止重放。
响应包:TGT和用户NTML-Hash加密的Login Session Key以及一些其他信息以及PAC。Login Session Key 用于在下阶段的交互中的数据加密。
1 | TGT:krbtgt hash(Login session key,client info) |
3.TGS-REQ
客户端向KDC申请针对指定服务的ST服务票据请求。
请求包:客户端信息、authenticator、TGT认购凭证和访问的服务名以及一些其他信息。
1 | info+authenticator(login session key(time)stamp)+TGT+service name |
4.TGS-REP
TGS接受到请求之后,检查自身是否存在客户端所请求的服务。如果服务存在,使用krbygt_NTML_Hash解密TGT获取Login Session Key解密 Authenticator, 若解密成功,则验证了客户端身份, 同时还会验证时问戳是否合法,防⽌重放。并且还会检查TGT中的时间戳是否过期,原始地址是否和TGT中保存的 地址相同,这⾥的地址主要指的是主机名。
如果验证通过,KDC会⽣成⼀个⽤Logon Session Key加密后的⽤于确保客户端-服务器之间通信安全的Service Session Key会话秘钥。并且会为该客户端⽣成ST服务票据。
1 | ST:service hash(client info,service session key) |
5.AP-REQ
客户端接收到TGS回复后,通过步骤2中Login Session Key解密得到原始Service Session Key,同时它也拿到了 ST(Service Ticket)服务票据。该Serivce Session Key 和 ST服务票据 会被客户端缓存。
1 | authenticator: 由service session key 加密的用户信息和时间轴 |
1 | 请求包(请求对象为业务服务器):authenticator + ST |
6.AP-REP
服务器在接收到请求之后,先通过该服务的NTLM Hash哈希解密ST服务票据,并从中提取 Service Session Key。 然后通过提取出来的Service Session Key 解密Authenticator,进⽽验证了客户端的真实身份。
验证了客户端的身份后,服务端使⽤PAC发送给KDC验证该⽤户的权限。KDC通过SID判断⽤户的⽤户组信息,⽤户权限,最终将结果返回给服务端。最终客户端根据KDC的验证结果进⾏访问服务。
1 | 双向验证 :访问者和被访问者互相验证对⽅的身份。客户端验证服务器--服务端⽤ Service Session Key加密时问戳 作为Authenticator,发送给客户端。客户端使⽤ Service Session Key解密authenticator,如果解密成功,则可以 验证服务器的合法 性。双向认证过后,开始了服务资源的访问。 |