NEW:在 TwitterMastodon 获取项目更新。

RFC-2136

本文档的目的是提供在符合 RFC2136 的 DNS 服务器(如 BIND named)上部署 cert-manager 所需的各种设施的配置概述。此功能通常也称为“动态 DNS”。

与其他 cert-manager DNS 集成的同类产品不同,named 类似于“瑞士军刀”,是域名服务器的综合工具。多年来,它经过高度优化,为单个节点提供了最大化的垂直可扩展性,以及通过服务提供商接口实现的水平可扩展性。这种灵活性使得不可能涵盖用户可能会遇到的所有可能的 named 部署方式。相反,本文档将尝试确保您的服务器准备使用命令行工具接受来自 cert-manager 的请求,然后开始将两者结合在一起。

事务签名 ⇒ TSIG

动态 DNS 更新本质上是服务器查询,否则可能会返回资源记录 (RR)。由于 DNS 服务器通常暴露在公共互联网上,因此能够将未经身份验证的更新推送到响应查询的任何服务器将立即变得无法维持。

named 架构师眼中,解决此问题空间的通用解决方案是双重的。第一个是要求在区域级别手动启用更新,例如 example.com。在简单的网络中,不需要区域更新有任何安全性,并且可以配置客户端,使它们能够在没有任何身份验证的情况下提供更新。一个有用的示例是使用 DHCP 启动的机器,在这种情况下,机器了解自身,并且可以配置 DNS 服务器,使其在从正在配置的地址接收更新时接受更新。

这在 cert-manager 和 DNS01 挑战等情况下显然存在局限性。在此环境中,必须在与 ACME 服务器协调后创建 TXT RR。在与 ACME 服务器协商后,发布在域上的 TXT RR 将验证该域是否合法地参与了为其创建证书的过程。从 DNS 的更大图景来看,这意味着任意行为者(在本例中为 cert-manager)必须能够将这些 KV 映射之一添加到域中,并在证书颁发后将其删除。 cert-manager 没有 DHCP 分配之类的便捷物理特性来验证其请求。

对于这种情况,我们需要能够对发送到 DNS 服务器的请求进行签名。我们通过 TSIG(事务签名)来实现这一点。

配置步骤 1 - 为安全动态更新设置您的 DNS 服务器

网上有很多优秀的教程介绍了如何为动态更新准备基本的 named 服务器

更复杂的 name 部署将不会使用文本文件,而是可能使用 LDAP 或 SQL 作为资源记录的数据库。另一个细节是元数据配置,例如区域元数据(如启用动态更新或区域的访问控制列表 (ACL))。这里有太多配置无法详细说明,但您应该能够找到相应的文档。

无论您的部署是什么,此阶段的目标与 cert-manager 无关,而与名为 nsupdate 的工具有关,该工具用于生成使用 TSIG 签名的更新。一旦完成了这一步,您就可以更加自信地处理 cert-manager 配置。

使用 nsupdate

大多数配置 BIND named 的方法都将使用 dnssec-keygen。此命令行工具会生成一个名为私钥,用于签署 TSIG 请求。对请求进行签名时,签名和私钥的名称将以未加密的形式附加到请求中。这样,当接收请求时,接收者可以使用私钥的名称找到私钥本身,用它构建新的签名,并比较这两个签名以确定是否接受。

由于您的 named 服务器存在几十种配置错误的方式,因此我们将在开始使用 cert-manager 之前,使用 nsupdate 测试服务器是否按预期运行。 https://debian-administration.org/article/591/Using_the_dynamic_DNS_editor_nsupdate 详细介绍了如何使用该工具。

要开始,我们只需运行 nsupdate -k <keyID>,其中 keyIDdnssec-keygen 返回的值。这将从磁盘读取密钥并提供命令提示符来发出命令。通常,我们希望编写一个简单的 TXT RR 并确保能够将其删除。

$ nsupdate -k <keyID>
update add www1.example.com 60 txt testing
send
test here with `nslookup`
update delete www1.example.com txt
send
test here with `nslookup`

无法写入、读取或删除记录将意味着 cert-manager 也不会能够这样做,无论其配置如何完善。

