Paranoid Penguin - 单点登录和企业目录,第一部分

作者:Ti Leggett

所以你想要一个企业目录,但你没有企业预算。你想要获得单点登录的好处,为你自己提供易于管理的便利,为你的用户提供易于使用的便利。如果你想要所有这些,加上一个安全和统一的授权和身份管理系统,请继续阅读。我将引导你走上系统管理员的极乐之路。在本系列文章中,我将向你展示如何在你可能已经拥有的部分基础上构建,添加新的部分,并使它们协同工作。从身份验证服务器到邮件传递,再到客户端集成(包括 Windows 和 OS X)都将讨论。我们有很多内容要介绍,所以让我们开始吧!

使用之前的构建块

我们分别使用 MIT Kerberos V v1.4.1 和 OpenLDAP v2.1.30 在 Gentoo Linux 上运行作为我们的身份验证和身份管理系统。我假设你有三台服务器:kdc.example.com、ldap.example.com 和 mail.example.com。在我们进一步深入之前,你应该首先阅读Linux Journal文章“使用 Kerberos 5 进行集中身份验证,第一部分”和“无处不在的 OpenLDAP”(请参阅在线资源)。我们以这些文章的结尾为基础,但请记住,我们的 Kerberos 域将是 CI.EXAMPLE.COM,我们的基本 DN 将是 o=ci,dc=example,dc=com。此外,本文中引用的所有配置文件都可从在线资源中获得。

设置 SSL 证书颁发机构 (CA)

本节是可选阅读内容,但强烈建议拥有许多使用 SSL 的服务器的站点阅读。每台服务器都可以自签名其自己的证书,但你会失去统一性以及运行你自己的 CA 的一些强大功能。如果你对 OpenSSL 的细节感兴趣,我强烈推荐《使用 OpenSSL 的网络安全》这本书。

我们首先选择 /etc/ssl/example.com 作为存储所有已签名证书、证书吊销列表 (CRL) 和帐户信息的基本目录。创建该目录后,我们然后在基本目录下创建目录 certs、crl、newcerts 和 private。我们创建一个空文件 /etc/ssl/example.com/index.txt,然后创建一个文件 /etc/ssl/example.com/serial

# touch /etc/ssl/example.com/index.txt
# echo '01' > /etc/ssl/example.com/serial

最后,我们创建 CA 的 OpenSSL 配置文件,/etc/ssl/example.com/ca-ssl.cnf。

要创建自签名 CA 证书,我们必须以拥有 /etc/ssl/example.com 目录及其子目录的用户身份执行以下操作,该用户可能是 root

# export OPENSSL_CONF=/etc/ssl/example.com/ca-ssl.cnf
# openssl req -x509 -days 3650 -newkey rsa \
 -out /etc/ssl/example.com/ci-cert.pem -outform PEM
# cp /etc/ssl/example.com/ci-cert.pem /etc/ssl/certs
# /usr/bin/c_rehash /etc/ssl/certs

有关 openssl req 命令的更多详细信息,请查看 req(1) 手册页。

务必将 CA 密钥的密码短语保存在非常安全的地方,因为如果 CA 私钥泄露,则所有先前签名的证书都不可信任。同样重要的是要确保 CA 机器的安全以及对其的访问权限。你如何确保机器的安全取决于你和你的实际安全需求,但如果未经授权的用户获得物理或网络访问权限,他们就可以访问 CA 私钥。正如我上面提到的,CA 私钥的泄露会危及整个信任链,使所有已签名的证书都可疑且不可信。有些人建议 CA 机器应进行物理保护,且没有网络访问权限。为了在这种环境中签署证书,你使用注册机构 (RA) 来接收证书签名请求 (CSR)。然后将 CSR 传输到一些安全的便携式介质,将其带到 CA,在那里 CSR 被签名,并将证书写回到便携式介质上,以便放回 RA 以供最终用户检索。如果你认为你的需求可能需要这样做,那么 OpenCA 项目的设计就考虑了这种类型的安全性。它还支持将已签名证书存储在 LDAP 中。

