16.9.Kerberos

Kerberos 是一个网络身份验证协议,最初由麻省理工学院(MIT)创建,作为一种安全地提供跨潜在敌对网络的身份验证的方式。Kerberos 协议使用强加密技术,以便客户端和服务器可以证明其身份,而不会在网络上发送任何未加密的秘密。Kerberos 可以说明为一个验证身份的代理系统和一个受信任的第三方身份验证系统。用户与 Kerberos 进行身份验证后,他们的通信可以加密,以确保隐私和数据完整性。

Kerberos 的唯一功能是在网络上为用户和服务器提供安全身份验证。它不提供授权或审计功能。建议将 Kerberos 与提供授权和审计服务的其他安全方法一起使用。

该协议的当前版本是版本 5,说明在 RFC 4120 中。可用的该协议的几个免费实现覆盖了各种操作系统。MIT 一直在开发他们的 Kerberos 软件包。它在美国作为一种密码学产品通常被使用,并且在历史上受到美国出口管制的限制。在 FreeBSD 中,MITKerberos 可作为安全/krb5 包或port 使用。Heimdal Kerberos 实现是明确在美国以外开发的,以避免出口管制。Heimdal Kerberos 发行版包含在基本的 FreeBSD 安装中,另一个具有更多可配置选项的发行版可在Ports 中的安全/heimdal 中找到。

在 Kerberos 中,用户和服务被标识为“主体”,这些“主体”包含在一个管理分组内,称为“领域”。典型的用户主体形式可能类似于 user@REALM (领域通常是大写)。

本节介绍如何使用 FreeBSD 中包含的 Heimdal 发行版设置 Kerberos。

为了演示 Kerberos 安装,名称空间将如下所示:

  • DNS 域(区域)将是 example.org。

  • 凯比特存储库将会 EXAMPLE.ORG。

16.9.1. 设置 Heimdal KDC

密钥分发中心(KDC)是 Kerberos 提供的集中式认证服务,是系统的“可信第三方”。它是发放 Kerberos 票据的计算机,用于客户端认证到服务器。由于 KDC 被认为是 Kerberos 领域中所有其他计算机信任的对象,因此存在较高的安全性问题。应限制对 KDC 的直接访问。

虽然运行 KDC 所需的计算资源很少,但出于安全原因,建议使用专用机器仅作为 KDC。

要开始,请按照以下方式安装 security/heimdal 软件包:

# pkg install heimdal

然后,使用 sysrc 更新/etc/rc.conf 如下:

# sysrc kdc_enable=yes
# sysrc kadmind_enable=yes

然后,按照以下步骤编辑/etc/krb5.conf:

[libdefaults]
    default_realm = EXAMPLE.ORG
[realms]
    EXAMPLE.ORG = {
	kdc = kerberos.example.org
	admin_server = kerberos.example.org
    }
[domain_realm]
    .example.org = EXAMPLE.ORG

在本例中,KDC 将使用完全合格的主机名 kerberos.example.org。KDC 的主机名必须在 DNS 中可解析。

Kerberos 也可以使用 DNS 来定位 KDC,而不是在 /etc/krb5.conf 中的 [realms] 部分。对于拥有自己 DNS 服务器的大型组织,上述示例可以被精简为:

[libdefaults]
      default_realm = EXAMPLE.ORG
[domain_realm]
    .example.org = EXAMPLE.ORG

以下行包含在 example.org 区域文件中:

_kerberos._udp      IN  SRV     01 00 88 kerberos.example.org.
_kerberos._tcp      IN  SRV     01 00 88 kerberos.example.org.
_kpasswd._udp       IN  SRV     01 00 464 kerberos.example.org.
_kerberos-adm._tcp  IN  SRV     01 00 749 kerberos.example.org.
_kerberos           IN  TXT     EXAMPLE.ORG

接下来,创建包含所有主体(用户和主机)密钥加密的 Kerberos 数据库,主密码存储在/var/heimdal/m-key 中,不需要记住该密码,可以使用一个 45 个字符的随机密码来实现这个目的。执行 kstash 以创建主密钥,并输入密码:

# kstash

输出应该类似于以下内容:

