学习Kerberos
Kerberos的 是一种分布式、基于票证的身份验证服务,因为基于分布式,可能这种类型的协议我们平时接触比较少,Web端一般都是通过Cookie、Token、Oauth、Password等各种协议认证,客户端通过Ssh、Password等认证方式,但其实各种客户端也有使用Kerberos认证,例如你如果在linux服务器下载并配置了kerberos服务器,那么linux服务器就会默认先使用kerberos认证、Microsoft也使用 Kerberos 作为基于 Windows 的网络中的默认身份验证方法。
Kerberos在大数据领域应用的更将广泛,大部分的云计算Hadoop组件基本都使用Kerberos作为安全协议。
Kerberos能在分布式领域中大放光彩是因为它的一些不同于传统认证的优点:
- 强大的安全性: Kerberos 使用强大的加密算法来保护用户凭据以及客户端和服务器之间的通信。 它还支持相互身份验证,确保在建立会话之前客户端和服务器都得到验证。
- 集中认证: Kerberos 通过使用密钥分发中心 (KDC) 提供集中式身份验证,从而简化了用户凭据和访问控制策略的管理。
- 单点登录: 一旦用户通过 Kerberos 身份验证,他们就可以访问多个网络资源,而无需再次输入其凭据。 这减轻了用户的负担,并最大限度地降低了密码重复使用或泄露的风险。
- 可扩展性:Kerberos 旨在扩展以支持具有数千个用户和资源的大型网络。 它使用分层信任模型,允许部署多个 KDC 并将其集成到单个身份验证域中。
- 互操作性: Kerberos 是一种广泛采用的网络身份验证标准,受到许多操作系统和应用程序的支持,包括基于 Unix 的系统、Windows 和 Web 浏览器。
概述
Kerberos 是一种基于加密 Ticket 的身份认证协议,抽象概括如下:
- 用户要去游乐场,首先要在门口检查用户的身份(即 CHECK 用户的 ID 和 PASS), 如果用户通过验证,游乐场的门卫 (AS) 即提供给用户一张门卡 (TGT)。
- 这张卡片的用处就是告诉游乐场的各个场所,用户是通过正门进来,而不是后门偷爬进来的,并且也是获取进入场所一把钥匙。
- 现在用户有张卡,但是这对用户来不重要,因为用户来游乐场不是为了拿这张卡的而是为了游览游乐项目,这时用户摩天楼,并想游玩。
- 这时摩天轮的服务员 (client) 拦下用户,向用户要求摩天轮的 (ST) 票据,用户说用户只有一个门卡 (TGT), 那用户只要把 TGT 放在一旁的票据授权机 (TGS) 上刷一下。
- 票据授权机 (TGS) 就根据用户现在所在的摩天轮,给用户一张摩天轮的票据 (ST), 这样用户有了摩天轮的票据,现在用户可以畅通无阻的进入摩天轮里游玩了。
- 当然如果用户玩完摩天轮后,想去游乐园的咖啡厅休息下,那用户一样只要带着那张门卡 (TGT). 到相应的咖啡厅的票据授权机 (TGS) 刷一下,得到咖啡厅的票据 (ST) 就可以进入咖啡厅。
- 当用户离开游乐场后,想用这张 TGT 去刷打的回家的费用,对不起,用户的 TGT 已经过期了,在用户离开游乐场那刻开始,用户的 TGT 就已经销毁了。
术语
-
Principal:大致可以认为是 Kerberos 系统的用户名,用于标识身份,如上图所示。
principal 主要由三部分构成:primary,instance(可选) 和 realm。
包含 instance 的principal,一般会作为server端的principal,如:NameNode,HiverServer2,Presto Coordinator等;
不含有 instance 的principal,一般会作为 客户端的principal,用于身份认证,
-
Keytab:"密码本"。包含了多个 principal 与密码的文件,用户可以利用该文件进行身份认证。
-
Ticket Cache:客户端与 KDC 交互完成后,包含身份认证信息的文件,短期有效,需要不断renew。
-
Realm:Kerberos 系统中的一个namespace。不同 Kerberos 环境,可以通过 realm 进行区分。
-
Kerberos 主要由三个部分组成:密钥分发中心 (Key Distribution Center) (即KDC) 、客户端 Client 和 HTTP服务(HTTP Service)。
具体认证流程
-
发送客户端ID, 目标HTTP服务ID, 网络地址(可能是多个机器的IP地址列表,如果想在任何机器上使用,则可能为空),以及请求Ticket Grenting Ticket(TGT) lifetime给**Authentication(AS)**用以请求 TGT
-
**Authentication(AS)通过Key Distribution Center(KDC)**检查客户端ID是否存在
-
数据库AD 将随机生成一个 TGS(Ticket Grenting Server) Session Key ,用于客户端与 Ticket Granting Service(TGS) 通信,并发送给AS
-
AS发送两条信息给客户端:
- Ticket Grenting Ticket(TGT) :由TGS的密钥 加密,客户端无法解密,包含Client ID/name, TGS Session Key、TGS name/ID、timestamp、network address、TGT lifetime。
- 该信息包含TGS name/ID、timestamp、TGT lifetime、TGS Session Key等信息,该信息使用由客户端密钥加密。
-
客户端利用Client密钥解密第二条信息,获得**TGS Session Key 等信息,**无法解密则失败。
客户端密钥是通过提示输入密码、附加一个 salt (由 user@REALMNAME.COM 组成)和散列整个过程来确定的。
之后使用解密的 TSG Session Key 加密的需要访问的HTTP Service Name/ID、Ticket lifetime, Client Id、timestamp创建Authenticatior。
-
发送未解密的TGT 和Authenticator
-
TGS 将利用自身的密钥从TGT中解密出 TGS Session Key ,然后利用 TGS Session Key 从 Authenticator 中解密出请求信息,再进行身份检查,进行认证:
- 比较来自 Authenticator 的时间戳和TGT的timestamp
- 检查 TGT 是否过期 (lifetime)
- 检查 Authenticator 是否已经在TGS的缓存中(为了避免重放攻击)
- 比较TGT中的ClientID 和 Authenticator中的ClientID 是否相同
- 比较 source'IP address 和 TGT中的 address
认证完后生成一个 HTTP Service Session Key并使用HTTP Service 密钥加密一个 HTTP Service Ticket,其中包含:
- client name/id
- HTTP service name/id
- 你的 network address(可能是多台地址或为空)
- timestamp
- ticket lifetime
- HTTP Service Session Key
-
客户端利用缓存的TGS Session Key 解密获得HTTP Service Session Key等信息,但还有HTTP Service Ticket无法解密。
随后使用 HTTP Service Session Key加密生成 Authenticator,其中包括 ClientID/name、timestamp
-
客户端开始请求目标HTTP Service,并附带 HTTP Ticket和Authenticator
-
HTTP Service 首先利用自身的密钥解密 HTTP Service Ticket 的信息,得到 HTTP Service Session Key等信息 ;随后,利用HTTP Session Key 解密出用户的 Authenticator 信息,之后进行检查:
-
比较来自 Authenticator 的时间戳和TGT的timestamp
-
检查 Ticket 是否过期 (lifetime)
-
检查 Authenticator 是否已经在TGS的缓存中(为了避免重放攻击)
-
比较 Ticket 中的ClientID 和 Authenticator中的ClientID 是否相同
-
比较 source'IP address 和 Ticket 中的 address
-
HTTP Service根据认证结果响应客户端请求
配置文件解析
krb5.conf
toml
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = EXAMPLE.COM
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
# default_ccache_name = KEYRING:persistent:%{uid}
[realms]
EXAMPLE.COM = {
kdc = cdh0
admin_server = cdh0
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COM
配置文件默认存放在/etc/krb5.conf,该配置文件包含Kerberos的配置。例如,KDC的位置,Kerberos的admin realms等。需要所有使用的Kerberos的机器上的配置文件都同步。这里仅列举需要的基本配置。
- [logging]:表示server端的日志的打印位置
- [libdefaults]:每种连接的默认配置,需要注意以下几个关键的小配置
- default_realm = EXAMPLE.COM 默认的realm,必须跟要配置的realm的名称一致。
- udp_preference_limit = 1 禁止使用udp,可以防止一个Hadoop中的错误
- ticket_lifetime表明凭证生效的时限,一般为24小时
- renew_lifetime表明凭证最长可以被延期的时限,一般为一周。当凭证过期之后,对安全认证的服务的后续访问则会失败。
- [realms]:列举使用的realm。
- kdc:代表kdc的位置,格式是:机器hostname或ip地址
- admin_server:代表admin的位置,格式是:机器hostname或ip地址
- default_domain:代表默认的域名
- [appdefaults]:可以设定一些针对特定应用的配置,覆盖默认配置。
- [domain_realm]:将instance映射到对应的realm
注:这里需要分发krb5.conf至所有client主机
kdc.conf
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
[realms]
EXAMPLE.COM = {
#master_key_type = aes256-cts
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
max_life = 25h
max_renewable_life = 8d
}
默认存放在/var/kerberos/krb5kdc/kdc.conf,用于启动kdc服务,服务器作为密钥分发中心时需要配置这个文件
- EXAMPLE.COM:是设定的realms,名字随意。Kerberos可以支持多个realms,会增加复杂度。一般为大写。
- max_renewable_life = 8d 涉及到是否能进行ticket的renew必须配置。
- master_key_type:和supported_enctyps默认使用aes256-cts。由于,JAVA使用aes256-cts验证方式需要安装额外的jar包,推荐不使用。
- acl_file:标注了admin的用户权限。文件格式是Kerberos_principal permissions [target_principal] [restrictions]支持通配符等。
- admin_keytab:KDC进行校验的keytab。
- supported_enctypes:支持的校验方式。注意把aes256-cts去掉。
kadm5.acl
toml
*/admin@EXAMPLE.COM *
默认存放在/var/kerberos/krb5kdc/kadm5.acl,以允许具备匹配条件的admin用户进行远程登录权限
标注了admin的用户权限,需要用户自己创建。文件格式是Kerberos_principal permissions [target_principal] [restrictions]支持通配符等。最简单的写法是*/admin@EXAMPLE.COM * 代表名称匹配*/admin@EXAMPLE.COM都认为是admin,权限是*代表全部权限。
常用命令
Kerberos常用命令:
操作 | 命令 |
---|---|
启动kdc服务 | systemctl start krb5kdc |
启动kadmin服务 | systemctl start kadmin |
进入kadmin | kadmin.local / kadmin |
创建数据库 | kdb5_util create -r EXAMPLE.COM -s |
修改当前密码 | kpasswd |
测试keytab可用性 | kinit -k -t /home/xiaobai/xb.keytab xiaobai@EXAMPLE.COM |
查看当前票据 | klist |
查看keytab | klist -e -k -t /home/xiaobai/xb.keytab |
通过keytab文件认证登录 | kinit -kt /home/xiaobai/xb.keytab xiaobai@EXAMPLE.COM |
通过密码认证登录 | kinit xiaobai@EXAMPLE.COM / kint xiaobai |
清除缓存 | kdestroy |
kadmin模式下常用命令(Kerberos进入admin管理模式需要使用root用户):
查看principal | listprincs |
---|---|
生成随机key的principal | addprinc -randkey root/admin@EXAMPLE.COM |
生成指定key的principal | addprinc -pw xxx root/admin@EXAMPLE.COM |
修改root/admin的密码 | cpw -pw xxx root/admin |
添加/删除principal | addprinc/delprinc root/admin |
直接生成到keytab | ktadd -k /home/xiaobai/xb.keytab xiaobai@EXAMPLE.COM xst -norandkey -k /home/xiaobai/xb.keytab xiaobai@EXAMPLE.COM注意:在生成keytab文件时需要加参数"-norandkey",否则导致直接使用kinit xiaobai@EXAMPLE.COM初始化时提示密码错误。 |
设置密码策略(policy) | addpol -maxlife "90 days" -minlife "75 days" -minlength 8 -minclasses 3 -maxfailure 10 -history 10 user |
修改密码策略 | modpol -maxlife "90 days" -minlife "75 days" -minlength 8 -minclasses 3 -maxfailure 10 user |
添加带有密码策略 | addprinc -policy user hello/admin@EXAMPLE.COM |
修改用户的密码策略 | modprinc -policy user1 hello/admin@EXAMPLE.COM |
删除密码策略 | delpol [-force] user |