记一次由于 GitHub Pages 启用强制 HTTPS 访问引发的证书更新事故

阿里云推广 (opens new window)

# 前言

近期在准备将自己的一个玩具项目 Code: Certs (opens new window) 打磨打磨开放出来给大家用一用, 于是搭建了一个简单的项目介绍网站, 将其托管在了 GitHub Pages (opens new window) 上, 并分配了自定义域名 https://code-certs.dengchao.fun (opens new window) 进行访问. 谁知后续 SSL 证书更新时遇到了 Verify error:CAA record for XXX prevents issuance 错误无法生成证书的问题.

Code: Certs 是一项适用于个人与小型团队的 HTTPS 证书免运维服务.

# 正文

# 启用 GitHub Pages 强制 HTTPS 访问功能

为了避免网站内容被劫持, Code: Certs (opens new window) 的项目介绍网站一开始就打算启用强制 HTTPS 访问. 正好 GitHub Pages 也支持启用强制 HTTPS 访问, 于是配置好自定义域名后便开启了此项功能. GitHub Pages 也支持启用强制 HTTPs 访问 此时, 网站已经能够顺利地将 HTTP 流量重定向到 HTTPS 了, 一切看起来都那么地自然与美好🌞.

# 更新 SSL 证书报错

随后不久, 我的其他网站和应用使用的 HTTPS 证书也即将到期了, 于是我打算用这个项目来完成自身 HTTPS 证书的更新. 然而 *.dengchao.fun 这个通配符却一直没法申请到 Let's Encrypt (opens new window) 颁发的新证书, 并不断提示 Verify error:CAA record for XXX prevents issuance 错误.

错误信息很直白, 就是 CAA 记录导致 CA 机构 Let's Encrypt 无法为指定的通配符域名颁发新证书. 由于本就打算一直使(白)用(嫖) Let's Encrypt 来签发证书, 早早的就给裸域名 dengchao.fun 添加的了值为 0 issuewild "letsencrypt.org" 的 CAA 记录.

反复尝试申请这个通配符域名的证书失败, 并且对比其他启用了相同 CAA 记录的域名后, 确定不是 CA 机构或者网络故障导致的问题, 又回想起前一段时间刚部署到 GitHub Pages 上的 Code: Certs (opens new window) 也开启了强制 HTTPS 访问, 于是开始猜测是 GitHub Pages 引发了此次异常 🤔.

# 调查原因

由于是 CAA 记录引发的异常, 因此开始对比分配给 Code: Certs (opens new window) 服务的域名 code-certs.dengchao.fun 与裸域名 dengchao.fun 的 CAA 记录, 结果发现 code-certs.dengchao.fun 的 CAA 记录不是 0 issuewild "letsencrypt.org" 😮:

# dig code-certs.dengchao.fun CAA
;; Warning: Message parser reports malformed message packet.

; <<>> DiG 9.16.1-Ubuntu <<>> code-certs.dengchao.fun CAA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64915
;; flags: qr rd ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;code-certs.dengchao.fun.          IN      CAA

;; ANSWER SECTION:
code-certs.dengchao.fun.   0       IN      CAA     0 issue "letsencrypt.org"
code-certs.dengchao.fun.   0       IN      CAA     0 issue "digicert.com"
code-certs.dengchao.fun.   0       IN      CAA     0 issuewild "digicert.com"
.                          0       IN      OPT

;; Query time: 109 msec
;; SERVER: 172.28.0.1#53(172.28.0.1)
;; WHEN: Sun Feb 05 12:11:52 CST 2023
;; MSG SIZE  rcvd: 169

进一步查看 CAA 记录的文档后发现当域名是 CNAME 类型的记录时, CA 会优先解析 CNAME 的值的 CAA 记录, 而不是像 A 类型记录一样继续检查上一级域名: CAA and CNAME 也就是说当 CA 机构查询 code-certs.dengchao.fun 的 CAA 记录时, 会优先查看 code-certs.github.io 是否有 CAA 记录, 结果 github.io 刚好配置了 CAA, 并且允许 Let's Encrypt 颁发单域名证书以及允许 Digi Cert 颁发单域名与通配符证书.

# 尝试与 GitHub 沟通

发现问题出在 github.io 的 CAA 记录上后, 我立即尝试与 GitHub 进行沟通 (opens new window), 出于自身的安全政策与影响范围等方面的考虑, GitHub 并没有采纳修改 CAA 记录相关的意见, 但给出了一个可行的应对方案.

# 应对方案

经过探索以及与 GitHub 的沟通, 我得出了如下几个可行的应对方案:

  1. 继续将网站托管在 GitHub Pages 上, 并继续使用 Let's Encrypt 来颁发通配符证书, 但将自定义域名的类型由 CNAME 类型变更为 A 类型 (opens new window), 以避免 CA 机构查询 CAA 记录时获取到 github.io 的 CAA 记录. 虽然 GitHub Pages 文档中关于自定义域名方面的文档 (opens new window) 提到用户需要使用 CNAME 类型来解析自定义域名到 <repo>.github.io 来启用自定义域名功能, 但实际上将自定义域名设置为 A 类型, 并解析到任意 <repo>.github.io 对应的 ip 上也能启用自定义域名功能.
  2. 继续将网站托管在 GitHub Pages 上, 但使用 Digi Cert 来颁发通配符证书. 由于 Digi Cert 不提供免费证书, 因此暂不考虑.
  3. 将网站迁出 GitHub Pages, 并继续使用 Let's Encrypt 来颁发通配符证书. 毕竟网站是你自己的, 没人要求你一定要托管在 GitHub Pages 上.

# 相关内容

# 推广

欢迎大家尝试使用 Code: Certs | https://code-certs.dengchao.fun (opens new window) 来申请免费的 HTTPS 证书, Code: Certs (opens new window) 还支持自动部署到部分公有云的产品上, 降低 HTTPS 证书运维工作量. 大家遇到什么使用问题或者有任何建议都可以私信我, 或者提交到 https://github.com/code-certs/code-certs/issues (opens new window) 也行.

欢迎大家领取 阿里云优惠券 (opens new window), 新购续费更优惠, 详询 钉钉 (opens new window): 限量阿里云优惠券 (opens new window)