Let's Encrypt 证书续订(突然)失败

几个月前(具体时间不清楚,但至少有几个月了),我的 Discourse 论坛上的 Let’s Encrypt 续订开始失败,尽管之前已经正常运行了很多年。几天前我注意到这个问题时,证书已于 2021 年 8 月过期。在尝试手动续订和重启 nginx 后,我发现证书的过期日期被推迟到几天前。显然,这仍然不是一个当前证书。在 discourse 容器内手动运行 acme.sh 强制续订时,我遇到了这个错误(其中 [site] 当然是我的网站地址):

[site]:Verify error:Fetching http://[site]/.well-known/acme-challenge/[long alpha challenge string]: Error getting validation data

我应该注意的是,该网站要求所有用户访问都需要登录,但这在过去几年中对 SSL 证书续订一直不是问题。

有什么想法吗?非常感谢!

更新:使用 wget 测试验证会返回 404。但是,我不知道这些数据是如何在容器中的 nginx 中为 Discourse 配置的,以及它与代理在容器外部的 nginx 有何关系。

2 个赞

如果这是几个月前的事情,这与以下内容有关吗?

2 个赞

您好。这不应该有关联,因为该问题会导致浏览器因不同的错误而拒绝证书,而不是像我遇到的那样出现过期错误。看起来 Let’s Encrypt 突然无法与 Discourse 进行身份验证以提供新证书。谢谢。

2 个赞

如果第一次到期是在八月份,那就不是了。它应该在那之后续期。

4 个赞

对于一个在六月之后未更新的应用,可能存在此问题:Letsencrypt certificate failure to renew - #11 by pfaffman

不确定这是否是您要找的,但:discourse_docker/templates/web.letsencrypt.ssl.template.yml at main · discourse/discourse_docker · GitHub

2 个赞

您好。这些似乎不适用。我看到的是 404 错误,而不是那些其他错误,构建一直都在更新,而且 GitHub 上的那个模板确实是我安装中已安装的版本。谢谢!

3 个赞

您在使用 Cloudflare(橙色云)还是其他反向代理?

2 个赞

否。在 Ubuntu 18.04 上本地托管,使用默认的 Docker 安装。

3 个赞

在容器中手动运行 cron 作业进行证书续订时,失败情况始终相同。尝试获取:

http://[site]/.well-known/acme-challenge/[challenge-string]

因“获取验证数据时出错”而失败。

2 个赞

由于不熟悉该流程,它是否期望容器处于运行该脚本时并非如此的状态?例如,也许它期望另一个 cron 作业首先发生,该作业准备 nginx 以允许访问此类 URL。

您是否尝试过重建?(这将尝试在此过程中获取新证书。)

您提到它托管在本地。您是否能够使用域名从网络外部访问该实例?

2 个赞

您好,是的,多次重建。没有变化。我在许多非 Discourse 网站上使用 Let’s Encrypt,它们都能正常续订。是的,我可以从外部网站访问,并且我已使用 wget 测试过,结果是 404。问题是:在这种情况下,nginx html 树的确切位置在哪里,也就是包含(或应该包含).well-known 目录的部分?我一直找不到。谢谢。

2 个赞

我找不到 cron 作业,只有一个位于 /etc/runit/1.d/letsencrypt 的 runlevel 脚本。看起来该脚本会启动一个新实例的 nginx,其配置包括:

location ~ /.well-known {
  root /var/www/discourse/public;
  allow all;
}

我认为这意味着路径最终会是 /var/www/discourse/public/acme-challenge,尽管它可能在挑战之前被创建,然后在之后被删除。

如果你尝试手动运行的脚本是那个,你是否先停止了 nginx?脚本尝试启动的实例会尝试监听端口 80,所以我怀疑如果 nginx 已经为 Discourse 运行,那会失败。

2 个赞

我认为我可能看到了问题所在。但我不知道如何解决它。看起来所有对https端口80上的论坛的访问尝试(正如预期的那样)都被重定向到了https端口443。对。但这导致Let’s Encrypt在尝试续订验证时失败,因为当前证书已过期。我可以用wget看到重定向。那么问题来了,我该如何暂时禁用重定向,以便Let’s Encrypt能够验证并为我获取新的未过期证书?一个可能的额外复杂情况是,重定向是301永久重定向。谢谢。

2 个赞

此重定向位于 /etc/nginx/conf.d/discourse.conf 中,在 nginx 停止然后使用我之前帖子中提到的配置启动时将不会使用。

恐怕我对自动升级的工作方式不太熟悉,因此不确定在容器运行时续订的合适方法是什么。理论上,只需停止并启动容器就应该可以续订,但既然您说重建没有做到这一点,那可能也不会。

acme.sh 有 --renew-all 等选项,但不确定它需要哪些其他选项才能在此处正确执行。以下内容可能就是您所需要的,但我无法确定。

