# DNS-01 验证方式

## 使用 DNS-01 方式申请证书，有两种方法:
- **Certbot + DNS 插件**：Certbot 提供了多种 DNS 插件（如 Cloudflare、Route53 等），可以自动完成 DNS 记录的添加和删除。
- **Certbot + 手动 DNS**：你可以选择手动添加 DNS 记录，适合不支持自动化的 DNS 提供商。

##### DNS-01 验证方式的优势：
- **适用于任何环境**：不依赖于 HTTP 服务，适合内网服务器、CDN 后端等。
- **支持通配符证书**：可以申请 *.example.com 的通配符证书，适合多子域名场景。
- **更安全**：不需要暴露 HTTP 服务，减少攻击面。

##### DNS-01 验证方式的缺点：
- **配置复杂**：需要正确配置 DNS 记录，可能需要等待 DNS 生效。
- **不适合频繁变更**：DNS 记录的修改可能需要较长时间生效，不适合频繁申请和续期。

总的来说，DNS-01 验证方式适合需要通配符证书、没有公共 HTTP 服务或需要更高安全性的场景。选择适合的验证方式，可以让你的证书申请和管理更加顺利。

### 自动化 DNS-01 (推荐)

如果你用的是 [Cloudflare](https://www.cloudflare.com/) 或 [AWS Route53](https://aws.amazon.com/route53/)，Certbot 提供了官方插件，可以自动完成 DNS 记录的添加和删除，极大简化了流程。

**以 Cloudflare 为例**

{{< callout context="tip" title="Tip" icon="outline/rocket" >}}
在配置 Cloudflare API Tokens 之前,你需要了解,配置好 权限 和 资源 后, 请将Debian的公网的IP地址添加到 Cloudflare API页面中 `客户端IP` 地址白名单 中, 否则会在Certbot 申请证书时遇到 `403 Forbidden` 错误。
{{< /callout >}}

{{< steps >}}
{{< step >}}

配置 [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens)
- 选择 "Create Custom Token"
- 权限选择 "Zone:DNS:Edit"
- 资源选择 "Include:All zones"
- 创建后复制 API Token
- 记得将你的公网 IP 地址添加到 Cloudflare API 的 `客户端IP` 白名单中，以避免申请证书时遇到 `403 Forbidden` 错误。

{{< /step >}}
{{< step >}}

在Debian 上安装 Cloudflare 插件：

```bash
apt update && apt install python3-certbot-dns-cloudflare
```

{{< /step >}}
{{< step >}}

在Debian上创建一个 Cloudflare API Token 的凭据文件：

```bash
/etc/letsencrypt/cloudflare.ini
```

编辑文件，添加以下内容（将 `API_Token` 替换为你的实际 API Token）：

```ini
dns_cloudflare_api_token = API_Token
```

设置权限为只读，并且仅限于 DNS 编辑：

```bash
chmod 600 /etc/letsencrypt/cloudflare.ini
```
{{< /step >}}
{{< step>}}

申请证书：
{{< tabs "install debian certbot advantages" >}}
{{< tab "多域名" >}}

**一个证书包含多个域名（SAN 证书）**

__假设我想申请一个包含多个域名的证书, 证书包含 `www.eternal.foo`、`u.eternal.foo`、 `j.eternal.foo` 三个域名。并且将证书存储在 `/etc/letsencrypt/live/www.eternal.foo/` 目录下。__

```bash
certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  --dns-cloudflare-propagation-seconds 60 \
  -d www.eternal.foo \
  -d j.eternal.foo \
  -d u.eternal.foo
```

**关键点解释**

- `-d` 参数可以重复使用，每个 `-d` 后面跟一个域名，表示这个证书包含这些域名。
- 最终生成的证书会包含多个 SAN（Subject Alternative Name），即 `www.eternal.foo`、`u.eternal.foo` 和 `j.eternal.foo`。
- 每个 `-d` 都是证书的一个域名
- `--dns-cloudflare-propagation-seconds 60` 参数告诉 Certbot 在添加 DNS 记录后等待 60 秒，以确保 DNS 记录已经传播并生效，避免验证失败。

**证书位置（默认）**

生成后：

```
/etc/letsencrypt/live/www.eternal.foo/
```

包含：
`fullchain.pem`
`privkey.pem`

{{< /tab >}}
{{< tab "单域名" >}}

**每个域名单独申请一个证书**

如果你不想使用 SAN 证书，可以为每个域名单独申请一个证书：

```bash
certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d www.eternal.foo
```

{{< /tab >}}
{{< /tabs >}}
{{< /step>}}
{{< /steps >}}


{{< callout context="caution" title="Caution" icon="outline/alert-triangle" >}}
Certbot 默认用第一个域名作为目录名，所以即使证书包含多个域名，目录名也只会是第一个(从上往下数) `-d` 后面的域名。这不会影响证书的使用，但需要注意路径。
{{< /callout >}}


### 手动 DNS-01 申请（基础理解）

适合学习流程，不适合生产环境，因为需要手动添加 DNS 记录，比较麻烦。


```bash
certbot certonly \
  --manual \
  --preferred-challenges dns \
  -d example.com
```

执行后会提示：

```bash
Please create a TXT record under:
_acme-challenge.example.com

with the following value:
xxxxxx
```

**你需要：**

- 登录 DNS 服务商后台
- 添加 TXT 记录
- 等待生效
- 回车继续验证