Master key: xxxxxxxxxxxxxxxxxxxxxxx
Verifying password - Master key: xxxxxxxxxxxxxxxxxxxxxxx

创建了主密钥后,应初始化数据库。可以在 KDC 上使用 Kerberos 管理工具 kadmin(8)以直接操作数据库的模式进行操作,而无需使用 kadmind(8)网络服务,如 kadmin -l。这解决了在数据库创建之前尝试连接到数据库的鸡生蛋问题。在 kadmin 提示符下,使用 init 来创建领域的初始数据库:

# kadmin -l
kadmin> init EXAMPLE.ORG
Realm max ticket life [unlimited]:

最后,在 kadmin 中,使用 add 创建第一个主体。现在先使用默认选项,稍后可以使用 modify 更改这些选项。在提示符下输入 ? 以查看可用选项。

kadmin> add tillman

输出应类似于以下内容:

Max ticket life [unlimited]:
Max renewable life [unlimited]:
Principal expiration time [never]:
Password expiration time [never]:
Attributes []:
Password: xxxxxxxx
Verifying password - Password: xxxxxxxx

接下来,通过运行以下命令启动 KDC 服务:

# service kdc start
# service kadmind start

在这一点上不会运行任何 Kerberized 守护程序,但可以通过为刚刚创建的主体获取票证来确认 KDC 是否正在运行:

% kinit tillman

输出应类似于以下内容:

tillman@EXAMPLE.ORG's Password:

使用 klist 确认已成功获取票证:

% klist

输出应类似于以下内容:

Credentials cache: FILE:/tmp/krb5cc_1001
	Principal: tillman@EXAMPLE.ORG

  Issued                Expires               Principal
Aug 27 15:37:58 2013  Aug 28 01:37:58 2013  krbtgt/EXAMPLE.ORG@EXAMPLE.ORG

在测试完成时可以销毁临时票证:

% kdestroy

16.9.2. 配置服务器以使用 Kerberos

配置服务器以使用 Kerberos 身份验证的第一步是确保它在/etc/krb5.conf 中具有正确的配置。可以直接使用来自 KDC 的版本,或者在新系统上重新生成。

接下来,在服务器上创建/etc/krb5.keytab。这是对服务进行"Kerberizing"的主要部分 - 它对应于生成一个服务与 KDC 之间共享的秘密。这个秘密是一个加密密钥,存储在"keytab"中。keytab 包含了服务器的主机密钥,这使得服务器和 KDC 能够相互验证彼此的身份。它必须以安全的方式传输到服务器,因为如果密钥被公开,服务器的安全性可能会受到破坏。通常,keytab 在管理员信任的机器上使用 kadmin 生成,然后以安全的方式传输到服务器,例如使用 scp(1);它也可以直接在服务器上创建,如果这符合所需的安全策略。非常重要的是以安全的方式将 keytab 传输到服务器:如果密钥被其他某方知晓,该方可以冒充任何用户对服务器进行身份验证!在服务器上直接使用 kadmin 很方便,因为 KDC 数据库中的主机主体条目也是使用 kadmin 创建的。

当然,kadmin 是一种 kerberized 服务;需要 Kerberos 票证才能对网络服务进行身份验证,但为了确保运行 kadmin 的用户确实存在(并且其会话未被劫持),kadmin 将提示输入密码获取新的票证。对于要认证到 kadmin 服务的主体,必须允许使用 kadmin 接口,在/var/heimdal/kadmind.acl 中指定。请参阅 info heimdal 中标题为"远程管理"的部分,了解有关设计访问控制列表的详细信息。管理员可以通过本地控制台或 ssh(1)与 KDC 进行安全连接,并使用 kadmin -l 在本地执行管理操作,而不是启用远程 kadmin 访问。

安装完 /etc/krb5.conf 后,在 kadmin 中使用 add --random-key。这会将服务器的主机主体添加到数据库,但不会将主机主体密钥的副本提取到关键表中。要生成关键表,请使用 ext 将服务器的主机主体密钥提取到其自己的关键表中:

# kadmin

输出应该类似于以下内容:

