如何使用 DuckDNS 进行多个 letsencrypt DNS 挑战(普通 + 通配符证书)

如何使用 DuckDNS 进行多个 letsencrypt DNS 挑战(普通 + 通配符证书)

工具

让我们加密是业余爱好者级别的几乎所有 HTTPS SSL/TLS 证书的来源,使用通过 HTTP 或 DNS 提供的挑战提供证书的自动颁发和更新功能。

具体来说,网站必须通过 DNS 质询才能获得 形式的域名的通配符证书,方法是将相关域名(或该域名的 ,Letsencrypt 会尊重该域名的 )的记录*.example.org设置为特定值。和 的控制均通过检查处的记录进行验证。TXTCNAMEexample.org.*.example.org.TXT_acme-challenge.example.org.

Letsencrypt 证书的自动续订通常由Certbot

鸭子DNS,虽然不是那么普遍,但却是一个流行的免费动态 DNS 提供商。帐户可以注册表单的域example.duckdns.org.并通过简单的 HTTP API更新其A/记录。通常,它与传统 DNS 提供商一起使用,通过指向(例如) at 。AAAAwww.example.org.CNAMEexample.duckdns.org.

此外,相同的 API 还允许用户设置或清除TXT其域的记录,特别是为了与 letsencrypt 互操作。(为 设置的所有A/ AAAA/TXT记录example.duckdns.org.都镜像到*.example.duckdns.org.。)

目标

目标是使用合理标准的 Letsencrypt/Certbot 设置来通过 DuckDNS API 传递 DNS 挑战。

具体来说,我们希望为example.org和都提供证书*.example.org,其中我们控制example.duckdns.org.并且普通 DNS 提供商提供服务*.example.org. CNAME example.duckdns.org.

如果我们有多个前端域名都指向同一个后端网络服务器,我们甚至可能希望处理、、、、所有四个example.org域名的*.example.org续订example.com*.example.com

简单的解决方案

要使用 DuckDNS API,请按照其规格,我们可以把这一行放在一个简单的 shell 脚本中(在重命名相应的环境变量,并对 DuckDNS 域和身份验证令牌进行硬编码)

V1='example.duckdns.org'
V2='our-duckdns-auth-token'
V3="$CERTBOT_VALIDATION"
curl -s -S "https://www.duckdns.org/update?domains=${V1}&token=${V2}&txt=${V3}"

并要求 Certbot 使用以下命令运行它

certbot certonly -v --manual --manual-auth-hook my-script.sh -d '*.example.org.'

此后将自动处理续订。

问题

DuckDNSTXT每次只为一个域名保留一条记录,任何附加记录都会覆盖旧记录。至少在使用默认 Certbot 时,Letsencrypt 会要求请求证书的客户端一次性通过所有挑战。

也就是说,虽然上述简单的解决方案适用于*.example.org.,但如果我们将其扩展到

-d 'example.org' -d '*.example.org'

然后 Letsencrypt 将运行两个挑战,每个域一个,并期望TXT同时存在两个不同的记录_acme-challenge.example.org.。Certbot 将运行两次挂钩脚本,TXT添加的第二条记录将覆盖第一条记录,只留下一条。因此,至少有一次挑战将失败,无法颁发完整证书。在问题的四域扩展版本中,将有一次成功和三次失败。

由于 Letsencrypt 无处不在,DuckDNS 也相当流行,因此有零散的参考资料 [1][2][3] 在互联网上对此问题进行了讨论(包括非公开的 DuckDNS google 群组中的更多内容),但我在任何 Stack exchange 网站上都找不到任何相关信息。

答案1

下面整理了我发现的一些解决方案。

混合挑战

DNS 质询仅对通配符证书是绝对必要的。我们可以要求 Certbot 使用 HTTP 质询(如果可用)--preferred-challenges

certbot certonly -v --manual          \
 --preferred-challenges 'http,dns'    \
 --manual-auth-hook my-script.sh      \
 -d 'example.org.' -d '*.example.org.';

这需要一个--manual-auth-hook可以设置任一挑战的脚本。再次咨询文档,其形式大致为

if [ -z "$CERTBOT_TOKEN" ]; then
    # DNS auth
    # See original question
else
    # HTTP auth
    # echo "$CERTBOT_VALIDATION" > "/the/correct/dir/$CERTBOT_TOKEN"
fi;

加上相应的清理逻辑。这样就可以example.org顺利*.example.org地并行验证。这也是我选择的方法,因为它最干净。

为了比较,

  • 这基本上是涉及的所有工具的正确使用。
  • 设置稍微复杂一些。
  • 它不处理问题中的(更一般的)四域.org&情况,因为两个不同的通配符挑战仍然会发生冲突。.com

example.org.和域名example.com.可以指向单独的 DuckDNS 域名,例如example0.duckdns.org.example1.duckdns.org.,但免费 DuckDNS 帐户一次最多只能使用五个域名。只要只有一个通配符证书,任意域名组合(例如 、*.example.orgexample.orgexample.com)都www.example.com可以正常工作。

暴力破解串行挑战

Certbot 将始终尝试并行运行所有挑战,但只要一个域名的挑战成功,通过该挑战的 Certbot 客户端将继续被授权在三十天内兑换该域名的证书。

也就是说,虽然简单的解决方案

certbot certonly -v --manual --manual-auth-hook my-script.sh \
 -d 'example.org' -d '*.example.org' ;

第一次执行会失败,但第二次执行会成功,因为的控制example.org已经过验证并且*.example.org不会遇到冲突。

续订应该以类似的方式进行。典型的 Certbot 安装将每天检查即将到期的证书,并尝试续订剩余时间少于 30 天(总共 90 天)的证书。第一次尝试续订此证书将失败,这意味着 Certbot 将在一天后再次尝试,届时它将成功。(我还没有找到一种无需等待 60 天即可正确测试此证书的方法。)

为了比较,

  • 虽然这基本上无害,但这在某种程度上滥用了 Letsencrypt API。我不确定速率限制是否值得关注。
  • 设置非常简单,但是每次更新时都会产生大量虚假错误消息。
  • 除了速率限制之外,这还可以处理大量碰撞挑战。

不同的客户端,上游修复

从我在(非公开的)DuckDNS Google 群组中看到的情况来看,DuckDNS 管理员最近才被告知存在此问题,并正在考虑将限制增加到TXT一次两个记录。这将完美地涵盖最常见的情况。我不确定他们是否想提高限制,因为整体服务必须尽可能简单(且操作成本低廉)。

据我所知,Certbot 不必并行运行所有挑战(尽管这可能是使用 ACME 协议更“自然”的方式)。甚至似乎还存在其他可以连续运行挑战的客户端,但截至撰写本文时,我还没有仔细研究过任何客户端。这应该完全是客户端实现的问题,因为 Letsencrypt 授权缓存行为无论如何都存在。

当然,理想的解决方案是 Certbot 具有连续挑战功能。我不知道为什么这会很难实现,除非它只在像这样的某些狭隘情况下有用。

相关内容