example.com 是好的。你把 blog.example.com 指到博客托管,等 10 分钟,结果还是 DNS_PROBE_FINISHED_NXDOMAIN、This site can't be reached 或 ERR_NAME_NOT_RESOLVED。根域名能解析,子域名解析不了。95% 的情况下都是 DNS 层或主机端的 5 类问题,跟传播等待没关系,也跟浏览器没关系。本文按它们实际发生的顺序逐一排查。
先判断属于哪一种
先来一条查询:
dig blog.example.com +short
dig blog.example.com @1.1.1.1 +short
nslookup blog.example.com 8.8.8.8
对照预期:
- 空 / NXDOMAIN → 没有 DNS 记录(情况 1 或 2)
- 返回了 IP,但页面报
SSL_ERROR_NO_CYPHER_OVERLAP或ERR_SSL_PROTOCOL_ERROR→ DNS 通了,主机不认这个子域名(情况 3) - 返回了错误的 IP → 旧记录或通配挡在前面(情况 4)
- 部分 resolver 正确、部分错误 → 还在传播(情况 5)
情况 1:子域名根本没有 DNS 记录
你加了 example.com(apex),但从没给 blog 这一行加过记录。DNS 不会自动生成子域名。
怎么看:dig blog.example.com +short 返回空。DNS provider 面板里没有 blog(或 blog.example.com,看显示风格)这一行。
修复:在权威 DNS provider(dig NS example.com +short 看是哪家)加一行 A 或 CNAME:
- 静态托管(Vercel / Netlify / Cloudflare Pages / GitHub Pages):
CNAME blog → cname.vercel-dns.com.(按主机自定义域面板里给的值)。 - 指向服务器 IP:
A blog → 203.0.113.42。 - apex(
@)不能是 CNAME,但子域名可以——主机给的是主机名而不是 IP 时用 CNAME。
情况 2:记录存在但目标已经死了
dig 返回了 CNAME,但这个 CNAME 链到的最终目标 NXDOMAIN,或者那个 IP 早不再托管任何东西。
怎么看:
dig blog.example.com +trace
# 跟着 chain 看。最后是"no servers could be reached"
# 或 NXDOMAIN,就是最终目标死了。
修复:把 CNAME / A 改到当前的正确目标。如果你换了主机,旧的 cname.heroku-app.com 之类已经废了,要换成新主机给的值。
情况 3:DNS 通了但主机不认这个子域名
Vercel / Netlify / Cloudflare Pages 最经典的坑。DNS 指向是对的,但主机的项目里没把 blog.example.com 加到允许域名列表,主机的负载均衡返回通用 404 或 SSL 握手错。
怎么看:
curl -vI https://blog.example.com 2>&1 | head -30
# 典型征兆:
# - SSL 证书是 *.vercel.app 而不是你的域名
# - HTTP/2 404,正文是 "The deployment could not be found on Vercel"
# - Netlify 的 "Site not found" 页
修复:在主机面板里项目设置 → Domains,显式加上 blog.example.com。主机会自动签 SSL 证书并接入流量。这是个双边握手:DNS 在注册商配 + 域名在主机端绑定,缺一不可。
情况 4:通配或旧记录把子域名挡住了
*.example.com CNAME → some-old-host 这种通配会在 blog.example.com 命中之前先吃掉。或者你有两行 blog 记录(A + CNAME,DNS 规范禁止;或两行 A 指向不同 IP)。
怎么看:
dig blog.example.com +short
# 返回一个意料之外的 IP,仔细一看是你另一个项目的 IP
然后在 DNS 面板里找:有没有 * 行、有没有以前同事加的 blog 行、有没有被某个早就忘掉的平台集成偷偷加上的 blog 行。
修复:精确的 blog 记录永远优先于 *。删重复,确保 blog 每种类型只有一行。
情况 5:真的就是传播延迟
比大家想象的少见得多。如果 blog 这一行刚加,而之前 NXDOMAIN 的负缓存 TTL 高,某些 resolver 还会继续返回 NXDOMAIN 最长 1 小时。
怎么看:dig @1.1.1.1 和 @8.8.8.8 都通,但本地 ISP 的 resolver 不通;或反过来。whatsmydns.net 上有的地区打勾、有的打叉。
修复:等。同时把本地缓存清掉:
# macOS
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
# Linux (systemd-resolved)
sudo resolvectl flush-caches
# Windows
ipconfig /flushdns
开一个全新的无痕窗口硬刷。
最短修复路径
按命中率排序:
dig NS example.com +short—— 找到权威 DNS provider。子域名加在那里,不是注册商(如果不同的话)。- 同时在主机面板里加这个子域名 —— Vercel / Netlify / Cloudflare Pages / Render / Fly 都需要这一步。
- 等 10 分钟,
dig blog.example.com @1.1.1.1 +short期望看到主机给的主机名或 IP。 - 看主机面板的 SSL 状态 —— DNS 验证通过后通常 1–5 分钟签证完成。
- 还不行,找有没有通配或重复行把子域名挡住了。
各主机的子域名配置参考
| 主机 | DNS provider 处的记录 | 主机面板的动作 |
|---|---|---|
| Vercel | CNAME blog → cname.vercel-dns.com. | 项目 → Settings → Domains → 添加 blog.example.com |
| Netlify | CNAME blog → your-site.netlify.app. | Site → Domain settings → Add custom domain |
| Cloudflare Pages | CNAME blog → your-project.pages.dev. | Pages → Custom domains → Set up |
| Firebase Hosting | A 指向”Add Custom Domain”向导给的两个 IP | Hosting → Add custom domain |
| GitHub Pages | CNAME blog → username.github.io. | 仓库 Settings → Pages → Custom domain |
| Render | CNAME blog → your-service.onrender.com. | Service → Settings → Custom Domain |
CNAME 值大小写不敏感,不要带 https:// 前缀和结尾 /。DNS 界面通常会自动补尾点。
预防
- 子域名指向托管平台时优先用 CNAME,而不是 A —— 主机偶尔会悄悄换 IP 扩容,CNAME 跟随者会自动跟上。
- 没有真实需要别加通配 CNAME
*.example.com。 通配让新子域名”开箱即用”,但也会默默吃掉拼写错误的子域名,挡掉你正常添加的精确行。 - 新子域名加完立刻在手机网络或
@1.1.1.1resolver 测一次 —— 你笔记本的 DNS 缓存会骗你。 - 在团队文档里写清楚每个子域名归哪个主机:
blog→ Ghost;app→ Vercel;status→ BetterUptime。半年后调起来快得多。 - 稳态下子域名 CNAME 的 TTL 保持 3600 —— 缓存命中够高,需要切换时一小时内也能切。
FAQ
问:5 分钟前刚加的 CNAME,为什么还没解析?
答:新记录传到公共 resolver 只要几秒钟,但如果你在加之前就查过这个子域名,本地 resolver 已经把 NXDOMAIN 按它自己的 TTL(通常 5–60 分钟)缓存了。等过去就好,或者换一个 resolver:dig blog.example.com @1.0.0.1 +short。
问:访问子域名时跳出 Vercel / Netlify 的”Site not found”页。
答:DNS 是对的(确实打到了 Vercel 边缘),但项目没认领这个主机名。在项目的 domain settings 里加上 blog.example.com。
问:子域名需要自己的 SSL 证书吗? 答:要,但现代托管都会在 DNS 验证通过的几分钟内通过 Let’s Encrypt 自动签发。如果 1 小时之后 SSL 还卡着,看 自定义域 SSL 延迟。
问:能像 CNAME 子域名一样 CNAME 根域名(example.com)吗?
答:不能。RFC 1034 禁止在 zone apex 上配 CNAME,因为会和 SOA / NS 冲突。要么用 A 记录,要么用 DNS provider 的 “CNAME flattening” / “ALIAS” 功能(Cloudflare 和 DNSimple 都支持)。
问:子域名能打开但会跳转到根域名。
答:要么主机有”强制根域名”重定向,要么你的 CMS / 框架在服务端发了 Location: https://example.com。curl -I https://blog.example.com 看一下 —— 301 到 apex 说明是重定向问题,跟 DNS 无关。