kadmin> add --random-key host/myserver.example.org
Max ticket life [unlimited]:
Max renewable life [unlimited]:
Principal expiration time [never]:
Password expiration time [never]:
Attributes []:
kadmin> ext_keytab host/myserver.example.org
kadmin> exit

请注意,ext_keytab 默认情况下将提取的密钥存储在 /etc/krb5.keytab 中。当在进行 kerberized 的服务器上运行时,这是很好的,但是提取关键表到其他地方时应该使用 --keytab path/to/file 参数:

# kadmin

输出应类似于以下内容:

kadmin> ext_keytab --keytab=/tmp/example.keytab host/myserver.example.org
kadmin> exit

然后可以使用 scp(1)或可移动介质将 keytab 安全地复制到服务器。请确保指定非默认 keytab 名称,以避免将不需要的密钥插入系统的 keytab 中。

此时,服务器可以使用存储在 krb5.keytab 中的共享密钥从 KDC 读取加密消息。现在可以启用使用 Kerberos 的服务。最常见的此类服务之一是 sshd(8),它通过 GSS-API 支持 Kerberos。在/etc/ssh/sshd_config 中添加以下行:

GSSAPIAuthentication yes

进行此更改后,必须重启 sshd(8)以使新配置生效: service sshd restart .

16.9.3. 配置客户端以使用 Kerberos

就像服务器一样,客户端需要在/etc/krb5.conf 中进行配置。将文件复制到指定位置(安全地)或根据需要重新输入。

通过使用客户端来测试 kinit,klist 和 kdestroy,从客户端获取、显示,然后删除现有主体的票证。Kerberos 应用程序也能够连接到启用了 Kerberos 的服务器。如果这样做不起作用,但获取票证可以,问题很可能出在服务器上,而不是客户端或 KDC 上。对于 kerberized ssh(1),默认情况下禁用了 GSS-API,因此请使用 ssh -o GSSAPIAuthentication=yes hostname 进行测试。

在测试 Kerberized 应用程序时,请尝试使用类似 tcpdump 这样的数据包嗅探器来确认没有敏感信息以明文形式发送。

可用各种 Kerberos 客户端应用程序。随着一座桥梁的出现,以便使用 SASL 进行身份验证的应用程序也能够使用 GSS-API 机制,大量的客户端应用程序可以使用 Kerberos 进行身份验证,从 Jabber 客户端到 IMAP 客户端。

领域内的用户通常将其 Kerberos 主体映射到本地用户账户。偶尔,需要将对本地用户账户的访问权限授予没有匹配的 Kerberos 主体的人。例如,tillman@EXAMPLE.ORG 可能需要访问本地用户账户 webdevelopers。其他主体也可能需要访问该本地账户。

放置在用户的主目录中的.k5login 和.k5users 文件可用于解决此问题。例如,如果将以下.k5login 放置在 webdevelopers 的主目录中,则列出的两个主体将能够访问该账户,而无需共享密码:

tillman@example.org
jdoe@example.org

有关.k5users 的更多信息,请参考 ksu(1)。

16.9.4. MIT 差异

MIT 和 Heimdal 实现之间的主要区别是 kadmin 具有不同但等效的一组命令,并使用不同的协议。如果 KDC 是 MIT,请注意,无法使用 Heimdal 版本的 kadmin 远程管理 KDC,反之亦然。

客户端应用程序也可以使用稍有不同的命令行选项来执行相同的任务。建议按照 http://web.mit.edu/Kerberos/www/ 上的说明进行操作。注意路径问题:默认情况下,MIT port 安装到 /usr/local/,如果 PATH 列出系统目录在前,则 FreeBSD 系统应用程序将代替 MIT 版本运行。

当在 FreeBSD 上使用 MIT Kerberos 作为 KDC 时,执行以下命令将所需的配置添加到/etc/rc.conf 中:

# sysrc kdc_program="/usr/local/sbin/krb5kdc"
# sysrc kadmind_program="/usr/local/sbin/kadmind"
# sysrc kdc_flags=""
# sysrc kdc_enable="YES"
# sysrc kadmind_enable="YES"

16.9.5. Kerberos 提示、技巧和故障排除

