Kerberos 是一种面向受统一管理系统的网络身份验证协议。用户向受信任的密钥分发中心(KDC)进行身份验证,然后获取面向各个服务的限时票据。服务无需接收用户密码即可验证用户身份,客户端还可以请求证明某个服务持有预期的秘密。
Kerberos 主要使用对称密码学。对称密码学使 KDC 成为集中式信任锚点:如果 KDC 或其数据库遭到入侵,那么 KDC 控制其长期密钥的所有主体都可能受到入侵。因此,Kerberos 以集中式身份管理、高效的票据签发以及领域内的单点登录,换取了对分散式信任的依赖。
信任模型和核心对象 #
**领域(realm)**是一个管理上的身份验证域,通常使用大写形式书写,例如 EXAMPLE.COM。领域名称通常类似于 DNS 域,但两者属于不同的命名空间。配置或 DNS 发现机制会将主机名和域名映射到 Kerberos 领域。
**主体(principal)**表示一个身份:
alice@EXAMPLE.COM
HTTP/web.example.com@EXAMPLE.COM
krbtgt/EXAMPLE.COM@EXAMPLE.COM主体名称由一个或多个组件以及后面的领域组成。alice 是用户主体。HTTP/web.example.com 是服务主体,其第一个组件表示服务,第二个组件表示主机。尽管领域、用户和主机组件的运维约定可能不同,主体字符串仍区分大小写。
每个主体都在 KDC 中注册一个或多个长期密钥。不同类型的主体以不同方式获取这些密钥:
- 人类主体通常通过与加密类型相关的 string-to-key 函数和盐值,从密码派生密钥。
- 服务主体通常接收由管理员生成的随机密钥。
- 领域的
krbtgt/REALM主体拥有用于加密票据授予票据(TGT)的密钥。
keytab 保存主体名称、密钥版本号(KVNO)、加密类型和长期密钥。守护进程使用 keytab,因为无人值守的服务无法输入密码。keytab 是一种凭据,而不是公钥证书;任何能够读取可用服务密钥的人员都可以冒充该服务,并解密为其主体签发的票据。
KDC 提供两个逻辑服务:
- **身份验证服务(AS)**在初始身份验证后签发 TGT。
- **票据授予服务(TGS)**将有效 TGT 兑换为面向特定服务的票据。
两个服务通常运行在同一个 KDC 进程中,并使用同一个领域数据库。生产领域会部署冗余 KDC,因为否则票据获取会依赖单台主机;数据库管理和复制则需要额外的控制措施。
协议流程 #
假设 alice@EXAMPLE.COM 希望访问 HTTP/web.example.com@EXAMPLE.COM。需要通过三次交换来建立所需的凭据。下面的名称描述的是 Kerberos 协议消息,而不是应用特定的数据包。
初始身份验证:AS-REQ 和 AS-REP #
客户端发送 AS-REQ,请求获取面向 krbtgt/EXAMPLE.COM@EXAMPLE.COM 的 TGT。请求包含客户端主体、请求的有效期和标志、nonce、支持的加密类型,以及在需要时包含的预身份验证数据。
基于密码的预身份验证通常包含一个使用从 Alice 密码本地派生的密钥加密的当前时间戳。KDC 查找 Alice 的密钥并验证时间戳。一些客户端会先发送不带预身份验证的 AS-REQ,收到 KDC_ERR_PREAUTH_REQUIRED 以及方法和盐值信息后再重试。第一次错误表示协议协商,而不是身份验证失败。
KDC 返回一个 AS-REP,其中包含两个相关结果:
- 使用领域的
krbtgt密钥加密的 TGT。客户端保存该票据,但无法解密其中受保护的内容。 - 使用 Alice 长期密钥加密的应答数据。应答向客户端提供 TGT 会话密钥、票据时间和标志、nonce 响应以及相关元数据。
成功解密应答证明客户端知道从 Alice 密码派生出的密钥。客户端将 TGT 及其会话密钥放入凭据缓存后,即可丢弃密码。
获取票据:TGS-REQ 和 TGS-REP #
客户端发送面向 HTTP/web.example.com@EXAMPLE.COM 的 TGS-REQ。请求包含:
- 不透明的 TGT;
- 使用 TGT 会话密钥加密的新认证器;
- 请求的服务主体、生命周期、选项、nonce 和支持的加密类型。
KDC 使用 krbtgt 密钥解密 TGT,获取 TGT 会话密钥,然后使用该会话密钥验证认证器。有效的证明将请求与 TGT 内指定的客户端关联起来。
TGS-REP 同样包含两个有用的部分:
- 使用
HTTP/web.example.com的长期密钥加密的服务票据。Alice 无法解密受保护的票据。 - 使用 TGT 会话密钥加密的应答数据。Alice 可以解密这些数据,获取新的客户端—服务会话密钥和票据元数据。
呈现 TGT 不会将 Alice 的密码派生密钥发送给 TGS。但是,由于缓存中也包含关联的会话密钥,窃取 TGT 仍可能在票据过期或撤销控制生效之前实现冒充。
服务身份验证:AP-REQ 和 AP-REP #
客户端向 Web 服务发送 AP-REQ,其中包含:
- 为
HTTP/web.example.com加密的服务票据; - 使用客户端—服务会话密钥加密的新认证器。
服务在其 keytab 中查找匹配的主体、KVNO 和加密类型,解密票据,提取会话密钥,并验证认证器。应用程序或 GSS-API 库还会验证票据时间、名称、校验和以及其他与策略相关的字段。
认证器包含客户端身份和带有亚秒级数据的当前时间戳。它还可以携带针对应用绑定数据的校验和、序列号以及客户端生成的子密钥。服务维护重放缓存,因此同一票据—认证器组合无法在时钟偏差窗口内被重复接受。服务票据可以在其有效期内重复使用,但每次身份验证交换都需要新的认证器。
请求相互身份验证时,服务会返回使用客户端—服务会话密钥加密的 AP-REP。其受保护的时间戳响应,以及可能包含的子密钥和序列号,可以证明对端已解密服务票据。Kerberos 支持相互身份验证,但应用程序必须主动请求并验证,不能假定每个集成都执行该操作。
Client KDC Service
|--- AS-REQ ----------------->| |
|<-- AS-REP: TGT + Kc,tgs ----| |
|--- TGS-REQ: TGT + auth ---->| |
|<-- TGS-REP: ticket + Kc,s ---| |
|--- AP-REQ: ticket + auth ------------------------------->|
|<-- AP-REP, when mutual authentication is requested ------|Kc,tgs 表示 TGT 会话密钥,Kc,s 表示客户端—服务会话密钥。两者都是为协议使用而生成的短期密钥,而不是主体的长期密钥。
为什么密码不会到达服务 #
Alice 的密码是本地 string-to-key 函数的输入。盐值和加密类型会影响生成的密钥,因此相同密码在不同领域或不同 enctype 设置下不一定产生相同的密钥。KDC 保存等价于密码的密钥材料,并验证使用该材料生成的证明;Web 服务只保存自身的随机服务密钥。
因此,Web 服务既不会收到 Alice 的密码,也不会收到 Alice 的长期密钥。它收到的是使用服务密钥加密的票据,并验证使用票据会话密钥生成的认证器。因此,即使服务遭到入侵,也不会直接暴露所有用户的密码。
基于密码的 Kerberos 在某些情况下仍然允许离线猜测。攻击者获取适当的加密协议材料后,可以在不重复联系 KDC 的情况下测试密码候选。预身份验证会阻止 KDC 向未经身份验证的请求签发 AS-REP,但加密时间戳预身份验证本身仍可能提供用于密码猜测的材料。强密码、受保护的 KDC 数据库、现代加密类型、速率控制,以及在支持时使用 PKINIT 或 FAST 等更强的初始身份验证机制,可以降低其中不同部分的风险。
票据内容和加密边界 #
Kerberos 数据包会公开足以进行路由和算法选择的外部结构,同时将身份断言和会话密钥加密给预期的读取者。概念上:
- 票据通过外部字段标识目标领域和服务。其加密部分包含客户端主体、会话密钥、标志、身份验证和到期时间、可选的可续期时间、跨越领域信息、可选的客户端地址以及授权数据。
- TGT 的加密部分由
krbtgt密钥保护,因此 KDC 可以读取。 - 服务票据的加密部分由服务主体的长期密钥保护,因此目标服务可以读取。
- 面向密码身份验证用户的 AS 应答数据由用户长期密钥保护。
- TGS 应答数据使用通过 TGT 交换已经获得的密钥保护,通常是 TGT 会话密钥。
- 认证器由与所呈现票据关联的会话密钥保护。
客户端通过不同的加密边界接收每张票据及其对应的会话密钥。客户端需要会话密钥来构造认证器,但不需要解密票据。同样,服务可以使用自己的密钥解密服务票据,因此不需要 Alice 的长期密钥。
票据标志会改变凭据的使用方式。**可转发(forwardable)的 TGT 可以为另一台主机生成转发凭据,而可续期(renewable)**的 TGT 可以在可续期上限内获得更晚的到期时间。任一标志都不会使票据永久有效;领域策略和票据编码的时间仍然具有决定性。
运维依赖 #
协议正确性依赖名称、时间、传输以及共享密钥状态。因此,许多 Kerberos 故障发生在应用程序评估用户权限之前。
DNS 和名称规范化 #
服务主体会编码主机名,因此 DNS 别名和规范化会影响主体选择。连接到 https://reports.example.com 的客户端可能请求 HTTP/reports.example.com@EXAMPLE.COM,而会规范化名称的库可能请求 HTTP/web17.example.com@EXAMPLE.COM。只有在 KDC 和 keytab 中已配置的主体才会生效。
MIT Kerberos 的 rdns 以及在支持该选项的版本中的 dns_canonicalize_hostname 等设置,会控制主机名规范化的部分行为。设置 rdns = false 可以避免从反向 DNS 推导服务名称。禁用正向规范化也可以使服务名称更可预测,但由于某些客户端库和应用程序会自行执行解析,因此必须测试每个客户端库和应用程序。
Kerberos 可以通过 _kerberos._udp.example.com 和 _kerberos._tcp.example.com 等 DNS SRV 记录发现 KDC。显式的 [realms] 条目可以避免发现歧义。应用程序、TLS 证书、Hadoop _HOST 展开和运维仍需要正向记录与反向记录使用一致的主机名。
时间同步和重放保护 #
认证器包含当前时间,KDC 和服务会强制执行配置的时钟偏差范围。因此,NTP 或其他经过身份验证且受监控的时间服务属于运维依赖。时钟跳变可能使预身份验证失效、导致 KRB_AP_ERR_SKEW,或者使有效票据被判断为尚未生效或已经过期。
重放保护将较短的认证器接受窗口与服务端重放缓存结合起来。为了掩盖文件系统或权限问题而禁用重放缓存,会移除重要的协议防御。服务需要根据进程模型使用可写、私有且稳定的重放缓存位置。
UDP、TCP 和防火墙 #
Kerberos 使用端口 88,当前实现支持 TCP,许多实现也支持 UDP。当组信息和授权数据增大票据尺寸时,大型响应可能超过 UDP 的实际限制。客户端可以通过 TCP 重试,但防火墙必须允许实现选择的传输方式。MIT Kerberos 管理员有时会设置 udp_preference_limit = 1 来优先使用 TCP;该决定应由兼容性和网络策略驱动。管理服务和密码更改服务还使用独立端口,通常 kadmind 使用 TCP 749,密码更改使用 TCP/UDP 464。
跨领域信任 #
跨领域信任允许领域 A.EXAMPLE 中的主体请求领域 B.EXAMPLE 中的服务票据。KDC 通过共享的跨领域 krbtgt 主体建立路径。对于从 A 到 B 的直接路径,两个领域必须为类似以下主体拥有匹配的密钥材料:
krbtgt/B.EXAMPLE@A.EXAMPLE客户端首先从 A 获取跨领域 TGT,然后将其提交给 B 以获取服务票据。层次化领域名称可以隐含一条路径,而 [capaths] 配置可以定义非层次化路径。票据中的 transited 字段会记录路径中的领域,以供策略评估。
信任方向、密钥分发、加密类型兼容性和主体映射都需要明确管理。跨越信任路径的身份验证并不会授予应用访问权限;领域 B 和目标服务仍会应用本地授权策略。
构建一个小型 MIT Kerberos 领域 #
下面的 Debian 或 Ubuntu 示例使用 KDC kdc01.example.com 创建 EXAMPLE.COM。软件包名称、路径、服务单元和默认值因发行版而异,因此软件包文档具有权威性。生产 KDC 应使用专用主机、备份、复制、监控和受限管理。
安装软件包 #
sudo apt-get update
sudo apt-get install krb5-kdc krb5-admin-server krb5-user软件包配置可能会要求输入默认领域和 KDC。下面的文件将示例配置明确写出。
配置客户端和领域映射 #
在 KDC、客户端和服务主机上创建 /etc/krb5.conf:
[libdefaults]
default_realm = EXAMPLE.COM
dns_lookup_realm = false
dns_lookup_kdc = false
rdns = false
dns_canonicalize_hostname = false
ticket_lifetime = 10h
renew_lifetime = 7d
forwardable = false
[realms]
EXAMPLE.COM = {
kdc = kdc01.example.com
admin_server = kdc01.example.com
kpasswd_server = kdc01.example.com
}
[domain_realm]
.example.com = EXAMPLE.COM
example.com = EXAMPLE.COMforwardable = false 使最小权限成为客户端默认行为。需要委派的工作流可以显式请求该功能。使用 DNS KDC 发现的站点可以省略显式 KDC 主机,并在发布和验证 SRV 记录后设置发现选项。
配置 KDC #
在常见的 Debian 派生软件包中,/etc/krb5kdc/kdc.conf 可以包含:
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
[realms]
EXAMPLE.COM = {
database_name = /var/lib/krb5kdc/principal
admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
acl_file = /etc/krb5kdc/kadm5.acl
key_stash_file = /etc/krb5kdc/stash
kadmin_port = 749
max_life = 10h
max_renewable_life = 7d
default_principal_flags = +preauth
supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal
}加密类型必须与所需的最老客户端和服务匹配。AES-SHA2 enctype 可在较新的 Kerberos 协议栈中使用,而较旧的已部署软件可能只能与 AES-SHA1 互操作。管理员应盘点兼容性并有计划地迁移,而不是在没有记录需求的情况下启用过时算法。
在 /etc/krb5kdc/kadm5.acl 中授予专用管理类别广泛权限:
*/admin@EXAMPLE.COM *更严格的 ACL 应仅向自动化和运维人员委派所需操作。KDC 配置、数据库、stash 和 ACL 文件应通过 root 所有权和严格权限保护。
初始化数据库和主体 #
创建领域数据库并将数据库主密钥存入 stash:
sudo kdb5_util create -s -r EXAMPLE.COM
sudo kadmin.local -q "addprinc admin/admin@EXAMPLE.COM"
sudo kadmin.local -q "addprinc alice@EXAMPLE.COM"kdb5_util create 会提示输入数据库主密码。addprinc 会提示输入每个人类主体的密码。kadmin.local 直接访问本地数据库,适合初始引导;远程 kadmin 作为管理主体进行身份验证,并受 kadm5.acl 控制。
数据库创建后再启动服务:
sudo systemctl enable --now krb5-kdc
sudo systemctl enable --now krb5-admin-server
sudo systemctl status krb5-kdc krb5-admin-server单元名称因软件包而异。确认客户端能够访问端口 88,并且仅向需要的管理网络公开管理端口。
创建服务主体和 keytab #
假设名为 websvc 的本地服务账户运行 HTTP 应用程序:
sudo install -d -m 0750 -o root -g websvc /etc/security/keytabs
sudo kadmin.local \
-q "addprinc -randkey HTTP/web.example.com@EXAMPLE.COM"
sudo kadmin.local \
-q "ktadd -k /etc/security/keytabs/web.keytab HTTP/web.example.com@EXAMPLE.COM"
sudo chown websvc:websvc /etc/security/keytabs/web.keytab
sudo chmod 0600 /etc/security/keytabs/web.keytab
sudo klist -k -e -t /etc/security/keytabs/web.keytabktadd 在写入 keytab 时通常会创建新的密钥版本。不了解其更改密钥行为就再次运行,可能使已部署的副本失效。对于复制的服务,应根据站点工具生成或提取一个受控的密钥版本,通过受保护的通道进行分发,在所有位置验证 KVNO,并删除传输产物。绝不要将 keytab 放入源代码管理、容器镜像层或不受限制的配置存储中。
服务账户的权限应只允许该进程读取所需的 keytab 条目。分离服务主体和 keytab 可以降低单个守护进程或主机被入侵时的影响。
使用 Kerberos 客户端 #
获取并检查 TGT:
kinit alice@EXAMPLE.COM
klist -efklist -e 显示加密类型,-f 显示票据标志。在测试应用程序之前,请请求服务票据并确认主体选择正常:
kvno HTTP/web.example.com@EXAMPLE.COM
klistkvno 向 KDC 请求指定的服务票据并报告其 KVNO。成功表明客户端可以找到 KDC、使用 TGT 并定位服务主体,但不能证明服务器 keytab 包含相同的密钥,也不能证明应用程序会接受该票据。
其他核心操作包括:
# 通过 Kerberos 密码服务更改主体密码。
kpasswd alice@EXAMPLE.COM
# 获取一个有效 10 小时、最多可续期 7 天的可转发 TGT。
kinit -f -l 10h -r 7d alice@EXAMPLE.COM
# 续期仍然有效且可续期的 TGT。
kinit -R
# 使用 keytab 对守护进程或诊断进程进行身份验证。
kinit -k -t /etc/security/keytabs/web.keytab \
HTTP/web.example.com@EXAMPLE.COM
# 删除活动凭据缓存。
kdestroy领域策略可能缩短请求的有效期,或拒绝请求的标志。只有在工作流需要委派时才应启用可转发凭据,因为被入侵的中间主机可以在凭据过期前以用户身份使用这些凭据。
凭据缓存和集合 #
Kerberos 客户端将票据和会话密钥存储在凭据缓存中。KRB5CCNAME 可以选择其类型和位置:
export KRB5CCNAME=FILE:/run/user/$(id -u)/krb5cc_example
kinit alice@EXAMPLE.COM
klist
kdestroy常见缓存类型包括 FILE、DIR、内核密钥环和 KCM,具体取决于操作系统和 Kerberos 构建方式。FILE 缓存保存一组主凭据。支持集合的类型可以保存多个主体的凭据,并选择一个主缓存。在支持相应操作的 MIT Kerberos 版本中,klist -l 列出集合成员,klist -A 显示所有缓存,kdestroy -A 销毁整个集合。
脚本不应假设缓存路径是普通文件。容器、sudo、systemd 服务、用户命名空间和 SSH 会话可能改变缓存的可见性和所有权。为自动化设置显式的私有缓存,在退出时清理,并避免在不相关的进程之间共享同一个可变缓存。
集成应用程序 #
应用程序很少直接构造 AS、TGS 和 AP 消息。常见的集成层包括:
- GSS-API,提供安全上下文、相互身份验证、完整性和可选机密性,同时隐藏 Kerberos 消息细节;
- SPNEGO,协商一种 GSS-API 机制,并作为 HTTP Negotiate 的基础;
- SASL/GSSAPI,为 LDAP、Kafka 和数据库连接等协议增加 Kerberos 身份验证。
对于 HTTP Negotiate,浏览器或命令行客户端首先接收质询:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Negotiate支持 GSS-API 的 curl 可以使用当前凭据缓存:
kinit alice@EXAMPLE.COM
curl --negotiate -u : https://web.example.com/protectedcurl 发送包含 GSS-API 交换的 Authorization: Negotiate ... 令牌。服务器加载包含 HTTP/web.example.com@EXAMPLE.COM 的 keytab,接受安全上下文,并将已身份验证的主体映射为应用程序身份。服务器进程通常通过以下实现特定设置接收 keytab 位置:
KRB5_KTNAME=FILE:/etc/security/keytabs/web.keytab ./web-server生产环境的服务管理器应设置该环境变量和 keytab 权限,同时避免将二者暴露给无关进程。
GSS-API 基于主机的名称通常表示为 HTTP@web.example.com;Kerberos 机制会将该形式映射到 HTTP/web.example.com@EXAMPLE.COM 之类的服务主体。客户端必须使用已配置主体所覆盖的主机名。因此,负载均衡器名称和 DNS 别名需要相应的服务主体规划,而不能依赖偶然的规范化。
如果应用程序请求完整性或机密性,GSS-API 可以保护消息。HTTP Negotiate 通常对连接进行身份验证,而 HTTPS 保护 HTTP 标头和正文。服务器证书验证、GSS 封装消息之外的通信机密性,以及 Cookie、持有者令牌和应用程序数据的保护仍然需要 TLS。
跟踪 Kerberized Beeline 到 Kyuubi 的连接 #
考虑一个 Kyuubi 端点,其组织专用名称已匿名化为 mycompany:
jdbc:hive2://kyuubi.hadoop.vip.mycompany.com:10010/default;ssl=true;principal=kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM?kyuubi.session.cluster=analytics-prod#spark.yarn.queue=analytics-high-memory调用 Beeline 时应引用完整 URL,因为 ; 和 # 在 shell 中具有特殊含义:
kinit alice@PROD.MYCOMPANY.COM
klist
kvno kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM
beeline -u \
'jdbc:hive2://kyuubi.hadoop.vip.mycompany.com:10010/default;ssl=true;principal=kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM?kyuubi.session.cluster=analytics-prod#spark.yarn.queue=analytics-high-memory'该 URL 包含多个相互独立的职责:
kyuubi.hadoop.vip.mycompany.com:10010/default选择 Kyuubi 监听器和初始数据库。ssl=true启用 TLS,用于传输加密和服务器证书验证。TLS 与 Kerberos 身份验证相互独立。principal=kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM指定客户端期望 Kyuubi 服务器证明的 Kerberos 身份。它不是 Alice 的主体,也不是密码。kyuubi.session.cluster=analytics-prod选择特定于部署的 Kyuubi 会话集群。spark.yarn.queue=analytics-high-memory为会话的 Spark 引擎请求 YARN 队列。
Kyuubi JDBC 驱动接受 ? 或 # 后的会话属性。较旧的 Hive JDBC URL 解析器对配置后缀和变量后缀的区分更加严格。因此,同时使用两个分隔符的 URL 属于部署契约:已安装的 Beeline 驱动和 Kyuubi 版本必须对这些属性的转发方式达成一致。两个属性都不会更改 Kerberos 服务主体。
Kerberos 参与连接的过程如下:
kinit获取 Alice 的 TGT,并将其与会话密钥一起存入凭据缓存。Beeline 不会从 URL 获取 Alice 的密码。- JDBC 驱动读取缓存,并请求
kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM的服务票据。如果该票据尚未缓存,Kerberos 库会使用 Alice 的 TGT 发送 TGS-REQ。 - 领域的 TGS 返回一个为 Kyuubi 主体加密的服务票据,以及一个 Alice 的 Kerberos 库可以读取的客户端—服务会话密钥。
- 在 JDBC 传输的 SASL/GSSAPI 协商期间,Beeline 发送包含该服务票据和新认证器的 AP-REQ。
- Kyuubi 读取其受保护的 keytab,选择匹配的主体、KVNO 和加密类型,解密票据并验证认证器。相互身份验证允许 Beeline 验证对端持有预期的 Kyuubi 服务密钥。
- Kyuubi 现在获得 Alice 已通过身份验证的 Kerberos 身份。授权规则决定 Alice 是否可以打开会话、选择
analytics-prod、使用请求的 YARN 队列以及访问数据。 - Kyuubi 启动或复用 Spark 引擎时,Hadoop 委派令牌可以将 Alice 已获授权的 HDFS 和 YARN 访问权限传递给分布式应用程序,而无需将 Alice 的 TGT 复制到每个执行器。
主机名同时出现在网络地址和服务主体中,但两项检查彼此独立。TLS 验证 kyuubi.hadoop.vip.mycompany.com 的证书;Kerberos 验证是否持有 kyuubi/kyuubi.hadoop.vip.mycompany.com@PROD.MYCOMPANY.COM 的密钥。DNS 规范化、领域映射、KDC 数据库、Kyuubi 配置的主体以及其 keytab 必须对该身份达成一致。
使用以下命令序列隔离常见故障:
- 没有有效 TGT 时执行
klist,说明服务票据还无法被请求。 kvno报告“server not found in Kerberos database”,表示主体、领域、DNS 或配置之间存在不匹配。kvno成功而 Beeline 报告服务器主体或完整性错误时,应检查 Kyuubi 的 keytab、KVNO、加密类型或配置的服务器名称。- Kerberos 成功而 TLS 失败时,应检查证书链、信任库或证书主机名。
- 身份验证成功而会话或查询被拒绝时,应检查 Kyuubi 策略、YARN 队列授权、SQL 授权或存储权限。
Hadoop 生态系统中的 Kerberos #
安全的 Hadoop 部署使用 Kerberos 在 HDFS、YARN、Hive 及相关服务之间建立守护进程和用户身份。代表性的服务主体包括:
nn/nn01.example.com@EXAMPLE.COM
dn/dn01.example.com@EXAMPLE.COM
rm/rm01.example.com@EXAMPLE.COM
nm/nm01.example.com@EXAMPLE.COM
hive/hive01.example.com@EXAMPLE.COM
HTTP/nn01.example.com@EXAMPLE.COMHadoop 配置通常使用 _HOST:
<property>
<name>hadoop.security.authentication</name>
<value>kerberos</value>
</property>
<property>
<name>dfs.namenode.kerberos.principal</name>
<value>nn/_HOST@EXAMPLE.COM</value>
</property>
<property>
<name>dfs.namenode.keytab.file</name>
<value>/etc/security/keytabs/nn.service.keytab</value>
</property>运行时,Hadoop 会将 _HOST 替换为主机解析出的规范名称。因此,DNS、主机名配置和实际的 KDC 主体必须一致。除非两个主体名称都按预期进行了配置,否则 nn/nn01.example.com keytab 无法满足对 nn/namenode-alias.example.com 的请求。
NameNode、DataNode、ResourceManager、NodeManager、HiveServer2 和 HTTP 端点需要使用组件安全文档规定的服务主体和 keytab 条目。所有守护进程共享一个 keytab 会扩大入侵影响范围,并使密钥轮换更加困难。
Hadoop 客户端首先使用 Kerberos 进行身份验证,然后可以为受支持的服务获取委派令牌。委派令牌是由 Hadoop 服务的秘密管理器签发并验证的限时持有者式凭据。令牌允许分布式作业访问 HDFS 或其他服务,而不必为每次 RPC 联系 KDC,也不必将用户 TGT 复制到每个任务。令牌范围、续期、撤销和最大有效期由服务决定,令牌被窃取后可以在这些限制内使用。
Kerberos 回答的是哪个主体发起了连接。HDFS 权限和 ACL、YARN 队列策略、Hive 或 SQL 权限、代理用户规则以及外部授权系统决定该主体可以执行什么操作。主体到本地名称的规则(例如 Hadoop 的 auth_to_local 映射)也需要审查,因为意外映射可能将不同的 Kerberos 身份合并到同一个本地账户。
安全实践 #
Kerberos 部署需要围绕每个长期密钥和每个可重用凭据实施控制:
- 将每个 keytab 限制给其服务账户,仅包含所需主体,避免将同一个 keytab 复制到无关主机。
- 通过考虑 KVNO 传播、运行中进程、复制主机以及使用旧密钥签发的票据的流程轮换服务密钥。突然删除旧密钥可能导致尚未过期的票据失效。
- 保持客户端、KDC 和服务的加密类型支持兼容。在禁用某个 enctype 前,同时检查票据和 keytab。
- 除非经过审查的机制需要例外,否则要求密码主体进行预身份验证。使用强密码策略,并在威胁模型要求时使用更强的预身份验证机制。
- 保护凭据缓存和转发凭据。SSH 凭据委派和应用程序冒充功能会扩大能够以某个用户身份操作的主机范围。
- 为 KDC 打补丁并进行隔离,限制管理访问,安全备份领域数据库和主密钥材料,并测试恢复过程。
- 不要将密码、keytab、KDC 数据库转储、stash 文件和凭据缓存放入代码仓库、日志、支持包或镜像层。
- 即使 Kerberos 已对端进行身份验证,也要使用 TLS。Kerberos 不会自动加密每个应用程序的传输。
密钥轮换需要规划重叠期。KDC 可以保留多个按 KVNO 和 enctype 区分的服务密钥,keytab 也可以包含多个条目。确切的轮换行为取决于 KDC 工具和应用程序重新加载 keytab 的行为,因此应在废弃旧密钥前验证新票据、仍未过期的旧票据以及每个副本。
按因果层排查问题 #
从应用程序层以下开始排查。浏览器错误或通用 GSS 异常往往封装了领域、DNS、时钟、缓存或 keytab 故障。
跟踪票据获取 #
MIT Kerberos 可以跟踪库的决策:
env KRB5_TRACE=/dev/stderr kinit alice@EXAMPLE.COM
env KRB5_TRACE=/dev/stderr \
kvno HTTP/web.example.com@EXAMPLE.COM跟踪输出会显示配置文件、KDC 选择、预身份验证协商、缓存操作、引荐、主机名决策和传输重试。跟踪可能包含主体名称和运维元数据,因此在共享前应进行清理。
检查凭据和服务器密钥:
klist -ef
sudo klist -k -e -t /etc/security/keytabs/web.keytab
kvno HTTP/web.example.com@EXAMPLE.COM将已获取票据报告的服务主体、KVNO 和 enctype 与守护进程可用的条目进行比较。同时确认运行中的进程读取的是运维人员检查的 keytab,而不是其他路径或过期的容器密钥。
验证名称、时间和传输 #
hostname -f
getent hosts web.example.com
dig +short -x 192.0.2.20
dig +short SRV _kerberos._tcp.example.com
timedatectl status正向解析、反向解析、配置的服务主机名、TLS 名称和 KDC 主体在每种设计中不一定必须相同,但差异必须是有意的,并且得到客户端规范化规则的支持。当小请求可以工作但大响应失败时,应检查所需传输方式上的端口 88 以及防火墙。
将常见错误映射到原因 #
| 错误或症状 | 可能的因果检查 |
|---|---|
Cannot find KDC for realm | 领域拼写、[realms]、[domain_realm]、DNS SRV 记录、解析器状态和网络可达性 |
Client not found in Kerberos database | 客户端主体拼写、领域选择、已删除账户或意外的企业主体映射 |
Preauthentication failed | 密码错误、客户端对旧盐值的假设、禁用或不兼容的预身份验证方法,或主体密钥不匹配 |
Clock skew too great / KRB_AP_ERR_SKEW | 客户端、KDC 和服务时钟;NTP 状态;虚拟机恢复或时钟跳变 |
Server not found in Kerberos database | 请求的主机名、服务类、领域、DNS 规范化、负载均衡器别名或缺失的服务主体 |
No key table entry found | 错误的 keytab 路径、缺少主体、不支持的 enctype、无法读取的 keytab,或使用其他身份的守护进程 |
KRB_AP_ERR_MODIFIED / 无法解密票据 | 过期 keytab、KVNO 不匹配、错误主机上的重复主体、DNS 将流量发送到没有匹配密钥的主机,或 enctype 不匹配 |
Replay cache 错误 | 重用的认证器、共享或不可写的重放缓存路径、克隆的进程状态,或实际发生的重放 |
| 凭据缓存缺失或过期 | KRB5CCNAME、进程 UID、容器或 sudo 边界、票据时间、可续期上限或已销毁的缓存 |
| 仅在大型票据上失败 | UDP 分片、被阻断的 TCP/88、代理或防火墙限制,或增大的授权数据 |
| 身份验证成功但访问被拒绝 | 应用程序身份映射、本地账户映射、ACL、HDFS 权限、YARN 队列、Hive 权限或其他授权策略 |
错误文本因实现而异。来自 KRB5_TRACE、KDC 日志、服务日志、klist、kvno、DNS 工具和同步时间戳的证据,比一次更改多个配置选项更可靠。
边界和限制 #
Kerberos 在配置的信任关系内提供身份验证和共享会话密钥建立。Kerberos 本身不提供:
- 授权: 应用程序仍需执行权限、角色、ACL 和策略。
- 通用传输加密: 应用程序必须请求 GSS 机密性,或使用 TLS 等传输方式。
- 目录服务: LDAP、Active Directory、数据库或本地映射可以存储配置文件、组和属性。
- 互联网范围的公钥身份: 领域需要预先配置 KDC 和信任关系;Kerberos 不是 Web PKI 的替代品。
- 免受入侵: 被窃取的 keytab、凭据缓存、KDC 密钥或委派令牌,在其范围和有效期内仍是可用凭据。
集中式管理既解释了 Kerberos 的价值,也解释了其运维负担。由于 KDC 通过加密票据为主体背书,服务无需收集用户密码;但可靠的身份验证依赖于 KDC 安全、密钥分发、主体命名、DNS 行为、时间同步和应用层验证。
官方参考 #
- MIT Kerberos Documentation
- MIT Kerberos: Installing KDCs
- MIT Kerberos:
krb5.conf - MIT Kerberos:
kdc.conf - RFC 4120: The Kerberos Network Authentication Service (V5)
- RFC 4121: Kerberos Version 5 GSS-API Mechanism
- RFC 4178: SPNEGO
- RFC 4559: SPNEGO-Based Kerberos and NTLM HTTP Authentication
- Apache Hadoop: Secure Mode
评论
在 GitHub 上阅读或评论(发表评论需要登录)