跳到主要内容
AZ Tools

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)

SOA 记录

主域名服务器

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
各类型记录数
A 5CNAME 2NS 2AAAA 1CAA 1MX 1SOA 1TXT 1
记录
所有者TTL类型数据
example.com.3600INSOAns1.example.com. hostmaster.example.com. 2026090301 7200 3600 1209600 300
example.com.3600INNSns1.example.com.
example.com.3600INNSns2.example.com.
example.com.3600INA192.0.2.10
example.com.3600INAAAA2001:db8::10
example.com.3600INMX10 mail.example.com.
example.com.3600INTXT"v=spf1 mx -all"
example.com.3600INCAA0 issue "letsencrypt.org"
ns1.example.com.3600INA192.0.2.1
ns2.example.com.3600INA192.0.2.2
mail.example.com.3600INA192.0.2.3
www.example.com.3600INCNAMEexample.com.example.com.
shop.example.com.3600INCNAMEshops.myprovider.net.example.com.
old.example.com.0INA192.0.2.9

全部在浏览器中完成:文件不会上传,也不会发起任何网络查询。

使用方法

  1. 把区域文件粘贴到文本框里。内容只留在浏览器中,不会上传,也不会发起任何查询。
  2. 如果文件以 $ORIGIN 开头,源域输入框留空即可;否则请按服务器配置里的区域名原样填写,因为同一个文件在不同源域下含义完全不同。
  3. 如果解析失败,看行号和它下面打印出来的那一行:错误报告在解析器放弃的位置,遇到未闭合的引号或括号时,可能比真正出错的那行晚一行。
  4. 查看 SOA 面板:负责人地址会还原成邮件地址的形式,每个计时器都同时给出秒数和易读的写法。
  5. 按从上到下的顺序处理问题列表——先错误、再警告、最后提示——用每条上的行号回到出问题的记录。

常见问题

为什么我的 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 位序列空间算术,所以有人把日期敲错导致序列号"变小"时,从服务器可能会一直停留在旧区域,直到数字绕回足够远为止。

相关工具