1.Kerberos相关概念
主要有以下关键词。
1.1.Long-term Key/Master Key
长期内保持不变的Key,使用原则:被Long-term Key加密的数据不应该在网络上传输。
原因在于,一旦这些被Long-term Key加密的数据包被恶意的网络监听者截获,在原则上,只要有充足的时间,他是可以通过计算获得你用于加密的Long-term Key的——任何加密算法都不可能做到绝对保密。
1.2.Short-term Key/Session Key
我们使用另一种Short-term Key来加密需要进行网络传输的数据。由于这种Key只在一段时间内有效,即使被加密的数据包被黑客截获,等他把Key计算出来的时候,这个Key早就已经过期了。
1.3.KServer-Client
Client和Server之间的Key,代表Client自身Identity的信息,以明文传递。将Client的Identity使用KServer-Client作为Public Key,并采用对称加密算法进行加密。
1.4.SServer-Client
通过让被认证的一方提供一个仅限于他和认证方知晓的Key来鉴定对方的真实身份。而被这个Key加密的数据包需要在Client和Server之间传送,所以这个Key不能是一个Long-term Key,而只可能是Short-term Key,这个可以仅仅在Client和Server的一个Session中有效,所以我们称这个Key为Client和Server之间的Session Key(SServer-Client)。
1.5.principal
认证的主体,简单来说就是"用户名"
1.6.realm
realm有点像编程语言中的namespace。在编程语言中,变量名只有在某个"namespace"里才有意义。同样的,一个principal只有在某个realm下才有意义。
所以realm可以看成是principal的一个"容器"或者"空间"。相对应的,principal的命名规则是"what_name_you_like@realm"。
在kerberos, 大家都约定成俗用大写来命名realm, 比如"EXAMPLE.COM"。
1.7.password
某个用户的密码,对应于kerberos中的Master Key。password可以存在一个keytab文件中。所以kerberos中需要使用密码的场景都可以用一个keytab作为输入。
1.8.credential
credential是“证明某个人确定是他自己/某一种行为的确可以发生”的凭据。在不同的使用场景下, credential的具体含义也略有不同:
(1)对于某个principal个体而言,他的credential就是他的password。
(2)在kerberos认证的环节中,credential就意味着各种各样的ticket。
2.KDC
KDC全称是Kerberos Distribution Center。
KDC在整个Kerberos Authentication中作为Client和Server共同信任的第三方起着重要的作用,而Kerberos的认证过程就是通过这3方协作完成。
基本架构如下图所示:
KDC主要由两部分组成:Authentication Server和Ticket Granting Server。
3.认证过程
认证过程如下图所示:
从图中可知,认证过程分为以下6个步骤:
(1)第一步:用户向KDC发送请求验证自己的身份
(2)第二步:KDC确认用户身份,并用协议开始前Client与KDC之间的密钥将TGT加密回复给Client。此时只有真正的Client才能利用它与KDC之间的密钥将加密后的TGT解密,从而获得TGT。
(3)第三步:Client将之前获得TGT和要请求的服务信息(服务名等)发送给KDC,KDC中的Ticket Granting Service将为Client和Service之间生成一个Session Key用于Service对Client的身份鉴别。然后KDC将这个Session Key和用户名,用户地址(IP),服务名,有效期, 时间戳一起包装成一个Ticket(这些信息最终用于Service对Client的身份鉴别)发送给Service, 不过Kerberos协议并没有直接将Ticket发送给Service,而是通过Client转发给Service
(4)第四步:此时KDC将刚才的Ticket转发给Client。由于这个Ticket是要给Service的,不能让Client看到,所以KDC用协议开始前KDC与Service之间的密钥将Ticket加密后再发送给Client。同时为了让Client和Service之间共享那个密钥(KDC在第三步为它们创建的Session Key),KDC用Client与它之间的密钥将Session Key加密随加密的Ticket一起返回给Client。
(5)第五步:为了完成Ticket的传递,Client将刚才收到的Ticket转发到Service. 由于Client不知道KDC与Service之间的密钥,所以它无法篡改Ticket中的信息。同时Client将收到的Session Key解密出来,然后将自己的用户名,用户地址(IP)打包成Authenticator用Session Key加密也发送给Service。
(6)第六步:Service 收到Ticket后利用它与KDC之间的密钥将Ticket中的信息解密出来,从而获得Session Key和用户名,用户地址(IP),服务名,有效期。然后再用Session Key将Authenticator解密从而获得用户名,用户地址(IP)将其与之前Ticket中解密出来的用户名,用户地址(IP)做比较从而验证Client的身份。 如果Service有返回结果,将其返回给Client。
4.配置文件
主要有三个配置文件。
4.1.krb5.conf
krb5.conf是kerberos协议配置文件,配置文件具体内容介绍如下所示。
[logging] // 表示 server 端的日志的打印位置
[libdefaults] //每种连接的默认配置,需要注意以下几个关键的小配置
default_realm = JAVACHEN.COM // 设置 Kerberos 应用程序的默认领域。如果您有多个领域,只需向 [realms] 节添加其他的语句。
udp_preference_limit = 1 // 禁止使用 udp 可以防止一个Hadoop中的错误
clockskew // 时钟偏差是不完全符合主机系统时钟的票据时戳的容差,超过此容差将不接受此票据。通常,将时钟扭斜设置为 300 秒(5 分钟)。这意味着从服务器的角度看,票证的时间戳与它的偏差可以是在前后 5 分钟内。
ticket_lifetime // 表明凭证生效的时限,一般为24小时。
renew_lifetime // 表明凭证最长可以被延期的时限,一般为一个礼拜。当凭证过期之后,对安全认证的服务的后续访问则会失败。
[realms] // 列举使用的 realm。
kdc // 代表要 kdc 的位置。格式是 机器:端口
admin_server // 代表 admin 的位置。格式是 机器:端口
default_domain // 代表默认的域名
[appdefaults] // 可以设定一些针对特定应用的配置,覆盖默认配置。
共有四个主要模块。
4.2.kdc.conf
kdc.conf是KDC Server配置文件,具体说明如下所示。
[realms]
JAVACHEN.COM // 是设定的 realms。名字随意。Kerberos 可以支持多个 realms,会增加复杂度。大小写敏感,一般为了识别使用全部大写。这个 realms 跟机器的 host 没有大关系。
master_key_type // 和 supported_enctypes 默认使用 aes256-cts。由于,JAVA 使用 aes256-cts 验证方式需要安装额外的 jar 包(后面再做说明)。推荐不使用,并且删除 aes256-cts。
acl_file // 标注了 admin 的用户权限,需要用户自己创建。文件格式是:Kerberos_principal permissions [target_principal] [restrictions]
supported_enctypes // 支持的校验方式。
admin_keytab // KDC 进行校验的 keytab。
主要配置realm,定义KDC服务端信息。
4.3.kadm5.acl
kadm5.acl是admin用户权限配置文件
5.Kerberos认证操作案例
关于kerberos的管理,可以使用kadmin.local或kadmin命令,使用哪个则取决于账户和访问权限:
(1)如果有访问 kdc 服务器的 root 权限,但是没有 kerberos admin 账户,使用 kadmin.local
(2)如果没有访问 kdc 服务器的 root 权限,但是有 kerberos admin 账户,使用 kadmin
5.1.创建管理员
假设密码为root,则有以下两种方式:
kadmin.local -q "addprinc root/admin"
echo -e "root\nroot" | kadmin.local -q "addprinc root/admin"
第一种方法需要交互式输入密码
5.2.查询用户
有两种方式:
kadmin -p root/admin -q "list_principals"
kadmin.local -q "list_principals"
第一种需要输入密码,第二种不需要输入密码。
5.3.创建一个测试用户
用户名tbdstest,密码为tbdstest,命令如下。
echo -e "tbdstest\ntbdstest" | kadmin.local -q "addprinc tbdstest"
命令在交互窗口输入。
5.4.创建或更新tbdstest用户的ticket
有以下两种用法:
kinit tbdstest #基于密码进行认证
kinit -kt /tmp/tbds.keytab tbdstest #基于密钥进行认证
基于密码的认证需要在交互窗口输入密码。
5.5.查看tbdstest用户的ticket
直接使用klist命令:
klist tbdstest
5.6.销毁tbdstest用户的ticket
直接使用kdestroy命令:
kdestroy
5.7.密钥操作
抽取密钥并将其储存在本地 keytab 文件 /etc/krb5.keytab 中。这个文件由超级用户拥有,所以您必须是 root 用户才能在 kadmin shell 中执行以下命令:
kadmin.local -q "ktadd kadmin/admin"
klist -k /etc/krb5.keytab
5.8.删除用户tbdstest
有两种方法:
kadmin -p root/admin -q "delprinc user2"
kadmin.local -q "delprinc user2"
只能通过超级用户进行删除
5.9.kadmin.local进入本地管理员模式
kadmin.local #进入本地管理员模式,可执行以下命令:
? #查看支持的命令列表
listprincs #查看所有principal
addprinc -randkey hdfs/node3 ##生成随机key的凭据
addprinc -pw 123456 jack/node4 ###生成指定key的凭据
delprinc jack/node4 #删除凭据
ktadd -norandkey -k /root/tbdstest.keytab tbdstest #导出tbdstest的凭据
xst -norandkey -k /root/node4.keytab jack/node4 #导出jack/node4的凭据
xst -norandkey -k /tmp/test.keytab tbdstest hdfs/node3 jack/node4 #将多个principal生产一个keytab
我们就是通过以上方法来生成新用户的keytab。
5.10.注意事项
上一节生成的jack/node4是指定key,如果通过ktadd -k /root/node4.keytab jack/node4导出密钥后,创建时指定的key失效。
失效的原因是:每次生成秘钥文件时,密码可能会进行随机改变,后续再通过指定key进行认证时会报kinit: Password incorrect while getting initial credentials生成密钥时。
解决方案:命令行中添加"-norandkey"即可解决问题,上一节也有对应的案例介绍。