配置步骤 2 - 设置 cert-manager

现在我们开始有趣的部分,见证一切的运作。请记住,我们需要设置 ACME DNS01 发行者和挑战机制,以及 rfc2136 提供者。由于文档对其他部分的介绍已经足够充分,因此让我们在这里重点关注提供者。

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: example-issuer
spec:
acme:
...
solvers:
- dns01:
rfc2136:
nameserver: <address of authoritative nameserver configured above>
tsigKeyName: <key name used in `dnssec-keygen`, use something semantically meaningful in both environments>
tsigAlgorithm: HMACSHA512 // should be matched to the algo you chose in `dnssec-keygen`
tsigSecretSecretRef:
name: <the name of the k8s secret holding the TSIG key.. not the key itself!>
key: <name of the key *inside* the secret>

例如

rfc2136:
nameserver: 1.2.3.4:53
tsigKeyName: example-com-secret
tsigAlgorithm: HMACSHA512
tsigSecretSecretRef:
name: tsig-secret
key: tsig-secret-key

对于此示例配置,我们需要以下两个命令。第一个命令在您的 named 服务器上生成密钥。请注意 example-com-secret 同时出现在上面的 tsigKeyName 和后面的 dnssec-keygen 命令中。

$ dnssec-keygen -r /dev/urandom -a HMAC-SHA512 -b 512 -n HOST example-com-secret

还要注意 tsigAlgorithm 在配置和 keygen 命令中都提供了。它们列在 https://github.com/miekg/dns/blob/v1.0.12/tsig.go#L18-L23 中。

您需要在 Kubernetes 方面进行的第二项配置是创建一个密钥。从上面生成的 <key>.private 文件中提取密钥字符串,在下面的占位符中使用该密钥。

$ kubectl -n cert-manager create secret generic tsig-secret --from-literal=tsig-secret-key=<somesecret>

请注意 tsig-secrettsig-secret-key 与上面 tsigSecretSecretRef 中的配置相匹配。

速率限制

rfc2136 提供者将在您域的 SOA RR 中的 *所有* 域名服务器都返回相同的结果之前,才会联系 Let's Encrypt 完成挑战过程。这是因为挑战服务器会联系一个非权威 DNS 服务器,该服务器执行递归查询(查询它本地没有维护的记录)。如果 SOA 中的服务器不包含正确的值,那么非权威服务器也可能包含错误的信息,从而导致请求违反速率限制,最终导致进程被锁定。

此过程旨在保护用户免受服务器配置错误的影响,从而避免服务器配置修复后仍然存在的更隐蔽的锁定。

如其他地方所述,在使用生产服务器之前,使用 ACME 暂存服务器完全调试配置是谨慎的做法。暂存服务器的速率限制不太严格,但它们颁发的证书未用浏览器信任的根证书进行签名。

下一步是什么?

到目前为止,此配置实际上不会执行任何操作。您仍然需要按照 此处 的说明请求证书。请求证书后,提供者将开始处理请求。

故障排除

  • 请确保您已使用 nsupdate 完全测试了 DNS 服务器更新。理想情况下,这应该从与 rfc2136 提供程序相同命名空间的 pod 中执行,以确保没有防火墙问题。
  • cert-manager pod 的日志是您的好帮手。通过在容器启动时添加 --v=5 参数,可以生成额外的日志。
  • TSIG 密钥使用 base64 编码,但 Kubernetes API 服务器也期望密钥字面量在存储之前被解码。在某些情况下,密钥需要双重编码。(如果您已使用 nsupdate 测试过,那么很容易发现何时遇到了这种情况。)
  • 请注意您正在操作的区域的刷新时间。对于流量较低的区域,将刷新时间缩短至大约五分钟,以便获得初始证书,这不会造成重大影响。一旦该流程正常运行,cert-manager 的优势在于,即使续订由于刷新时间而需要数小时,它也是自动化的!
  • 与通常使用 REST API 修改 DNS RR 的其他提供程序相比,该提供程序可能需要稍长时间。您可以使用 watch kubectl certificate yourcert 来查看正在发生的事情。该过程总共需要五分钟并不罕见。