16.4.Kerberos ============= Kerberos 是一个网络认证协议,最初由麻省理工学院(MIT)创建,作为一种在潜在的敌对网络中安全地提供认证的方式。Kerberos 协议使用了强大的加密技术,因此客户端和服务器都可以证明他们的身份,而无需在网络上发送任何未加密的秘密。Kerberos 可以被当成一个身份验证代理系统或一个可信的第三方认证系统。在用户通过 Kerberos 认证后,他们的通信会被加密以保证隐私和数据的完整性。 Kerberos 唯一的功能是为网络上的用户和服务器提供安全认证。它并不提供授权或审计功能。建议将 Kerberos 与其他提供授权和审计服务的安全方法一起使用。 如 RFC 4120 中所述,该协议的当前版本是第 5 版。在大部分的操作系统上都有该协议的几种免费实现可用。麻省理工学院持续开发他们的 Kerberos 软件。它在美国通常用作加密产品,并且历来受美国出口法规的约束。在 FreeBSD 中,MITKerberos 可通过二进制包或 port `security/krb5 `__ 获取。Heimdal Kerberos 的实现是明确的在美国境外开发,以避免出口管制。Heimdal Kerberos 软件包含在 FreeBSD 基本系统中。而另一个具有更多可配置选项的软件在 ports 中以 `security/heimdal `__ 提供。 在 Kerberos 中,用户和服务被识别为“主体”(principal),它们被包含在一个管理组中,称为“领域”(realm)。典型的用户的形式是 **user@REALM** (传统上领域是大写的)。 本节提供了如何使用 FreeBSD 中包含的 Heimdal 发行版来设置 Kerberos 的指南。 为了演示 Kerberos 安装,命名空间将如下所示: - DNS 域名(区域)是 ``example.org``\ 。 - Kerberos 领域是 ``EXAMPLE.ORG``\ 。 .. **注意** **设置 Kerberos 时应使用真实域名,即使它将在内部运行。这样可以避免出现 DNS 问题,并确保与其他 Kerberos 域进行交互。** 16.4.1.建立 Heimdal KDC ----------------------- 密钥分发中心(KDC)是 Kerberos 提供的集中式身份验证服务,是系统的“受信的第三方”。是计算机发出 Kerberos 凭据,这些凭据用于客户端向服务器进行身份验证。由于 KDC 被 Kerberos 域的所有其他计算机视为可信,因此它加剧了安全问题。应限制对 KDC 的直接访问。 虽然运行 KDC 只需要很少的计算资源。但出于安全考虑。建议使用一台专用机器充当 KDC。 首先,请按如下方式安装软件包 `security/heimdal `__ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # pkg install heimdal 接下来,使用 ``sysrc`` 更新 **/etc/rc.conf**\ ,如下所示: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # sysrc kdc_enable=yes # sysrc kadmind_enable=yes 接下来,编辑 **/etc/krb5.conf**\ ,如下所示: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session [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 服务器的大型组织来说。上面的例子可以修改为: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session [libdefaults] default_realm = EXAMPLE.ORG [domain_realm] .example.org = EXAMPLE.ORG 在 ``example.org`` 区域文件中加入以下几行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session _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 服务,它们 *必须* 具有完整配置的 **/etc/krb5.conf** 或最简配置的 **/etc/krb5.conf**\ ,\ *并且* 正确的配置 DNS 服务器。 接下来,创建 Kerberos 数据库,它包含了所有主体(用户和主机)的密钥,并以主密码加密。不需要记住这个密码,因为它将被保存在 **/var/heimdal/m-key** 中;为此,使用一个 45 个字符的随机密码比较合适。要创建主密钥,请运行 ``kstash`` 并输入一个密码。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # kstash Master key: xxxxxxxxxxxxxxxxxxxxxxx Verifying password - Master key: xxxxxxxxxxxxxxxxxxxxxxx 主密钥被创建后,就应该初始化数据库。Kerberos 管理工具 `kadmin(8) `__ 可以在 KDC 上以 ``kadmin -l`` 的模式直接操作数据库。而不必使用 `kadmind(8) `__ 网网络服务。这就解决了在数据库创建之前试图连接到数据库的鸡生蛋蛋生鸡的问题。在 ``kadmin`` 提示下,使用 ``init`` 来创建领域的初始数据库: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # kadmin -l kadmin> init EXAMPLE.ORG Realm max ticket life [unlimited]: 最后,在 ``kadmin`` 中,使用 ``add`` 创建第一个主体。现在坚持使用主体的默认选项,因为这些选项可以在以后用 ``modify`` 修改。在提示符下输入 ``?`` 来查看可用的选项。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session 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 服务: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # service kdc start # service kadmind start 虽然此时不会运行任何 kerberized 守护程序,但可以通过获取刚刚创建的主体的凭据来确认 KDC 是否正在运行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % kinit tillman tillman@EXAMPLE.ORG's Password: 使用 ``kilist`` 命令确认已成功获取凭据: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % 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 测试完成后,可以销毁临时凭据: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % kdestroy 16.4.2.配置服务器使用 Kerberos ------------------------------ 将服务器配置为使用 Kerberos 身份验证的第一步是确保它在 **/etc/krb5.conf** 中具有正确的配置。KDC 中的版本可以按原样使用,也可以在新系统上重新生成。 接下来。在服务器上创建 **/etc/krb5.keytab**\ 。这是“Kerberizing”服务的主要部分——它相当于生成一个在服务和 KDC 之间共享的秘密。这个秘密是存储在“keytab”中的一个加密密钥。keytab 包含了服务器的主机密钥,它允许服务器和 KDC 互相验证对方的身份。它必须以安全的方式传送给服务器,因为如果钥匙被公开,服务器的安全就会被破坏。通常,\ **keytab** 是在管理员的信任机器上使用 ``kadmin`` 生成的,然后安全传输(例如使用 `scp(1) `__\ )到服务器;如果符合所需的安全策略,也可以直接在服务器上创建。以安全的方式将密钥表传输到服务器是非常重要的:如果密钥被其他方知道,该方可以冒充任何用户到服务器上! 在服务器上直接使用 ``kadmin`` 是很方便的。因为 KDC 数据库中的主机负责人条目也是用 ``kadmin`` 创建的。 当然,\ ``kadmin`` 是一个 ``kerberized`` 服务;需要 ``Kerberos`` 凭据来验证网络服务。但为了确保运行 ``kadmin`` 的用户确实存在 (并且他们的会话没有被劫持)。\ ``kadmin`` 会提示密码以获得一个新的凭据。正如在 **/var/heimdal/kadmind.acl** 中指定的那样,验证 kadmin 服务的主体必须被允许使用 ``kadmin`` 接口。关于设计访问控制列表的细节,请参见 ``info heimdal`` 中题为“远程管理”的章节。管理员可以通过本地控制台或 `ssh(1) `__ 安全地连接到 KDC。并使用 ``kadmin -l`` 进行本地管理,而不是启用远程 ``kadmin`` 访问。 安装 **/etc/krb5.conf** 后,在 ``kadmin`` 中使用 ``add --random-key``\ 。这将把服务器的主机主密钥添加到数据库中。但不会将主机主密钥的副本提取到钥匙串中。要生成钥匙串,请使用 ``ext`` 来提取服务器的主机主密钥到它自己的钥匙串中: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # 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** 中。当运行在支持 kerberos 的服务器上时,这很好,但是当在其他地方提取 keytab 时,应该使用 ``--keytab`` *path/to/file* 参数: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # kadmin kadmin> ext_keytab --keytab=/tmp/example.keytab host/myserver.example.org kadmin> exit 然后,可以使用 `scp(1) `__ 或可移动设备将密钥表安全地复制到服务器。请务必指定非默认键表名称,以避免将不需要的键插入到系统的键表中。 此时,服务器可以使用存储在 **krb5.keytab** 中的共享密钥从 KDC 读取加密邮件。现在,它已准备好启用使用 Kerberos 的服务。最常见的此类服务之一是 `sshd(8) `__\ ,它通过 GSS-API 支持 Kerberos。在 **/etc/ssh/sshd_config** 中,添加以下行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session GSSAPIAuthentication yes 进行此更改后,必须重新启动 `sshd(8) `__ 才能使新配置生效:\ ``service sshd restart``\ 。 16.4.3.配置客户端使用 Kerberos ------------------------------ 与服务器的情况一样,客户端也需要在 **/etc/krb5.conf** 中进行配置。将该文件复制到原地 (安全地) 或根据需要重新输入。 通过在客户机上使用 ``kinit、klist`` 和 ``kdestroy`` 来获取、显示并删除现有主体的凭据来测试客户机。Kerberos 应用程序也应该能够连接到支持 Kerberos 的服务器。如果这不起作用,而获取 ticket 却起作用。那么问题可能出在服务器上,而不是在客户机或 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`` 的主目录中,那么列出的两个主体都可以访问该帐户,而无需共享密码: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session tillman@example.org jdoe@example.org 有关 **.k5users** 的更多信息,请参阅 `ksu(1) `__\ 。 16.4.4.与 MIT 实现的差异 ------------------------ MIT 和 Heimdal 实现之间的主要区别在于 ``kadmin`` 有一套不同的、但又等价的命令,并使用不同的协议。如果 KDC 是 MIT 的,则 ``Heimdal`` 版本的 ``kadmin`` 就不能用来远程管理 KDC,反之亦然。 客户端应用程序也可能使用略有不同的命令行选项来完成同样的任务。建议遵循 http://web.mit.edu/Kerberos/www/ 上的说明。要注意路径问题:port 中的 MIT 默认会安装到 **/usr/local/**\ 。如果 PATH 中将系统目录列在前面,FreeBSD 版本的系统应用程序会代替 MIT 版本运行。 当在 FreeBSD 上使用 MIT Kerberos 作为 KDC 时。还应该对 **rc.conf** 进行以下编辑: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session kdc_program="/usr/local/sbin/kdc" kadmind_program="/usr/local/sbin/kadmind" kdc_flags="" kdc_enable="YES" kadmind_enable="YES" 16.4.5.Kerberos 提示、技巧和故障排除 ------------------------------------ 在配置 Kerberos 并进行故障排除时,请记住以下几点: - 当通过 ports 使用 Heimdal 或 MITKerberos 时,确保 ``PATH`` 在系统版本之前列出 port 的客户应用程序的版本。 - 如果领域中的所有计算机都没有同步时间设置,则身份验证可能会失败。\ `“NTP 的时钟同步” `__ 介绍了如何使用 NTP 同步时钟。 - 如果更改了主机名,则必须更改 ``host/`` 主体并更新 keytab。这也适用于特殊的 keytab 条目,如 ``HTTP/`` 主体用于 Apache 的 `www/mod_auth_kerb `__\ 。 - 领域中的所有主机必须在 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 中。要让一个主体的凭证寿命超过默认的 10 小时。可以在 `kadmin(8) `__ 提示下使用 ``modify_principal`` 来改变相关主体和 ``krbtgt`` 主体的最大寿命。然后。主体可以使用 ``kinit -l`` 来请求一个寿命更长的凭据。 - 在工作站上运行 ``kinit`` 时,在 KDC 上运行数据包嗅探器以帮助排除故障时,即使在输入密码之前,也会立即发送凭据授予凭据(Ticket Granting Ticket,TGT)。这是因为 Kerberos 服务器会对任何未经授权的请求自由地发送 TGT。然而,每一个 TGT 都被加密在一个从用户的密码衍生出来的密钥中。当用户输入他们的密码时,它不会被发送到 KDC,而是被用来解密 ``kinit`` 已经获得的 TGT。如果解密过程的结果是带有有效时间戳的有效凭据,那么该用户就拥有有效的 Kerberos 凭证。这些凭证包括一个会话密钥,用于在将来与 Kerberos 服务器建立安全通信,以及实际的 TGT,它是用 Kerberos 服务器自己的密钥加密的。这第二层加密允许 Kerberos 服务器验证每个 TGT 的真实性。 - 主机主体可以具有更长的凭据生存期。如果用户主体的生存期为一周,但要连接到的主机的生存期为 9 小时,则用户缓存将具有过期的主机主体,并且凭据缓存将无法按预期工作。 - 在设置 **krb5.dict** 以防止像 `kadmind(8) `__ 中所述使用特定的错误密码时,请记住,它仅适用于分配了密码策略的主体。\ **krb5.dict** 中使用的格式是每行一个字符串,创建指向 **/usr/share/dict/words** 的符号链接可能很有用。 16.4.6.缓解 Kerberos 限制 ------------------------- 由于 Kerberos 是一种全有或全无的方法,因此必须修改网络上启用的每个服务才能与 Kerberos 配合使用,否则必须保护其免受网络攻击。这是为了防止用户凭据被盗和重复使用。例如,在所有远程 shell 上启用了 Kerberos,但非 Kerberized POP3 邮件服务器以纯文本形式发送密码。 KDC 是单点故障。根据设计,KDC 必须与其主密码数据库一样安全。KDC 上绝对不应运行其他服务,并且应该在物理上是安全的。其重大危险在于 Kerberos 存储了使用相同主密钥加密的所有密码,该主密钥作为文件存储在 KDC 上。 主密钥的泄露并不像人们担心的那么糟糕:主密钥仅用于加密 Kerberos 数据库,并用作随机数生成器的种子。只要对 KDC 的访问是安全的,攻击者就无法使用主密钥执行太多操作。 如果 KDC 不可用,则网络服务不可用,因为无法执行身份验证。这可以通过单个主 KDC 和一个或多个从站以及使用 PAM 谨慎小心实现辅助或回退身份验证来缓解。 Kerberos 允许用户、主机和服务在它们之间进行认证。它没有一个机制可以让 KDC 对用户、主机或服务进行认证。这意味着一个被木马化的 ``kinit`` 可以记录所有的用户名和密码。像 `security/tripwire `__ 可以缓解这种情况。 16.4.7.资源和更多信息 --------------------- - `Kerberos 常见问题解答 `__ - `设计身份验证系统:四个场景中的对话 `__ - `RFC 4120,Kerberos 网络身份验证服务(V5) `__ - `MIT Kerberos 主页 `__ - `Heimdal Kerberos 项目维基页面 `__