Dockerized Nginx + Certbot + tls-sni 验证在续订时不起作用

Dockerized Nginx + Certbot + tls-sni 验证在续订时不起作用

我有一个使用 Docker 容器运行的现有服务:

  • nginx(nginx:1.13.5
  • node-api(节点容器)
  • node-website(节点容器)

我想为 api 和网站添加 SSL 证书。所以我使用certbot/certbotdocker 容器来执行此操作,没有任何问题。

我已经使用挑战生成了证书dns,并运行以下命令(从我的本地机器):

docker run --rm -it \
  --name certbot \
  -v $(pwd)/letsencrypt:/etc/letsencrypt \
  certbot/certbot \
    certonly --manual -d api.mydomain.com --preferred-challenges dns --renew-by-default --email xxx@xxxx --agree-tos --manual-public-ip-logging-ok

我被要求输入 TXT DNS 记录,_acme-challenge.api.mydomain.com我按照要求输入了,然后顺利生成了证书。

然后我更新了我的 Nginx 配置(/etc/nginx/nginx.conf/api.conf):

upstream api {
  server node-api:5000 max_fails=3;
}

map $http_upgrade $connection_upgrade {
  default       "upgrade";
  ""            "";
}

# Force HTTPS
server {
  listen 80;
  server_name api.domain.com;
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl http2;
  server_name       api.domain.com;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_certificate   /etc/nginx/certificates/api.domain.com/fullchain.pem;
  ssl_certificate_key /etc/nginx/certificates/api.domain.com/privkey.pem;
  ssl_trusted_certificate /etc/nginx/certificates/api.domain.com/chain.pem;

  access_log /var/log/nginx/api-domain.access.log main;
  error_log  /var/log/nginx/api-domain.error.log error;

  location / {
    proxy_pass         http://api;
    proxy_redirect     off;

    proxy_set_header   Connection $connection_upgrade;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

一切顺利,重启了我的服务器,现在可以完美运行 letsencrypt 证书!太棒了!


问题

现在开始测试更新证书...麻烦来了。首先,我只是尝试运行命令,renew --dry-run但没有成功。

尝试从 /etc/letsencrypt/renewal/api.mydomain.com.conf 更新证书 (api.mydomain.com) 时出现意外错误:手动插件不起作用;您现有的配置可能存在问题。错误为:PluginError('当以非交互方式使用手动插件时,必须使用 --manual-auth-hook 提供身份验证脚本。',)。跳过。

因此我尝试使用独立选项:

docker run --rm -it \
  --name certbot \
  -v $(pwd)/letsencrypt:/etc/letsencrypt \
  certbot/certbot \
    renew --dry-run --standalone --preferred-challenges dns

并收到此错误:

尝试从 /etc/letsencrypt/renewal/api.mydomain.com.conf 更新证书 (api.mydomain.com) 时出现意外错误:所选插件不支持任何首选挑战。跳过。

所以我推断我不能使用dns挑战来更新证书,这很公平。

让我们尝试一下tls-sniNginx 是否支持(我已验证,它已启用)

docker run --rm -it \
  --name certbot \
  -v $(pwd)/letsencrypt:/etc/letsencrypt \
  certbot/certbot \
    renew --dry-run --standalone --preferred-challenges tls-sni

现在我遇到了这个错误:

尝试从 /etc/letsencrypt/renewal/api.mydomain.com.conf 更新证书 (api.mydomain.com) 时出现意外错误:授权程序失败。api.mydomain.com (tls-sni-01):urn:acme:error:unauthorized :: 客户端缺乏足够的授权 :: tls-sni-01 质询的验证证书不正确。从 13.210.106.2:443 请求 e0fd03ddade6d902d5947028985253ba.63b177f317335bf9297f0bb963135fee.acme.invalid。收到 2 个证书,第一个证书名为“api.mydomain.com”。跳过。

我想知道是否需要在 Nginx 端启用某些特定功能,例如OCSPssl_stapling或者ssl_dhparam

我还注意到,如果我尝试在与获取证书的服务器不同的服务器上重新运行 certonly,则dns挑战值是不一样的。


所以我有两个问题:

  • 我可以tls-sni通过调整 nginx 配置轻松解决验证挑战吗?

  • 如果我在实际服务器(运行 nginx 容器的地方)上重新运行certonlychallenge dns,则使用新生成的记录更新 TXT 记录。我可以稍后使用certonly命令更新证书吗?TXT 记录值会随时间而变化吗?

提前致谢

答案1

ServerFault 上没有太多活动,因此答案如下:

https://github.com/certbot/certbot/issues/5252#issuecomment-346500852

答案2

谢谢 maxwell2022!根据您的回答,我的最终解决方案如下。在 CentOS 7 上测试。我手动创建了目录 /etc/letsencrypt/acme-challenge。

NGINX 服务器块

server {
    listen 80;
    server_name MY_DOMAIN;

    location /.well-known/acme-challenge/ {
        root /etc/letsencrypt/acme-challenge;
    }
}

创建证书

docker run -it --rm --name certbot -v /etc/letsencrypt:/etc/letsencrypt -v /var/lib/letsencrypt:/var/lib/letsencrypt certbot/certbot certonly --webroot -w /etc/letsencrypt/acme-challenge/ --domain MY_DOMAIN --agree-tos --email MY_EMAIL

更新证书

docker run -it --rm --name certbot -v /etc/letsencrypt:/etc/letsencrypt -v /var/lib/letsencrypt:/var/lib/letsencrypt certbot/certbot renew --webroot -w /etc/letsencrypt/acme-challenge/
docker kill --signal=HUP proxy

答案3

当问题首次出现时,这不是您的问题,但现在它会导致问题,所以我会提一下:

TLS-SNI 挑战正在逐步淘汰因为它们在许多常见托管平台下都不安全。如果您目前依赖以这种方式颁发的证书,则需要过渡到基于 HTTP 或 DNS 的挑战。

相关内容