# 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

```caddyfile
{
    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 配置

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

### Cloudflare 信任代理

```caddyfile
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 验证：

```bash
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
```

## 参考链接

- [caddy-dns/cloudflare](https://github.com/caddy-dns/cloudflare)
- [Caddy Global Options - ACME](https://caddyserver.com/docs/caddyfile/options#acme)
- [Cloudflare API Token 文档](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)
- [xcaddy 构建自定义 Caddy](/posts/custom-caddy-build/)


---

> 作者: Nite  
> URL: https://www.nite07.com/zh-cn/posts/caddy-cloudflare-dns-challenge/  

