折腾了一天半:GitHub Pages 自定义域名的 HTTPS 到底是谁给的
现象
给博客绑了自己的域名 nagu.cc。A 记录按官方文档老老实实指向 GitHub Pages 的四条 IP,www 也 CNAME 到了 na57.github.io,站点能打开,但仓库的 Settings → Pages 一直挂着一行红字:
DNS check unsuccessful — Domain’s DNS record could not be retrieved (InvalidDNSError)
点 “Check again”,还是这句。证书一直没签发,浏览器访问提示”不安全”。
排查:DNS 从头到尾都是对的
我把能怀疑的地方全查了一遍:
- 本地、
8.8.8.8、9.9.9.9(Quad9,会做 DNSSEC 校验)、两个 DoH 解析器、两个权威 NS —— 六路查询结果完全一致,都是那四条 GitHub IP; www的 CNAME 是na57.github.io.,没有被域名商拼成na57.github.io.nagu.cc.那种坑;- 没有 CAA 记录,没开 DNSSEC,没有通配符记录;
- 名下所有开了 Pages 的仓库都查了,没有别人占用这个域名;
- whois 状态 ACTIVE,没有 hold。
结论很清楚:DNS 没有任何问题。
我试过的,都没用
按网上能找到的办法,挨个试:
- 删掉 apex 的 AAAA 记录,只留 A(官方文档里 AAAA 本来就是可选项)—— 没用;
- 反复点 Check again —— 没用;
- 摘掉自定义域名再重新挂上 —— 没用(社区说中间要隔 5~10 分钟让缓存清掉,当时只隔了 40 秒,等于白做);
- 提工单 —— 秒关。回信说该账号可用的支持资源只有 Community、Docs、Skills 三样自助资源。Free 账号没有人工工单支持,这条路是死的;
- 把 DNS 从 GoDaddy 整个迁到 Cloudflare(灰云,纯做解析)—— 记录一模一样,报错一模一样。换 DNS 服务商也没用。
期间还有个很讽刺的插曲:GitHub 官方的 “Run a Pages domain health check” 诊断代理跑完告诉我 “Everything looks good on nagu.cc!”,而它自家的 Settings 页面坚持说 DNS 检查失败。两个都是 GitHub,结论相反。
转折:开了橙色云,证书立刻就有了
最后我把 Cloudflare 的代理打开(橙色云),再访问就是绿锁了。抓下来的证书长这样:
Subject: CN = nagu.cc
Issuer: C = US, O = Let's Encrypt, CN = YE1
SAN: DNS:*.nagu.cc, DNS:nagu.cc
有效期: 至 2027-01-05
注意 SAN 那一行里有 *.nagu.cc。这就是破案的关键:
- GitHub Pages 给自定义域签的证书,只覆盖你配置的那个确切主机名(nagu.cc),不会有通配符;
- Cloudflare 的 Universal SSL 固定是「apex + 通配」成对出现。
所以这张证书是 Cloudflare 签的,不是 GitHub 的。真实情况是:GitHub 的证书从头到尾就没签发过。HTTPS 能用,是因为 Cloudflare 挡在前面,替我签了证、做了 TLS 终结。
三条旁证也对得上:Pages API 里 https_available 至今仍是 null;na57.github.io 的 301 目标仍是 http://nagu.cc(它要是真有证书,这里会跳 https);官方 health check 和 Settings 页面的矛盾至今没消。
最后的方案,和一个必须提醒的坑
域名继续放在 Cloudflare,开橙色云代理:
- apex 的 A / AAAA 和
www的 CNAME 全部 Proxied; - SSL/TLS 加密模式设 Full;
- 打开 Always Use HTTPS。
⚠️ 千万别把加密模式切成 Full (strict)。 源站 GitHub 现在手上只有 *.github.io 的通用证书,跟 nagu.cc 主机名不匹配,strict 模式下 Cloudflare 校验源站证书会失败,直接给你 526。只有等 GitHub 真给你签了域名证书,strict 才成立 —— 而在代理开着的情况下,它永远不会签。
必须接受的副作用: GitHub 的 DNS 检查会永久显示失败,Enforce HTTPS 也永远勾不上。因为开了代理之后,GitHub 查 DNS 看到的是 Cloudflare 的 IP 而不是它自己的,这个检查永远不可能通过。这是架构决定的,不是故障,访客侧一切正常。
换个角度看还有个好处:证书续期从此由 Cloudflare 负责,不再依赖 GitHub 那条异步流水线的心情。
给后来人的几条经验
一、别信 Settings 的报错文案,也别信 API。 我的 HTTPS 早就通了,Pages API 里 https_available 还是 null。直接看证书最准:
curl -sS -o /dev/null -w '%{certs}' https://你的域名/ | grep -E 'Subject:|DNS:'
二、怎么判断证书是谁签的: SAN 里有 *.你的域名 就是 Cloudflare 的;只有确切主机名才是 GitHub 的。这一眼能省掉一整天的瞎猜。
三、想要 GitHub 原生发证书,就别开代理(用灰云),并且要有耐心 —— 它那条流水线是异步的,慢,还可能一直卡住。
四、等不及就用 Cloudflare 橙色云,SSL 模式记得是 Full,不是 strict。
五、Free 账号别浪费时间提工单,会被自动关闭。
六、官方那个 health check 值得跑。 它给的是 GitHub 自己看到的域名状态,虽然这次它和 Settings 页结论相反,但正是这种自相矛盾,反证了问题不在 DNS 上。
七、别把时间上的先后当成因果关系。 这次的坑在于:开代理和证书出现几乎同时发生,很容易顺理成章地以为”终于等到了,GitHub 只是慢”。但实际上是 Cloudflare 在发证书。判断归属要看证据(SAN),不要靠感觉。