这几天 Let's encrypt 的 Bot 连着给我发了两封信,说几个网站的的 TLS 证书一直没有续签。尽管这些网站都在 Cloudflare 的 CDN 代理下(开启 DNS Proxy),访问时已经套了 Cloudflare 的证书,但想着 Traefik 的成熟度应该不至于连默认配置的 Let's Encrypt 证书续签都搞不定,多半是有啥原因,于是找了一下。
先去翻 Traefik 的论坛,大家说翻一下 log,于是 docker logs xxx
,得到:
time="2024-03-20T06:19:50Z" level=error msg="Error renewing certificate from LE: {life2.wellwellsleep.com [tech.wellwellsleep.com]}" error="error: one or more domains had a problem:\n[life2.wellwellsleep.com] acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: Cannot negotiate ALPN protocol \"acme-tls/1\" for tls-alpn-01 challenge\n" providerName=mytlschallenge.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"
看来是 tls-alpn-01 的挑战没成功,导致续签失败。
到 Let's Encrypt 的官方文档 里看看 tls-alpn-01 是啥。不同于正常签发证书的 dns-01 认证,tls-alpn-01 是一个纯粹的协议认证,受基础设施的限制和干扰较小。
https://community.letsencrypt.org/t/cannot-negotiate-alpn-protocol/111996 在 Let's encrypt 的论坛有人遇到了同样的问题,并获得了解答。
You can’t use TLS-ALPN (lego's --tls option) when your domain is going through Cloudflare’s proxy. Cloudflare doesn’t allow non-HTTP ALPNs to pass through its CDN.
I notice that you’ve now disabled the Cloudflare proxy on your domain, since creating your post.
If you try again, I suspect it should now work.
一句话结论就是:在使用 tlschallenge
申请或续签证书的时候,证书机构需要访问到本机的 443 端口。然而 Cloudflare 的代理没有将该请求转发到目标主机,因此造成续签失败。
解决起来也很简单:
- 关闭 Cloudflare 代理
- 重新续签证书
在重新续签证书这步,如果不想「不安全的网站」被挂一天(一天自动续签一次),就需要手动续签。
https://github.com/traefik/traefik/issues/3652#issuecomment-593943264 这位老哥给了最简单的方法:
- 删掉 acme.json 的证书配置文件(Traefik 内持久化到了磁盘上
/var/lib/docker/volumes/traefik_data/_data/acme.json
) - 重启 traefik