Caddy Cloudflare DNS-01:获取通配符 TLS 证书

为什么用 DNS-01,不用 HTTP-01

Let’s Encrypt 常见的证书质询方式有两种:

方式 原理 适用场景 局限
HTTP-01 在 80 端口提供指定文件 单域名、公网可达 不能签发通配符证书
DNS-01 在 DNS TXT 记录写入质询令牌 通配符证书、内网服务 需要 DNS 服务商 API

如果服务跑在内网,只有部分端口暴露,或者你需要 *.example.com 这样的通配符证书,就得用 DNS-01。

Caddy 默认用 HTTP-01。要改成 DNS-01,你需要安装 caddy-dns/cloudflare 插件(参考上一篇文章的 xcaddy 构建方法),然后在全局配置里指定 acme_dns

配置 DNS-01

{
    acme_dns cloudflare <API_TOKEN>
}

就这么一行。Caddy 启动时会调用 Cloudflare API 创建 _acme-challenge.example.com 的 TXT 记录。Let’s Encrypt 验证通过后,它会自动删掉这条记录,不用手动处理。

证书续期也是自动的。Caddy 会在后台检测证书过期时间,到期前再跑一遍同样的流程。

Cloudflare API Token 权限

这里不要用 Account API Key(全局密钥)。改用有限权限的 API Token:

  1. 登录 Cloudflare Dashboard → My Profile → API Tokens
  2. 点击 Create Token → 选择 Edit zone DNS 模板
  3. 权限设置为:
    • Zone → DNS → Edit
    • Zone → Zone → Read
  4. Zone Resources 选择你的域名(如 example.com
  5. TTL 设为永不或按需设置

这样即使 Token 泄露,攻击者也只能改你指定域名的 DNS 记录,不能做别的操作。

全局 Caddyfile 配置

{
    acme_dns cloudflare xxx
    servers {
        trusted_proxies cloudflare {
            interval 12h
            timeout 15s
        }
    }
}

Cloudflare 信任代理

trusted_proxies cloudflare {
    interval 12h
    timeout 15s
}

当 Caddy 跑在 Cloudflare CDN 后面时,所有请求的真实源 IP 都会被 Cloudflare 的代理 IP 覆盖。Caddy 得知道哪些 IP 是可信代理,才能正确提取 X-Forwarded-For 头里的真实客户端 IP。

caddy-cloudflare-ip 插件(自定义构建里已经包含)会自动获取 Cloudflare 的 IP 范围列表,并定期更新,每隔 12 小时检查一次。如果 Cloudflare 增加了新的回源 IP,配置也会自动生效,不用手动更新。

timeout 15s 指定 IP 范围获取的超时时间。

验证证书

部署完成后,用 OpenSSL 验证:

openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -text | grep -A1 "Subject Alternative Name"

应该看到类似输出:

X509v3 Subject Alternative Name:
    DNS:*.example.com, DNS:example.com

参考链接