xfyyzy

摘要

文章内容 在 Gentoo 上通过 Certbot 配合 Cloudflare DNS-01 验证获取通配符证书的完整配置指南,涵盖插件安装、API Token 创建、凭据配置、证书签发及自动续期。

通配符匹配规则

  • 通配符证书仅匹配单层子域名,不匹配裸域和多层子域
  • 如需同时覆盖裸域和子域,签发时需同时指定两者
  • 公共 CA 不支持多层通配符形式

多层子域策略 可通过添加额外的单层通配符解决,例如为 service 子域单独申请一个通配符。

关键注意事项

  • 凭据文件权限必须设为 600,否则 Certbot 将拒绝使用
  • 通配符证书只能通过 DNS-01 方式签发
  • Gentoo 特有:需处理测试分支关键字依赖问题

流程概览

安装 Certbot

添加 overlay

处理 ~amd64 依赖

创建 API Token

配置凭据文件

签发证书

配置自动续期

步骤 操作 关键文件/命令
1 安装 Certbot 及插件 emerge app-crypt/certbot-dns-cloudflare
2 创建 API Token Cloudflare Dashboard
3 配置凭据文件 /root/.secrets/certbot/cloudflare.ini
4 签发证书 certbot certonly --dns-cloudflare
5 自动续期 crontab + certbot renew

安装 Certbot 与 Cloudflare DNS 插件

安装 Certbot

同步 Portage 后安装 certbot:

emaint sync -a
emerge --ask app-crypt/certbot app-crypt/certbot-nginx

app-crypt/certbot-nginx 为可选组件,用于自动配置 Nginx(Apache 用户可安装 app-crypt/certbot-apache)。

添加 overlay 并安装插件

Cloudflare DNS 插件位于 certbot-dns-plugins overlay:

# 安装 overlay 管理工具
emerge --ask app-eselect/eselect-repository

# 启用并同步 overlay
eselect repository enable certbot-dns-plugins
emerge --sync certbot-dns-plugins

# 安装插件
emerge --ask app-crypt/certbot-dns-cloudflare

验证安装:

certbot plugins

输出应包含 dns-cloudflare authenticator。

处理 ~amd64 关键字依赖

安装 certbot-dns-cloudflare 时可能遇到以下错误:

!!! All ebuilds that could satisfy ">=dev-python/cloudflare-2.19.0[...]" have been masked.
!!! One of the following masked packages is required to complete your request:
- dev-python/cloudflare-2.19.4::certbot-dns-plugins (masked by: ~amd64 keyword)

这表示依赖包 dev-python/cloudflare 仅有测试分支(~amd64)版本,需要手动接受该关键字。

手动添加关键字

mkdir -p /etc/portage/package.accept_keywords

cat >> /etc/portage/package.accept_keywords/certbot-dns-plugins <<'EOF'
app-crypt/certbot-dns-cloudflare ~amd64
dev-python/cloudflare ~amd64
EOF

emerge --ask app-crypt/certbot-dns-cloudflare

若存在其他 ~amd64 依赖,按相同方式添加即可。

使用 autounmask(可选)

emerge -av app-crypt/certbot-dns-cloudflare --autounmask-write
etc-update  # 或 dispatch-conf
emerge --ask app-crypt/certbot-dns-cloudflare

创建 Cloudflare API Token

相比 Global API Key,API Token 支持细粒度权限控制,安全性更高。

创建步骤:

  • 登录 Cloudflare Dashboard
  • 进入 My ProfileAPI TokensCreate Token
  • 选择 "Edit zone DNS" 模板,或手动配置权限
  • 保存生成的 Token
配置项
Permissions Zone: DNS: Edit
Zone Resources 选择目标域名

Warning

Token 仅在创建时显示一次,请妥善保存。

配置凭据文件

创建凭据文件并设置权限:

mkdir -p /root/.secrets/certbot
chmod 700 /root/.secrets/certbot

cat >/root/.secrets/certbot/cloudflare.ini <<'EOF'
dns_cloudflare_api_token = YOUR_API_TOKEN
EOF

chmod 600 /root/.secrets/certbot/cloudflare.ini
对象 权限
凭据文件 600
上级目录 700

Caution

权限设置不当会导致 Certbot 拒绝使用该凭据。

签发证书