我们为我们的 CA 创建了一个 OpenSSL 配置文件,但这仅描述了如何请求和签名正好一个证书。我们仍然需要创建一个 OpenSSL 配置,以便从现在开始用于请求普通主机和用户证书:/etc/ssl/example.conf/ssl.cnf。客户端配置比 CA 的配置稍微复杂一些,因为客户端证书可能会出现更多变化。

现在我们有了客户端配置文件,让我们为 LDAP 服务器生成一个主机证书。生成 CSR 可以作为普通用户完成

# export OPENSSL_CONF=/etc/ssl/example.com/ssl.cnf
# openssl req -new -nodes -keyout ldap-key.pem \
 -out ldap-req.pem

使用的 openssl 选项与用于生成 CA CSR 的选项大致相同。唯一的新选项是 -nodes 选项,它创建了一个未加密的私钥。

我们的下一步是让 CA 签署 CSR,以便获得公共证书。同样,这需要以 root 身份完成

# export OPENSSL_CONF=/etc/ssl/example.com/ssl.cnf
# openssl ca -policy policy_anything -out \
 ldap-cert.pem -in ldap-req.pem

此时,我们有三个文件:ldap-cert.pem,公共证书;ldap-key.pem,私钥;以及 ldap-req.pem,CSR。一旦证书被 CA 签名,CSR 就可以丢弃了。同样,保护私钥非常重要,尤其因为它未加密。它可能应该由 root 拥有,并具有 0400 权限。

保护 LDAP

即使密码没有存储在 LDAP 目录中,但仍有很多敏感信息存储在其中。你的用户可能不希望整个互联网都知道他们的电话号码、电子邮件地址或员工 ID。一旦你阅读了“无处不在的 OpenLDAP”并拥有一个正在运行的 LDAP 服务器,你就需要保护信息传输和对目录的访问。

第一步是使用 OpenSSL 保护数据传输。首先,让我们将我们之前签名的证书和密钥复制到 /etc/openldap/ssl/slapd-cert.pem 和 /etc/openldap/ssl/slapd-key.pem,分别。我们需要在 slapd.conf 中提供五个选项:TLSCipherSuite(可选)、TLSCACertificatePath、TLSCertificateFile、TLSCertificateKeyFile 和 TLSVerifyClient。slapd.conf(5) 手册页对这些选项有很好的定义。

在保护了线路上的数据之后,我们现在使用 Kerberos KDC 保护身份验证。OpenLDAP 已 Kerberos 化,并使用 SASL 进行身份验证协商。我们首先必须告诉 slapd 如何找到其 Kerberos 密钥表文件。我们通过编辑 /etc/conf.d/slapd 或在 init 脚本中启动 slapd 之前定义 KRB5_KTNAME 来完成此操作。slapd.conf 中的两个选项也必须定义:sasl-secprops 和 sasl-regexp。

目前,TLS 和 SASL 可以使用但不是必需的。slapd.conf 中的另外两个选项 security 和 allow 用于指定某些操作发生所需的安全方法和加密强度。并且,请务必正确设置访问控制列表 (ACL) - 请参阅 slapd.access(5)。

安全地复制 Kerberos

我们首先将我们的 Kerberos 数据库从 kdc.example.com 复制到 ldap.example.com,这样如果 kdc.example.com 发生故障,ldap.example.com 将接替其工作。要记住的一个重要事实是,任何时候一个域中只能有一个 kadmin 服务器在网络上。否则,数据库更新将没有权威来源。Kerberos 附带 kprop 和 kpropd 以安全地传播 Kerberos 数据库。首先我们必须将 kpropd 识别为已知服务。将以下内容添加到 /etc/services

krb5_prop             754/tcp

