首页 > 代码库 > kerberos工作原理
kerberos工作原理
最近调研了kerberos。看了网上学多关于kerberos的文章,我认为这篇文章比较好。
http://blog.csdn.net/gracexu/article/details/1707032 这篇文章对麻省理工的论文进行翻译。该论文以四幕话剧的形式缓缓道来,有点像《研究之美》,通过两个人的头脑风暴讲解kerberos的原理。
一、使用kerberos进行验证的原因
1. 可靠 Hadoop 本身并没有认证功能和创建用户组功能,使用依靠外围的认证系统 高效
2. Kerberos使用对称钥匙操作,比SSL的公共密钥快 操作简单
3. 用户可以方便进行操作,不需要很复杂的指令。比如废除一个用户只需要从Kerbores的KDC数据库中删除即可。
二、kerberos能解决的hadoop安全认证的问题
2.1服务器到服务器的认证
1.没有DataNode,TaskTracker的认证:
用户可以伪装成DataNode,TaskTracker,去接受JobTracker,NameNode指派的任务
2.2 客户端到服务器的认证
1.NameNode,JobTracker上没有用户认证:
用户可以伪装成其他用户入侵到一个HDFS 或者MapReduce集群上。
2.DataNode上没有认证:
Datanode对读入输出并没有认证。导致如果一些客户端如果知道block的ID,就可以任意的访问DataNode上block的数据
3.JobTracker上没有认证:
可以任意的杀死或更改用户的jobs,可以更改JobTracker的工作状态
三、kerberos工作原理
3.1麻省理工kerberos论文
这里对论文中的对话进行简要概括。
A:我有个主意,我们设计一个工作站系统,把系统软件发在不同服务器上,工作站通过网络练到服务器,访问上面的系统软件。
B:我有个问题,比如我找出你的用户名,在你的文件服务器删除你的文件搞破坏怎么办?
A:提供服务的机器必须能够确认请求服务的人的身份。我必须让服务器知道我就是我声称的那个人。我可以通过输入口令的办法证明我自己。
B:这个办法有点笨。如果有一千个用户,那么每台服务器就要知道一千个口令,如果用户想改口令,也要通知每一个服务器。
A:可以这么做。每个用户有自己的口令,每个服务也有自己的口令。有一个认证服务拥有所有用户和服务的口令,将它们保存在一个中央数据库中。
比如说用户想访问邮件服务,用户给认证服务自己的密码,认证服务就把邮件服务的密码给用户,用户就可以访问邮件服务了。但这里有一个问题,认证服务不能把邮件服务的密码直接给用户,那么用户下次就可以直接用密码访问了,绕过了认证服务,我就可以冒充别人用密码访问服务。认证服务给用户一张”票“,票里包含着用户名,用户名是用邮件服务的密码加密的。邮件服务拿自己的密码解密,用得到的用户名对比提供的用户名。如果相符则通过认证。
B:有个问题,服务如何知道正确解密了“票”。也许应该把服务的名字也加入票里。
A:就像这样?
? 票 —{用户名:服务名}
B:我感觉还是不安全,如果在传输的过程中,我在网络上拷贝了一份,服务也可以把我拷的“票”解密,我也可以通过验证。我想了一个办法,我们可以加入请求票用户的网络地址。
A:像这样?
? 票 — {用户名:地址:服务名}
B:听起来我每次访问邮件服务都要请求一次邮件的“票”吗?
A:我认为你只需要得到一次邮件服务的“票”就可以,再此使用传一份拷贝的票就可以了。
B:我仍有问题,我在每次使用没有“票”的服务时,是不是都要传一次我的密码。这就是说你在网络上明文使用你的密码,如果我抓包抓到了你的密码,我就可以使用你的名字来使用任何服务。
A:好吧,我们先明确一下需求:一、用户只需要输入一次口令;二、口令不能以明文形式传输。对于要求一,创造一个“票据授予”服务,用户向认证服务认明身份后,“票据授予”把认证服务的票给用户,通过票而不是口令进行认证服务。我只需获得票据授予票一次就可以。
B:如何在获取票据授予票时不用明文传输口令?
A:用户通过一个kinit程序进行票据授予服务,进行票据授予时,kinit不是将用户口令传给认证服务器,而是将用户名传给认证服务器。认证服务器通过用户名对应的口令对“票据授予”票进行加密传给用户,用户在用自己的口令进行解密。
B:我感觉服务票是可重用的这一点很危险。比如我使用了一个不安全的工作站获取服务,当我离开时,无意中留下了一些票。别人登陆这个工作站发现我留下来的这些票后,就可以对我的文件进行破坏,还可以把票拷走,永远使用。
A:可以设计一些程序在用户离开时销毁这些票
B:我可以监控网络拷贝你的票据。等你会话结束。修改我的工作站地址,用你的用户名访问你的服务。你销毁你的票已经没意义,因为我己经拷贝下来,可以永远使用。
A:我们可以给每张票一个有效期。
B:像这样?
? 票{用户名:地址:服务名:有效期:时间戳}
A:那票的有效期就定为8小时吧。但有一个问题如果我只用了2小时就离开,那么其他人可以用拷贝来的票使用6小时,这段时间足够做很多事了。
B:这确实是个问题。
A:如果我们可以设计一种无法重用的票就好了。
但这是一个笨办法。重述一遍我们探讨的问题。我们希望网络服务必须能够证明使用票的人就是票上所记的人。我们先重新整理下思路。
现在客户端发给服务器三样东西:
? 用户名
? 网络地址
? 适当的服务票据。
现在有三个认证过程:
? 服务能否解密票据
? 票过期了吗
? 票中的名字和工作站地址与用户提供的匹配吗
第三点有点问题,坏人可以串改他的用户名和密码。而服务无法判断。而服务之所以无法判断是因为没有和用户共享一个秘密。为什么不让认证服务为合法用户和服务之间设一个口令呢?比如发一份会话密钥。服务可以用密钥验证用户身份。
B:认证服务如何给双方发密钥呢?
A:用户从认证服务获得会话密码。
? 认证服务的回应-[会话密码|票]
服务从票里获得会话密码,就像这样:
? 票-{会话密码:用户名:地址:服务名:有效期:时间戳}
当用户请求服务时,客户端生成一个“验证器”,“验证器”。用用户名和地址用会话密钥加密。
? 验证器-{用户名:地址} 会话密钥加密
服务器解开票后获得会话密钥,再用会话密钥解密验证器获得用户名和地址。
B:如果我把验证器和票一起偷走,不也是还可以做坏事吗?等等,我们可以把验证器设计成只可以使用一次。把有效期和时间戳放在上面。假设每个验证有两分钟的有效期。但有一个潜在的问题,我拷贝了一份认证服务对你请求票据时的回应。那里面有会话密钥和票,我也可以根据会话密钥生成验证器。
A:我也想到了这点,但我认为这是不可能的。我们可以这么做。在票据授予服务时,返回的会话密钥和票据授予票用用户密码加密,普通服务返回的票用票据授予会话密钥加密。
B:我又想到了一个严重的问题。上面的认证方式只能防止错误的用户使用服务器,不能防止错误的服务器被发送服务请求,也就是说如果我伪造了一个服务器我就可以得到你的请求。这显然是不安全的。我们还需要为客户端提供一种验证服务器的方法。服务端可以向客户端发回应答,应答用会话密钥加密,服务端需要用自己的口令去解密票据才可以得到会话密钥。这样系统就坚实了。
A:我们把这个认证服务叫做kerberos吧。
上述对话是对kerberos V4的运行方式介绍,kerberos V5对其有了一些改进。
第一处改变是因为意识到验证器用少于五分钟的有效期不足以防止攻击者进行重演,如果攻击者是用一个程序自动的截取票和验证器并进行重演的话。在Kerberos V5中,验证器真正的只能用一次因为服务器用‘重演缓冲区’保存了最近一次提交的验证器的信息。如果攻击者试图截取验证器并重用它,‘重演缓冲区’会发现验证器已经被提交了。
第二个主要改变是Kerberos送给kinit服务票的时候,票不再是用用户的口令加密。它已经用票据授予服务的口令加过密了。票据授予服务的票被用来获取其它票的时候,它直接就被传输了。因此票不需要再用用户的口令加密一次。一个类似的改变也应用到票据授权服务协议;从票据授权服务返回的票也不再用票据授权服务的口令来加密了,因为它所包含的票已经被对应的服务的口令加过密了。
3.2 基本概念
从上文四幕话剧的介绍我们可以引申出几个基本概念
- Princal(安全个体):被认证的个体,有一个名字和口令
- KDC(key distribution center ) :是一个网络服务,提供ticket 和临时会话密钥
- Ticket:一个记录,客户用它来向服务器证明自己的身份,包括客户标识、会话密钥、时间戳。
- AS (AuthenticationServer): 认证服务器
- TGS(Ticket Granting Server): 许可证服务器
3.3工作流程
我们来先整理一下kerberos的工作流程
1.客户端许可证服务
1)首先Princal发送自己的用户名等信息给KDC请求许可证服务
2)KDC调用TGS,得到一个TGT(许可票据票)里面包含用户名,地址,session 密码 ,有效期,时间戳等,TGT用许可证服务密码加密和一个session 密码用用户密码加密。发送给Princal
3) Princal用自己的密码解谜获得session 密码 和加密后的TGT
2.客户端获取服务的认证票
1)Princal将自己的用户名,地址,请求的服务,时间戳等用TGS的session 密码 加密得到一个验证器,和TGT一起发送给KDC
2)KDC判断验证器是否过期(只能被使用一次),再用自己的密码解密TGT获得用户的信息和session密码,再用session密码解密验证器,比对用户信息。生成一个目标server的session密码,用这个session密码和用户信息组成一个server票,再用KDC存储的这个 server的密码对票进行加密。用用户密码对server的session密码进行加密。一并返回给Princal。
3.客户端与目标server的相互认证
1)Princal收到KDC的返回包后,用自己的密码解密session 密码加密文件得到session 密码。将自己的用户名,地址,请求的服务,时间戳等用session 密码加密得到一个验证器。将验证器和票一起发给目标服务的服务器
2)目标服务器判断验证器是否过期(只能被使用一次),再用自己的密码解密票据获得用户的信息和session 密码,再用session密码解密验证器,比对用户信息。创造一个应答,用解密出来的session密码加密,回答给Princal
3)Princal接到回答后用session密码解密,如果解密成功,就开始与服务传送命令。
kerberos工作原理