什么是 Kerberos?
Kerberos 是一种网络身份验证协议,负责联网的系统安全身份验证。由麻省理工学院开发,取名自希腊神话中的守护地狱之门的——地狱三头犬(Cerberus)。它够识别所有经此路过的亡灵,防止活着的入侵者闯入地狱。
而真正的kerberos协议中也存在三个角色:
客户端(client):发送请求的一方
服务端(Server):接收请求的一方
密钥分发中心(Key Distribution Center,KDC),而密钥分发中心一般又分为两部分,分别是:
- AS(Authentication Server):认证服务器,专门用来认证客户端的身份并发放客户用于访问TGS的TGT
- TGS(Ticket Granting Ticket):票据授予服务器,用来发放整个认证过程以及客户端访问服务端时所需的服务授予票据(Ticket)
目前的主流版本是V5,RHEL7的版本中包含了 Kerberos 的客户端和软件包。
须注意的是,Kerberos 提供身份验证服务,但并不负责存储身份验证信息(目录存储)。这一部分的工作将由其他的服务或资源完成,如 LDAP、NIS (Network Information Service,网络信息服务)或本地的 /etc/passwd 文件。
值得一提的,微软的 Active Directory (活动目录服务),被视作是 Kerberos + 目录服务 + NTP 的整合(甚至还集成了DNS服务)。因为其安全性和Windows系统的广泛使用而得到普及,安全性较弱的 NIS 则很少使用。
Kerberos 解决什么问题?
一句话:Kerberos认证解决了“如何证明我就是我的问题”。
详细解释就是:网络中,客户端访问服务端,双方并不信任对方。对安全有要求的访问,双方都必须向对方证明自己的合法身份。
如何才能证明呢?
一般来说即使客户端的请求中携带自己的身份信息,直接发给服务端,服务端是没有理由信任这段信息就是真实的。同理,服务端返回自己的身份信息给客户端,客户端也是无法辨别该服务器是否是自己想要访问的服务器。这样就需要一个双方都信任的权威角色来介入证明,也就是KDC这个角色。
整个kerberos认证流程可以简述如下。客户端想要访问网络服务,需要完成下面三步:
- 客户端向KDC请求获取想要访问目标服务的票据(Ticket)
- KDC认出客户端身份后给予出票(而且是用服务端密钥加密的Ticket)
- 客户端拿票到服务端访问,服务端能解密Ticket,既能说明客户端受到KDC的认证,也能证明自己的身份。
不过这里面还存在一些细节问题:
- KDC是如何知道客户端的真实身份?凭什么给予发放票据?
-
基本概念
Client 客户端
Service 服务端
Realm,命名空间,领域,类似于Windows域的概念
Principal,主体,用来标识一个用户、主机或者服务,由 primary,instance(可选)和 realm三部分构成。
例如:
service/hostname@realm
ftp/server1.example.com@example.com
Keytab,“密码本”
Ticket Cache:客户端与 KDC 交互完成后,包含身份认证信息的文件,短期有效,需要不断renew。
Key Distribution Center (KDC), 密钥分发中心,是 Kerberos 的核心组件,主要由三个部分组成: Kerberos Database: 包含了一个 Realm 中所有的 principal、密码与其他信息。(默认:Berkeley DB)
- Authentication Service(AS): 进行用户信息认证,为客户端提供 Ticket Granting Tickets(TGT)。
- Ticket Granting Service(TGS): 验证 TGT 与 Authenticator,为客户端提供 Service Tickets。
工作原理
客户端在访问服务之前需要依次与 Authentication Service, Ticket Granting Service 以及目标Service进行交互,共三次交互,以完成验证身份的过程。(双向验证)
第一次交互
为了获得能够用来访问服务端服务的票据,客户端首先需要来到KDC获得服务授予票据(Ticket)。由于客户端是第一次访问KDC,此时KDC也不确定该客户端的身份,所以第一次通信的目的为KDC认证客户端身份,确认客户端是一个可靠且拥有访问KDC权限的客户端。
过程如下:
- 客户端明文发送【客户端ID】、【网络地址】、【时间戳】信息给像DC的AS
- AS通过 Kerberos用户目录数据库验证【客户端ID】,如果没有则认证失败,服务结束。如果通过了,则返回给客户端两块信息
- 生成 【TGS Session Key】,并和即将要访问的TGS名称,时间戳一起用客户端的密钥加密,客户端可以解密,这个key之后用于客户端与TGS通信。如果客户端是冒充的,那么它没有客户端密钥用于解密,也就无法使用【TGS Session Key】完成后续通信。
- 还生成一个【TGT】,用【TGS Secret Key】(TGS自己的key)加密,客户端无法解密。TGT中包含的内容有kerberos数据库中存在的该客户端的Name,IP,当前时间戳,客户端即将访问的TGS的Name。
第二次交互
客户端收到AS发过来两部分内容,将上述a部分解密。获得时间戳,自己将要访问的TGS的信息,和用于与TGS通信时的【TGS Session Key】。其中须判断时间戳和请求的时间之差是否大于5分钟,大于5分钟则认为AS是不合法的,认证也失败。如果时间戳合理,客户端会继续向TGS发起请求,来获取能够访问目标网络访问的票据【TGT】。
过程如下:
- 客户端使用【TGS Session Key】加密自己的信息(包括客户端名称,IP,时间戳)发送给TGS。同时携带自己想要访问的网络服务,以明文的方式发送,在第一次交互中收到的无法解密的【TGT】也直接携带给TGS。
- TGS收到信息后,首先验证网络服务的IP是否在Keberos系统中存在。如存在则用自己的【TGS Secret Key】解密【TGT】,得到时间戳和另一个【TGS Session Key】,并对客户端请求进行响应;响应的内容包括:
- 用于客户端访问网络服务使用的正式票据——Service Ticket,其中包括客户端的名称、IP,需要访问的网络服务的地址,ST的有效时间,时间戳,以及客户端和服务端直接通信用的【Session Key】,这些内容以服务端的密钥加密,客户端无法解密。
- 使用【TGS Session Key】加密的内容,包括时间戳,ST的有效时间。客户端之前已缓存这个Session Key,所以是可以解密的。
第三次交互
此时的客户端收到了来自KDC(TGS)的响应,并使用缓存在本地的CT_SK解密了 b 部分内容(a部分内容中的ST是由Server密码加密的,客户端无法解密),检查时间戳无误后取出其中的CS_SK准备向服务端发起最后的请求。
过程如下:
- 客户端使用CK_SK将自己的主机信息和时间戳进行加密作为第一部分内容,然后将ST作为第二部分内容发送给服务端。
- 服务器收到客户端的请求,使用自己的密钥将ST解密,核对时间戳后将【TGS Session Key】取出来并对第一部分内容进行解密,获得经过TGS认证后的客户端信息,并以此确认客户端的合法性。确认后服务端会响应客户端请求,并使用【TGS Session Key】加密,客户端收到响应后,使用本地缓存的【TGS Session Key】解密,同时也能确认服务端的合法身份。
至此,三次交互完成,也代表Kerberos的认证过程完成,客户端和服务端都确认了对方的身份,后续可以正常进行服务请求和响应了。
参考:https://blog.csdn.net/weixin_38233104/article/details/122963237