我们需要定义一个 ACL 文件 /etc/krb5kdc/kpropd.acl,它告诉 kpropd 哪些主机被允许传播。此文件中真正需要的是主 KDC 的主体名称,但是将所有 KDC 都放在这里也没有坏处,这样如果发生故障,我们可以选择一个新的主服务器,在其上启动 kadmin 服务,并从该主机传播到其他从服务器。

我们现在在我们的从服务器上创建一个 xinetd 服务定义 /etc/xinetd.d/kpropd;(重新)启动 xinetd;在 kdc.example.com 上转储数据库;并将其传播到从服务器,以便它们具有初始配置

# /usr/sbin/kdb5_util dump /etc/krb5kdc/slavedump
# /usr/sbin/kprop -f /etc/krb5kdc/slavedump \
 ldap.example.com

最后,我们使用设置 kdc.example.com 数据库时定义的主密钥在每个从服务器上创建一个隐藏文件,然后启动 kdc 服务

# /usr/sbin/kdb5_util stash
# /etc/init.d/mit-krb5kdc start

为了定期传播 KDC 数据库,我们在 kdc.example.com 上定义一个 cron 作业。感谢 Jason Garman 和 O'Reilly 的《Kerberos:权威指南》这本书提供了原始的 cron 作业。

运行此脚本的合理时间范围是每小时或从 /etc/cron.hourly 运行。我们的 Kerberos 数据库现在正在从主服务器安全地复制到任意数量的从服务器。如果主服务器发生故障,我们有一种方法可以快速切换到从服务器,并最大程度地减少数据丢失(如果有)。现在我们正在传播 Kerberos 更改,我们可以将从服务器添加到 krb5.conf 文件中作为有效的 KDC。

安全地复制 OpenLDAP

你的 LDAP 目录中将存储足够多的关键信息,你可能不希望出现单点故障。毕竟,如果你的 LDAP 目录不可用,你的用户将无法登录、查看电子邮件或执行许多其他日常任务。复制你的 LDAP 目录有助于确保没有单点故障。

让我们将 LDAP 目录从 ldap.example.com 复制到 kdc.example.com。OpenLDAP 有一个名为 slurpd 的守护进程负责此操作。不幸的是,slurpd 没有配置指令告诉它要使用哪个 Kerberos 密钥表,因此需要做一些工作。首先,我们在 ldap.example.com 上编辑 slapd.conf,添加选项 replogfile 和 replica,然后我们重新启动 slapd。

我们需要为 kdc.example.com 创建一个 Kerberos ldap 服务主体和 SSL 证书和密钥,就像我们为 ldap.example.com 所做的那样。我们还必须为 kdc.example.com 创建一个 slapd.conf 文件。此文件与 ldap.example.com 上的文件几乎相同,但有一些关键差异。出于与我们只有一个 Kerberos 管理服务器相同的原因,我们希望只有一个 LDAP 目录被更新和更改。唯一应该能够写入从服务器目录的用户应该是 uid=host/ldap.example.com,cn=GSSAPI,cn=auth 或主服务器的 Kerberos 主体,因此我们在从服务器上的 ACL 更具限制性。此外,slapd 需要知道谁将通过 slurp 发送更新,这由 updatedn 和 updateref 选项定义。

现在我们将注意力转回到 ldap.example.com 一会儿。我们需要创建一个 /etc/conf.d/slurpd 或确保在从 init 脚本启动 slurpd 之前设置了 KRB5CCNAME。

接下来,我们获取一些初始 Kerberos 凭据

# KRB5CCNAME=/var/run/slurpd.krb5cache /usr/bin/kinit -k

然后我们将目录转储到一个文件

ldap# /etc/init.d/slapd stop
ldap# /usr/sbin/slapcat -l /tmp/slavedump.ldif
ldap# /etc/init.d/slurpd start

由于 slurpd 仅传输主目录中的更改,因此我们需要使用主目录的当前状态填充从目录。我们通过将我们在上面创建的主服务器转储 /tmp/slavedump.ldif 复制到 kdc.example.com 并导入转储的目录并启动 slapd 来完成此操作

