---
id: dns-migration-incident
title: 一次 DNS 迁移的事故记录
date: 2025-11-22
updated: 2025-11-23
category: 复盘
tags: DNS, 迁移
minutes: 11
---

给域名换解析服务商，看起来是点几下鼠标的事。我那次掉了两个东西，一个是泛解析，一个是邮件验证。

记录一下，因为这类事故的共性是：**出错的时候你还不觉得出错。**

## 发生了什么

旧服务商（DNSPod）换到 Cloudflare，流程是：先在新家把记录建好，再改 NS。

我自认为建得很全：根域、www、blog、admin、api 都建了。改完 NS 大概半小时生效，主要站点都能开。

问题在第二天暴露：

- 一个客户说他的子域打不开——那是个临时测试域名 `demo-xxx.主域`，靠**泛解析 `*`** 生效的
- 另一个说收不到密码重置邮件——**TXT 的 SPF 记录**没迁

两条记录我都"以为"迁了。实际上泛解析在新服务商里是单独一条 `*` 记录，Cloudflare 不会自动推断；SPF 那条 TXT 因为长得长，我在复制的时候漏了后半个字符串。

## 后来改进的三件事

**一、迁之前先把旧记录导成文本，逐条对比。**

```
for n in @ www mail blog admin api '*' ; do
  echo "== $n"
  dig +short A     "${n}.example.com" 2>/dev/null
  dig +short AAAA  "${n}.example.com" 2>/dev/null
  dig +short CNAME "${n}.example.com" 2>/dev/null
  dig +short TXT   "${n}.example.com" 2>/dev/null
  dig +short MX    "${n}.example.com" 2>/dev/null
done > /root/dns-before.txt
```

**二、改完 NS 之后跑一遍同样的命令，用 diff 比。**

```
# 隔一天再跑一次，输出 dns-after.txt
diff <(sort dns-before.txt) <(sort dns-after.txt)
```

差异应该只有 TTL 和 NS 记录本身。出现别的行，就是漏的。

**三、TTL 提前降下来。** 迁移前 24 小时把所有记录的 TTL 从 3600 改成 300，出问题能快速回滚。这条我这次做了，帮了大忙——发现泛解析缺失后，改回去十分钟就恢复了。

## 三条经验

**泛解析要单独核对。** `*` 在新服务商里必须显式创建，而且它的优先级低于任何具体记录，很容易在测试时被具体记录掩盖。

**TXT 是最难搬的。** SPF、DKIM、各种域名验证都在 TXT 里，内容长、格式严。复制粘贴容易截断，一条 SPF 少个 `~all` 就会让邮件进垃圾箱而不是直接失败——更难发现。

**别在周五下午动 DNS。** 这条是老规矩，但每次都是它救命。

:::注意
如果域名同时用于邮箱，迁移后一定发一封测试邮件到 Gmail，看 SPF/DKIM 是否通过（Gmail 里"显示原始邮件"能看到）。收件箱正常不代表验证通过。
:::
