DNS 区域文件校验工具
区域文件看起来像一张表,行为却更像一段程序。一条记录可能仅仅因为该行以空格开头,就继承了上一行的所有者名称;结尾没有点号的名称会被悄悄追加当前源域,于是 `www IN CNAME example.com` 变成了 example.com.example.com.;文件中间的 $ORIGIN 或 $TTL 指令会改变其后所有内容的含义;用括号跨多行书写的记录,无论怎样缩进都仍然是一条记录。本工具按照 RFC 1035 第 5 节的定义解析文件——引号字符串、注释、反斜杠转义、括号续行、BIND 8 风格的 TTL 单位以及所有者继承规则——然后展示这个文件实际描述的区域:每条记录的所有者都补全为完全限定域名,TTL 是服务器真正会返回的值,并按类型给出计数。 在解析之外,它还会做解析器没有理由去做的检查:结尾漏写点号因而会被追加源域的名称;与同名的其他记录共存的 CNAME(RFC 1034 明确禁止,多数服务器会直接拒绝加载);绕回自身的 CNAME 链;位于区域内却没有任何地址记录的 MX、NS、CNAME 目标;TTL 为 0 的记录;重复的记录;源域之外因而被静默丢弃的名称;不是日期形式的序列号;以及长到足以让一个笔误在缓存里存活好几天的否定缓存 TTL。每条问题都会指出所在行,解析失败时同样会给出行号和该行的内容。 但它无法告诉你区域的内容是否属实。它从不发起网络查询,因此不知道你写给某台主机的地址是否就是它真实的地址,不知道你委派出去的域名服务器是否真的在应答,也不知道你粘贴的 TXT 是否与服务商期望的值一致。它检查的是文件而不是运行中的区域,所以从数据库生成的记录、查询时才展开的通配符、以及位于另一个区域中的 CNAME 目标都不在它的视野内。要看实际应答请用 DNS 查询工具;这个工具适合在文件被加载之前使用,那时少写一个点号还不需要付出任何代价。
下表中每条记录的所有者名称都已补全为完全限定域名,TTL 是服务器实际会返回的值。
记录
14
名称
7
类型
8
问题
5
文件末尾处的 $ORIGIN
example.com.
默认 TTL
3600 (来自 $TTL)
主域名服务器
ns1.example.com.
即 MNAME:从服务器向它请求区域传送,NOTIFY 也由它发出。
负责人邮箱
hostmaster@example.com
写成域名形式的 RNAME,第一个标签就是邮件地址的本地部分。
序列号
2026090301
只有这个数字变大,从服务器才会重新传送区域,按 32 位序列号算术比较。
Refresh
7200 (2h)
当 NOTIFY 没有送达时,从服务器重新检查序列号的间隔。
Retry
3600 (1h)
刷新失败后,从服务器等待多久再试一次。
Expire
1209600 (2w)
超过这段时间仍未成功传送,从服务器就不再为该区域应答。
否定缓存 TTL
300 (5m)
自 RFC 2308 起,这个字段限制 NXDOMAIN 应答被缓存的时长,而不再是区域的默认 TTL。
- 错误行 19结尾没有点号,因此会被追加源域example.com → example.com.example.com.
- 错误行 20结尾没有点号,因此会被追加源域shops.myprovider.net → shops.myprovider.net.example.com.
- 警告行 19目标在本区域内,却没有任何地址记录CNAME → example.com.example.com.
- 警告行 20目标在本区域内,却没有任何地址记录CNAME → shops.myprovider.net.example.com.
- 警告行 21TTL 为 0 表示这条记录完全不允许被缓存old.example.com. A
| 所有者 | TTL | 类 | 类型 | 数据 |
|---|---|---|---|---|
| example.com. | 3600 | IN | SOA | ns1.example.com. hostmaster.example.com. 2026090301 7200 3600 1209600 300 |
| example.com. | 3600 | IN | NS | ns1.example.com. |
| example.com. | 3600 | IN | NS | ns2.example.com. |
| example.com. | 3600 | IN | A | 192.0.2.10 |
| example.com. | 3600 | IN | AAAA | 2001:db8::10 |
| example.com. | 3600 | IN | MX | 10 mail.example.com. |
| example.com. | 3600 | IN | TXT | "v=spf1 mx -all" |
| example.com. | 3600 | IN | CAA | 0 issue "letsencrypt.org" |
| ns1.example.com. | 3600 | IN | A | 192.0.2.1 |
| ns2.example.com. | 3600 | IN | A | 192.0.2.2 |
| mail.example.com. | 3600 | IN | A | 192.0.2.3 |
| www.example.com. | 3600 | IN | CNAME | example.com.example.com. |
| shop.example.com. | 3600 | IN | CNAME | shops.myprovider.net.example.com. |
| old.example.com. | 0 | IN | A | 192.0.2.9 |
全部在浏览器中完成:文件不会上传,也不会发起任何网络查询。
使用方法
- 把区域文件粘贴到文本框里。内容只留在浏览器中,不会上传,也不会发起任何查询。
- 如果文件以 $ORIGIN 开头,源域输入框留空即可;否则请按服务器配置里的区域名原样填写,因为同一个文件在不同源域下含义完全不同。
- 如果解析失败,看行号和它下面打印出来的那一行:错误报告在解析器放弃的位置,遇到未闭合的引号或括号时,可能比真正出错的那行晚一行。
- 查看 SOA 面板:负责人地址会还原成邮件地址的形式,每个计时器都同时给出秒数和易读的写法。
- 按从上到下的顺序处理问题列表——先错误、再警告、最后提示——用每条上的行号回到出问题的记录。
常见问题
- 为什么我的 CNAME 变成了 example.com.example.com.?
- 因为目标名称结尾没有点号。在主文件里,凡是不以点号结尾的名称都是相对于当前源域的相对名,解析器无从判断 "example.com" 是想写完全限定域名,还是指你区域内一台叫 example.com 的主机。这条规则适用于所有名称字段,而不只是 CNAME:MX、NS、SRV 的目标以及 SOA 的主服务器同样会被追加源域。避免踩坑的习惯是:凡是指向区域之外的名称一律加点号,区域之内的名称只写标签部分。
- 文件里没有 $TTL,这算错误吗?
- 不一定。RFC 1035 里根本没有 $TTL 指令,RFC 2308 才加入并要求必须写,但包括 dnspython 在内的多数解析器仍会对没有自带 TTL 的记录回退到 SOA 的 minimum 字段;如果 SOA 是第一条记录,它自己的 TTL 也来自这个 minimum。反过来,如果一条没有 TTL 的记录出现在 SOA 和 $TTL 都还没出现之前,那就没有任何值可继承,属于真正的错误。本工具会把这种回退作为提示列出,并告诉你最终采用的是哪个值。
- 同名同类型的两条记录 TTL 不同,哪个生效?
- 严格来说都不生效。同名同类型的记录构成一个 RRset,而一个 RRset 只能以一个 TTL 应答;文件给出多个值时,加载器保留最小的那个,日志里也不会有任何警告。于是一条 60 秒的记录旁边那条 86400 秒的同名同类型记录也会变成 60 秒,这通常与作者的本意正好相反。本工具在表格里显示实际生效的 TTL,并标出每一行被覆盖掉的写法。
- 为什么名称在区域之外的记录没有出现在表里?
- 因为它根本没有进入这个区域。加载器只保留所有者名称等于或位于区域源域之下的记录,其余属于区域外数据,会被静默丢弃而不是报错。正向区域里粘进来的 PTR 记录,或者 $ORIGIN 行之后残留的按旧源域书写的记录,就是这样在文件正常加载的同时消失的。本工具会把每个被丢弃的名称列为问题,至少让这种消失可见。
- TXT 记录可以超过 255 个字符吗?
- 整条记录可以,但其中单个字符串不行。DNS 的 character-string 用一个八位组表示长度,所以 255 就是硬上限,更长的引号字符串是语法错误而不是被截断。较长的 DKIM 或 SPF 值应当在同一条记录里写成多个引号片段——"前半段" "后半段"——服务器会把它们原样拼接,中间不插入任何字符。解析器会把这些片段分别交给应用,所以在任意位置切开都能还原,前提是顺序正确。
- 区域文件通过校验就代表 DNS 能正常工作吗?
- 不代表。解析通过只说明语法正确,这里的额外检查也只验证了部分内部一致性。父区域是否把委派指向了你的域名服务器、那些服务器是否已经加载了这个版本、地址是否可达、你递增的序列号是否真的比从服务器手上那个更大,文件本身都回答不了。序列号比较尤其特殊,它是 32 位序列空间算术,所以有人把日期敲错导致序列号"变小"时,从服务器可能会一直停留在旧区域,直到数字绕回足够远为止。
相关工具
DNS 记录参考
可搜索的 DNS 记录类型速查表 — A、AAAA、CNAME、MX、TXT、NS、SOA、PTR、SRV、CAA、DNSSEC、SVCB / HTTPS — 含示例。
TXT 记录拆分器(255 字节块)
把长 SPF、DKIM 或 DMARC TXT 记录拆分为 DNS 协议要求的 255 字节块 —— 输出 BIND、通用 zone 文件、Cloudflare 或 Route 53 语法。
DKIM 记录构建器 & 解析器
构建或解析 DKIM(DomainKeys Identified Mail)DNS TXT 记录 —— 粘贴公钥、选择 selector / 密钥类型(RSA/Ed25519)/ 哈希 / 标志,即可得到完整记录、`selector._domainkey` 主机名,以及超过 255 字符时的 DNS 分段版本。
CAA 记录构建器 (DNS 证书颁发机构授权)
生成 DNS CAA (Certificate Authority Authorization) 记录,让只有你信任的 CA 才能为你的域名签发 TLS 证书。
静态库 (.a) 检查器
在浏览器里读取 .a 归档:成员的大小与日期、每个目标文件定义和需要的符号,以及符号索引是否已经过期。
TZif(zoneinfo)时区文件解析器
在浏览器中打开编译好的 zoneinfo 文件:头部、本地时间类型、全部转换、闰秒,以及解析后的 POSIX TZ 结尾字符串。