kdc# /usr/sbin/slapadd -l slavedump.ldif
kdc# /etc/init.d/slapd start
ldap# /etc/init.d/slapd start

我们需要测试从服务器是否具有健全的目录

# ldapsearch -H ldap://kdc.example.com -ZZ

为了测试复制是否正在发生,我们可以在 ldap.example.com 上对目录进行修改或添加,然后在 kdc.example.com 上进行搜索,以确保更改已传播。

一旦我们验证 slurpd 正在工作,我们就在 ldap.example.com 上创建一个 cron 作业,以防止凭据过期。凭据有效期的默认时间限制为十小时,因此如果我们定义一个每八小时运行一次的 cron 作业,我们应该是安全的。

最后,我们将 kdc.example.com 添加到我们的 nss_ldap 有效 LDAP 服务器轮换中。也就是说,我们将 kdc.example.com 附加到 /etc/ldap.conf 中 host 选项指定的服务器列表中。

配置 Postfix MTA

我们将使用 Postfix 邮件传输代理 (MTA) v2.1.5。Postfix 对 SASL 身份验证以及 LDAP 支持(例如别名)具有完善的支持。由于从头开始配置 Postfix 超出了本文的范围,我们将讨论如何启用 Postfix 以使用 SASL 和 TLS。有关设置 Postfix 的信息,请参阅资源。

Postfix 有两个主要配置文件,/etc/postfix/main.cf 和 /etc/postfix/master.cf。main.cf 文件主要负责如何接受传入邮件,而 master.cf 主要负责定义邮件传递代理。

在线资源中包含了一个 main.cf 示例,但要完全理解此文件中的指令,你应该参考 Postfix 文档和网站。

三个主要指令定义了我们的 SMTP 服务器如何与其他 SMTP 服务器交互:smtp_sasl_auth_enable、smtp_use_tls 和 smtp_tls_note_starttls。如果你的 SMTP 服务器将暴露于整个互联网,你应该尽可能灵活地设置这些指令,以确保所有其他 SMTP 服务器都可以与你的服务器通信。但是,如果它是一个仅限内部使用的 SMTP 服务器,你可以通过加强这些指令使其更安全。

更令人感兴趣的部分是我们如何指定我们的用户和机器连接到我们的 MTA 以发送邮件。这里有更多指令需要关注:smtpd_sasl_auth_enable、smtpd_sasl_security_options、smtpd_sasl_tls_security_options、smtpd_use_tls、smtpd_tls_cert_file、smtpd_tls_key_file 和 smtpd_tls_auth_only。

如果你将使用 IMAP 进行邮件传递,请确保在 master.cf 中设置 mailbox_transport 指令和 smtp 和 cyrus 传输机制。

与 OpenLDAP 类似,Postfix 已 Kerberos 化,使用 SASL 进行身份验证协商,并且可以使用 SSL 来保护数据传输。为了保护 Postfix 并将其配置为使用 SASL,除了修改 main.cf 之外,我们还需要执行一些任务。首先,我们创建一个 SSL 证书/密钥对,并将这两个部分放在 /etc/ssl/postfix/smtp-cert.pem 和 /etc/ssl/postfix/smtp-key.pem 中,确保它们由用户 postfix 和组 mail 拥有,并且密钥只能由用户 postfix 读取。接下来,我们为 mail.example.com 创建一个主机主体,并将其保存在正常位置。我们还创建一个服务主体 smtp/mail.example.com@CI.EXAMPLE.COM,并将其保存在 /etc/postfix/smtp.keytab 中。此文件应由 root 拥有,并具有与 smtp-key.pem 文件相同的权限。此外,我们创建一个名为 /etc/sasl2/smtpd.conf 的 SASL 配置文件,并编辑 /etc/conf.d/saslauthd。Postfix 使用 saslauthd 守护进程来获取有关身份验证机制的信息,这两个文件告诉 SASL 如何检查密码、支持哪些机制以及要使用的最小安全层。minimum_layer 的值等同于 OpenLDAP 中的安全强度因子 (SSF)。最后,我们通过创建 /etc/conf.d/postfix 或确保在启动 Postfix 之前在 init 脚本中设置 KRB5_KTNAME 环境变量来告诉 Postfix 其 Kerberos 密钥表文件的位置。完成所有这些任务后,我们可以启动 saslauthd 和 Postfix init 脚本。