插件会自动通过 Cloudflare API 创建 _acme-challenge TXT 记录完成验证。

Let's EncryptCloudflare APICertbotLet's EncryptCloudflare APICertbot创建 _acme-challenge TXT 记录确认创建成功请求验证查询 TXT 记录返回记录值验证通过,签发证书删除 TXT 记录

单域名证书

certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
  -d example.com

根域名 + 通配符证书

certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
  -d example.com \
  -d '*.example.com'

DNS 传播较慢时可添加 --dns-cloudflare-propagation-seconds 60 延长等待时间。

证书存储位置:

/etc/letsencrypt/live/example.com/
├── fullchain.pem  # 证书链
└── privkey.pem    # 私钥

自动续期

测试续期

certbot renew --dry-run

配置 cron

Gentoo 需手动安装 cron 实现:

emerge --ask virtual/cron
rc-update add cronie default
/etc/init.d/cronie start

添加定时任务:

crontab -e
# 每天 0:15 和 12:15 检查续期
15 0,12 * * * certbot renew -q

续期后重载 Nginx:

15 0,12 * * * certbot renew -q --deploy-hook "systemctl reload nginx"

签发时使用的插件和参数会自动保存在 /etc/letsencrypt/renewal/*.conf,续期时无需重复指定。

通配符证书覆盖范围

匹配规则

*.example.com 仅匹配单层子域名:

不匹配

example.com

a.b.example.com

v1.api.example.com

匹配 *.example.com

www.example.com

api.example.com

blog.example.com

域名 匹配 *.example.com
www.example.com
api.example.com
example.com 否(裸域)
a.b.example.com 否(多层)

同时覆盖裸域和子域

-d example.com -d '*.example.com'

证书将包含两个 SAN 条目,可覆盖 example.com 及所有单层子域。

多层子域的证书策略

*.example.com 无法用于 a.b.example.com。TLS 握手阶段客户端会验证证书 SAN/CN 与域名的匹配关系,这发生在应用层之前,无法通过服务器配置绕过。

可覆盖域名

证书 SAN

*.example.com

*.service.example.com

www.example.com

api.example.com

a.service.example.com

b.service.example.com

中间层固定的情况

若子域结构为 *.service.example.com,可申请额外的通配符:

certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
  -d example.com \
  -d '*.example.com' \
  -d '*.service.example.com'

注意:这仍是多个单层通配符的组合,而非 *.*.example.com——公共 CA 不支持多层通配符。

中间层不固定的情况

若子域结构无规律(如 a.b.example.comx.y.example.com),需逐一列出:

-d a.b.example.com -d x.y.example.com -d foo.bar.example.com

或重新规划域名结构,统一中间层后使用通配符方案。

常见问题

问题 原因 解决方案
403 错误 Token 权限不足 确保 Token 具有 Zone: DNS: Edit 权限
权限警告 凭据文件权限不当 cloudflare.ini 设为 600,目录设为 700
凭据读取错误 多凭据冲突 移除环境变量、cloudflare.cfg 等其他凭据来源
通配符签发失败 验证方式错误 通配符仅支持 DNS-01,不支持 HTTP-01 和 TLS-ALPN-01
续期失败 配置文件损坏 重新运行 certbot certonly(指定相同 --cert-name

命令速查

# 安装
emaint sync -a
emerge --ask app-eselect/eselect-repository
eselect repository enable certbot-dns-plugins
emerge --sync certbot-dns-plugins

cat >> /etc/portage/package.accept_keywords/certbot-dns-plugins <<'EOF'
app-crypt/certbot-dns-cloudflare ~amd64
dev-python/cloudflare ~amd64
EOF

emerge --ask app-crypt/certbot app-crypt/certbot-dns-cloudflare

# 配置凭据
mkdir -p /root/.secrets/certbot
cat >/root/.secrets/certbot/cloudflare.ini <<'EOF'
dns_cloudflare_api_token = YOUR_API_TOKEN
EOF
chmod 600 /root/.secrets/certbot/cloudflare.ini

# 签发证书
certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
  -d example.com \
  -d '*.example.com'

# 测试续期
certbot renew --dry-run

# 配置自动续期
emerge --ask virtual/cron
rc-update add cronie default
/etc/init.d/cronie start
# crontab: 15 0,12 * * * certbot renew -q --deploy-hook "systemctl reload nginx"