LE_WORKING_DIR="/shared/letsencrypt" /root/acme.sh/acme.sh --renew-all
2 个赞

这确实允许 Let’s Encrypt 在没有重定向的情况下进行访问,但它正在查找的文件似乎不存在,因此最终验证仍然失败。

2 个赞

我遇到了同样的问题。有人找到解决此问题的明确步骤吗?

2 个赞

我正在尝试使用此命令成功获取证书。看起来 curl 确实检索到了验证令牌,但 acme.sh 每次仍然声明验证失败!所以仍然无法访问。

“/shared/letsencrypt”/acme.sh --renew-all --force --insecure --home “/shared/letsencrypt” --debug

2 个赞

您好 @L30110 :slightly_smiling_face:

我是 Let’s Encrypt 社区 的常客 griffin@JimPas 让我来查看这个帖子,我会在午餐回来后立即处理。

3 个赞

对于许多 ACME 客户端(例如 acme.sh),当 nginx 被指定为身份验证方法时,http-01 挑战 文件会根据 nginx 服务器配置中的异常/重定向创建一个特定目录,而不是直接创建在 webroot 目录的 .well-known/acme-challenge 目录结构中。通常,这种重定向仅在挑战验证期间临时存在,挑战文件本身也是如此。

因此:


这是一个明智的考虑。一个编写良好的续订脚本应该不需要停止 nginx。通常,nginx 用于提供挑战文件,然后使用类似 nginx -s reload 的命令在获取新证书后优雅地重新加载 Web 服务器/代理。


不。:wink:

根据 Challenge Types - Let's Encrypt

我们对 HTTP-01 挑战的实现遵循重定向,最多 10 次重定向。它只接受到“http:”或“https:”的重定向,并且只接受到端口 80 或 443 的重定向。它不接受到 IP 地址的重定向。当重定向到 HTTPS URL 时,它不会验证证书(因为此挑战旨在引导有效的证书,它可能会遇到自签名或过期的证书)。


通常,当我们遇到此类问题时,通常是以下原因之一:

  • 防火墙未允许流量通过到提供挑战文件的 Web 服务器/代理。
  • 路由器/代理映射/配置不正确,导致 Boulder(Let’s Encrypt CA 服务器)的挑战验证请求尝试从错误的 Web 服务器或目录检索文件。
  • 某种重写/重定向(例如 Apache 中的 .htaccess 文件)干扰了 Web 服务器/代理从正确位置提供挑战文件的能力。
  • 使用非标准端口,通常伴随不正确的映射。
  • 运行 ACME 客户端的容器将挑战文件创建在 Web 服务器/代理(例如 nginx)未提供它们的目录中。当涉及 Docker 时,这几乎总是问题所在。
2 个赞

您好。您列出的各种项目中有几项显然不适用于我的情况。不是防火墙问题——我可以使用 wget 或 curl 从以下所有位置手动访问令牌:1) Docker Discourse 应用程序内部,2) 从 Docker 容器外部的主机系统,以及 3) 一个相关的系统。

对于这些手动情况,假设指定了 --ignore 或 -k 以绕过 Discourse 自动重定向到 https 时的过期证书,我确实从预期的位置获取了令牌内容。

我没有更改 Discourse 在 Discourse Docker 容器内部或外部创建的任何 nginx 配置。我没有运行任何 nginx 副本,Apache 也仅在本地使用完全不同的端口。请注意,这一切已经正常运行了两年多,有定期的证书续订,并且没有其他应用程序更改——这是一个非常稳定的盒子。

没有不寻常的端口。

由于我可以手动获取令牌内容,因此我认为错误的位置不会有问题。除非……

我在测试时没有手动停止 nginx。我现在已经这样做了,但没有明显区别——acme.sh 仍然出现相同的错误(目前又是错误 56)。当从容器内部停止 nginx 时,我确实在主机上看到了一个 runsv nginx 实例,但它没有工作进程或缓存进程。当我重新启动容器内的 nginx 时,工作进程和缓存进程会与仍然存在的 runsv nginx 一起出现在主机上。容器内的 sv start/stop nginx 命令会按预期确认这些操作。

但上面提到的还有其他可能令人担忧的事情。而且我不明白为什么在事情已经正常工作了这么长时间后,这会突然成为一个问题。

由于 ISP 提供静态 IP 地址的复杂性,论坛的静态 IP 地址(从我的本地网络外部使用)无法由该机器用于连接到该机器自身的服务。我通常会使用 /etc/hosts 中的条目为这些名称提供本地网络 IP 地址。因此,当我使用同一台机器(容器内部或外部,它们都有针对论坛的 /etc/hosts 添加项)上的 curl 进行测试时,测试使用的是与外部站点通过 DNS 查询时使用的 IP 地址不同的(本地)IP 地址。这是否可能相关?谢谢。

2 个赞