LDAP 不仅对于身份管理和授权很有用,而且对于存储 Postfix 的别名映射也很有用。它易于使用和维护,并且无需在每次更改别名数据库时都重建它。第一步是使我们的目录知道我们要将别名映射存储在其中。我们通过将 misc.schema 添加到 slapd 配置中来完成此操作。接下来,我们在目录中为别名创建一个分支。我们将使用 ou=aliases,o=ci,dc=example,dc=com。最后一步是告诉 Postfix 使用 LDAP 作为别名源,方法是将 ldap:/etc/postfix/aliases.cf 添加到 main.cf 中的 alias_maps 指令,并创建 /etc/postfix/aliases.cf 文件,该文件指定如何连接到 LDAP 以及别名在 LDAP 中的位置。我们重新启动 slapd,然后重新启动 Postfix;我们现在准备好添加邮件别名了。我们创建一个名为 alias.ldif 的 LDIF 文件并将其添加到目录中。就这样!

配置 cyrus IMAP MDA

我们将使用 cyrus IMAP 邮件传递代理 (MDA) v2.2.10。完整配置 cyrus IMAP 服务器超出了本文档的范围,但提供了示例工作配置文件。cyrus IMAP 服务器由开发 cyrus SASL 的同一组人开发,因此 SASL 和单点登录支持按预期工作。

与 Postfix 类似,cyrus IMAP 有两个配置文件:/etc/imapd.conf 和 /etc/cyrus.conf。我们将仅处理 /etc/imapd.conf。同样,有一些先决条件:SSL 证书/密钥对、主机主体和服务主体。服务主体应称为 imap/mail.example.com@CI.UCHICAGO.EDU 并存储在 /etc/imap.keytab 中。要启用 SSL,我们相应地定义 tls_ca_path、tls_cert_file 和 tls_key_file 选项。要使用 SASL,我们定义 sasl_pwcheck_method、sasl_mech_list 和 sasl_minimum_layer 选项。这些选项的值与 /etc/sasl2/smtpd.conf 中为 Postfix 设置的值相同。与 Postfix 类似,cyrus IMAP 需要被告知其密钥表文件的位置。我们通过编辑 /etc/conf.d/cyrus 或确保在启动 IMAP 守护进程之前在 init 脚本中设置 KRB5_KTNAME 环境变量来完成此操作。完成所有这些操作后,我们应确保 saslauthd 正在运行,然后启动 imap init 脚本。

总结

我们在短时间内肯定涵盖了很多内容,但所有这些辛勤工作都为你提供了一个安全且可扩展的企业目录。我们刚刚实现了一个系统,该系统适用于一个位置的数十个用户和主机,一直到遍布全球的数千个用户和主机。在我的下一篇文章中,我们将着手将 Linux 和 Apple OS X 客户端绑定到我们的系统中,以看到我们劳动的成果。

致谢

这项工作得到了美国能源部科学办公室高级科学计算研究办公室数学、信息和计算科学部门子计划在合同 W-31-109-ENG-38 下的支持。芝加哥大学计算研究所和国家科学基金会在 Grant SCI: 0451491 下提供了额外支持。

本文的资源: /article/8581

Ti Leggett (leggett@mcs.anl.gov) 是 Argonne 国家实验室数学和计算机科学部未来实验室的系统管理员。他还兼任芝加哥大学计算研究所的职务。

加载 Disqus 评论