在配置和故障排除 Kerberos 时,请牢记以下要点:

  • 当使用 Heimdal 或 MITKerberos 时,确保 ports 中列出的客户端应用程序版本在系统版本之前。

  • 如果领域中的所有计算机未同步时间设置,认证可能会失败。“使用 NTP 进行时钟同步”说明了如何使用 NTP 同步时钟。

  • 如果主机名更改,host/ 主体必须更改,然后更新 keytab。这也适用于用于 Apache 的 www/mod_auth_kerb 的 HTTP/ 主体等特殊 keytab 条目。

  • 在领域中,所有主机必须在 DNS 中同时具有正向解析和反向解析功能,或者至少存在于 /etc/hosts 中。CNAME 将起作用,但必须正确放置 A 记录和 PTR 记录。对于无法解析的主机,错误消息并不直观: Kerberos5 refuses authentication because Read req failed: Key table entry not found .

  • 作为 KDC 的客户端的某些操作系统未设置 ksu 的权限为 setuid root。这意味着 ksu 无法工作。这是一个权限问题,而不是 KDC 错误。

  • 使用 MITKerberos,要允许一个主体的票据生存期超过默认的十小时,可以在 kadmin(8) 提示符下使用 modify_principal 来更改问题主体和 krbtgt 主体的 maxlife。然后该主体可以使用 kinit -l 来请求一个更长生存期的票据。

  • 运行数据包嗅探器以帮助故障排除时,在工作站上运行 kinit 时,票证授予票证(TGT)会立即发送,甚至在密码输入之前。这是因为凯伯罗斯服务器会自由地向任何未经授权的请求传输 TGT。然而,每个 TGT 都是用用户密码衍生的密钥加密的。当用户输入他们的密码时,密码不会被发送到 KDC,而是用于解密 kinit 已经获得的 TGT。如果解密过程产生具有有效时间戳的有效票证,则用户具有有效的凯伯罗斯凭证。这些凭证包括用于将来与凯伯罗斯服务器建立安全通信的会话密钥,以及实际的 TGT,该 TGT 被凯伯罗斯服务器自己的密钥加密。这种第二层加密允许凯伯罗斯服务器验证每个 TGT 的真实性。

  • 主机主体可以具有较长的票证生存期。如果用户主体的生存期为一周,但所连接的主机的生存期为九小时,则用户缓存将具有过期的主机主体,票证缓存将无法正常工作。

  • 在设置 krb5.dict 以防止特定不良密码被用作 kadmind(8)中说明的一样,记住它仅适用于分配了密码策略的主体。krb5.dict 中使用的格式是每行一个字符串。创建指向/usr/share/dict/words 的符号链接可能会有用。

16.9.6. 缓解 Kerberos 的限制

由于 Kerberos 是一种全盘或全无的方法,网络上启用的每个服务都必须修改为与 Kerberos 配合使用,或者以其他方式防止网络攻击。这是为了防止用户凭据被窃取并重复使用。一个例子是,当 Kerberos 在所有远程服务器上启用时,非 Kerberized 的 POP3 邮件服务器以明文形式发送密码。

KDC 是一个单点故障。根据设计,KDC 必须与其主密码数据库一样安全。KDC 不应该在上面运行任何其他服务,并且应该在物理上是安全的。危险很高,因为 Kerberos 使用相同的主密钥对所有密码进行加密,而该主密钥存储在 KDC 上的文件中。

一个受损的主密钥并不像人们想象的那么糟糕。主密钥仅用于加密 Kerberos 数据库并用作随机数生成器的种子。只要对 KDC 的访问是安全的,攻击者无法利用主密钥做太多事情。

如果 KDC 不可用,网络服务将无法使用,因为无法执行身份验证。通过使用单个主 KDC 和一个或多个从属,以及仔细实施使用 PAM 的次级或备用身份验证,可以减轻这种情况。

Kerberos 能让用户、主机和服务之间进行身份验证。它没有一种机制可以对用户、主机或服务身份验证 KDC。这意味着一个木马 kinit 可以记录所有用户名和密码。诸如安全/行程跳线之类的文件系统完整性检查工具可以减轻这种情况。

资源和进一步信息

最后更新于

FreeBSD 中文社区