No. 14: GitHub Pages 自定义域名被劫持与恢复记录
域名被篡改成赌博网站,一次完整的 GitHub Pages 域名劫持事件复盘——从发现、定位到恢复和预防。
2025/12/29
那天下班前随手打开博客,页面加载完我愣住了——一片赌场配色。
kakarrot.com 跳转到了一个叫 DADU128 Slot 的页面。再试一次,一样。我当时想的是:完了,域名没了。
冷静下来之后,发现事情没我想的那么糟,但也足够糟糕。
1️⃣ 现象:DNS 没挂,但内容变了
第一时间查 DNS:
- 本地
dig kakarrot.com返回了错误 IP198.18.0.73 - 用 Google DNS 查
dig @8.8.8.8却指向了正确的 GitHub Pages IP
说明 DNS 解析本身没问题。问题出在 GitHub Pages 这端。
接着打开仓库 Settings → Pages,发现两个关键信号:
- 仓库被设成了私有。GitHub Pages 免费版只服务公开仓库,私有仓库不提供服务。
- 自定义域名显示已被占用,提示说如果我拥有该域名,需要先验证所有权才能重新绑定。
问题确认了:域名被另一个 GitHub 账户绑定了。
2️⃣ 根因:GitHub Pages 域名验证机制的漏洞
这不是 DNS 劫持。是一种针对 GitHub Pages 的特殊攻击:
- 攻击者发现某个域名的 DNS 指向了 GitHub Pages(CNAME 到
*.github.io) - 但该域名从未在 GitHub 上验证过所有权
- 攻击者在自己账户的仓库里配置了这个自定义域名
- GitHub Pages 的 Host 头匹配机制直接导向了攻击者的内容
GitHub Pages 的工作原理是:收到请求 → 看 Host 头 → 匹配绑定了该域名的仓库 → 返回内容。如果域名没被验证,任何人都能”认领”它。
3️⃣ 恢复:四步夺回域名控制权
第一步:仓库改公开。 仓库 Settings → General → Danger Zone → Change visibility → Make public。没有这一步,GitHub Pages 根本不服务你的仓库。
第二步:验证域名所有权。 这是最关键的步骤,也是我之前忽略的。进入 GitHub 账户设置 https://github.com/settings/pages → Add a domain。GitHub 会生成一条 TXT 记录验证要求,类似:
主机记录: _github-pages-challenge-kakarrot0109
记录值: a034b75ef658207bb454fc2edb01ff
在阿里云 DNS 管理后台添加这条 TXT 记录。生效后点 Verify,域名就从攻击者账户释放了。
第三步:配置 DNS。 根域名不能设 CNAME,所以用 4 个 A 记录:
| 主机记录 | 类型 | 记录值 |
|---|---|---|
| @ | A | 185.199.108.153 |
| @ | A | 185.199.109.153 |
| @ | A | 185.199.110.153 |
| @ | A | 185.199.111.153 |
| www | CNAME | kakarrot0109.github.io |
第四步:重新绑定域名 + 开启 HTTPS。 仓库 Settings → Pages → 输入自定义域名,Save,等 DNS check 通过后勾选 Enforce HTTPS。
4️⃣ 预防:一次就够
- 验证域名所有权要第一时间做。
https://github.com/settings/pages里 Add a domain,做一次就不需要再做。 - 保持仓库为公开(除非你买了 GitHub Pro)。
- 开启 Enforce HTTPS。
- 偶尔打开自己网站看一眼,别等别人提醒你。
这件事之后我养成了个习惯:每换一次 DNS 配置,就去检查一遍域名验证状态。
安全措施只有在出事之前做完才叫安全措施。出事后做的,叫补救。