DNS 是什么意思?域名解析原理、记录类型与查询命令
DNS 是 Domain Name System(域名系统)的缩写,作用是把 www.example.com 这样的域名翻译成服务器的 IP 地址。网络设置里的“DNS 地址”指替你完成查询的递归解析服务器;域名的记录则保存在权威服务器上。查询结果会按 TTL 缓存,所以改了解析不会立刻处处生效。
DNS 是什么意思?DNS 是 Domain Name System 的缩写,中文叫域名系统。它是一个分布在全球的数据库,负责把人记得住的域名(如 www.example.com)翻译成机器通信用的 IP 地址(如 203.0.113.10),也能反过来由 IP 查出域名。浏览器打开网站、服务器执行 yum update、邮件服务器投递邮件,第一步都是一次 DNS 查询。DNS 使用 53 端口,普通查询走 UDP,应答过大或在服务器之间同步整个区域时走 TCP。
DNS 地址、DNS 服务器、DNS 查询分别指什么
“DNS”在不同场合指不同的东西,先把三个常见说法分开:
- DNS 查询:程序发出“这个域名对应什么地址”的一次请求,以及收到的应答。
- DNS 地址:网卡设置里填的那一两个 IP,比如 223.5.5.5。它的作用是告诉本机:域名查询发给谁。这个地址指向的是一台递归解析服务器。
- DNS 服务器:分为两类,作用完全不同。
| 对比项 | 递归解析服务器 | 权威服务器 |
|---|---|---|
| 作用 | 替客户端跑完整个查询过程,把最终结果返回给客户端并缓存 | 保存某个域名区域(zone)的记录,只回答自己负责的域名 |
| 谁来问它 | 电脑、服务器,DNS 地址里填的就是它 | 递归解析服务器,按域名的 NS 记录找到它 |
| 例子 | 运营商 DNS、机房提供的 DNS、223.5.5.5、119.29.29.29 | 解析服务商的 ns1、ns2 服务器,自建的 BIND |
| 数据从哪来 | 向权威服务器查询后缓存 | 管理员在解析后台或区域文件里录入 |
| 出故障的表现 | 用它的机器,所有域名都解析失败或很慢 | 只有它负责的域名解析失败,所有访客都受影响 |
所以“给网站做域名解析”是在权威服务器上加记录,“给服务器设置 DNS”是指定递归服务器,两件事在不同的地方操作,互不替代。
域名解析的过程:递归查询与迭代查询
以一台服务器第一次访问 www.example.com、各级缓存都为空为例:
- 查本机。程序调用系统解析器,先看 hosts 文件,再看本机缓存(Windows 的 DNS Client 服务;Linux 上常见的是 systemd-resolved 或 nscd,没有运行任何缓存服务的 Linux 本机不缓存)。命中就直接返回。
- 问递归服务器。本机没有,就把查询发给 DNS 地址里的第一台服务器,报文里带“期望递归”(RD)标志,意思是“请直接给我最终答案”。客户端和递归服务器之间的这一问一答,叫递归查询。
- 递归服务器问根服务器。它的缓存里也没有,就去问根服务器。根服务器不知道
www.example.com的地址,但知道 .com 由哪些服务器负责,返回它们的名字和地址,这种“去问别人”的应答叫转介(referral)。 - 问 .com 的服务器。负责 .com 这一级的 TLD 服务器同样不给最终答案,只返回 example.com 的 NS 记录,也就是这个域名的权威服务器。
- 问权威服务器。权威服务器返回
www.example.com的 A 记录 203.0.113.10,应答里带“权威应答”(AA)标志。 - 缓存并返回。递归服务器把结果连同 TTL 存进缓存,再返回给客户端。
第 3 到第 5 步,递归服务器每次拿到的都是“下一步去问谁”的线索,然后自己再去问,这种方式叫迭代查询。根服务器共有 a 到 m 13 个名字,每个名字背后通过任播部署了大量节点;递归服务器会把 .com、.cn 这类 TLD(域名后缀这一级)的 NS 缓存很长时间,并不是每次查询都去问根。
dig +trace 只在第一步向本机配置的 DNS 取一份根服务器列表,之后由 dig 自己从根开始逐级迭代,能看到这条链的每一环:
dig www.example.com +trace
输出按级分段:第一段是根服务器列表(a.root-servers.net. 等),第二段是 .com 的服务器,第三段是 example.com 的权威服务器,最后一段才是 A 记录。断在哪一段,问题就在哪一级:如果卡在问 example.com 的权威服务器那一步,多半是域名的 NS 指向了不存在或不响应的服务器。
缓存与 TTL:为什么改了解析不立即生效
每条记录都带一个 TTL(Time To Live,生存时间),单位是秒,表示这条结果可以被缓存多久。递归服务器、操作系统、浏览器都可能缓存;权威服务器上的记录改了,已经缓存旧值的地方要等 TTL 到期才会重新查询。
查看递归服务器缓存里的结果还剩多少秒:
dig www.example.com @223.5.5.5 +noall +answer
# www.example.com. 2875 IN A 203.0.113.10
第二列 2875 是剩余 TTL,隔几秒再查会变小;直接问权威服务器,看到的则是设置的完整值。
计划更换服务器 IP 时,按 TTL 倒推操作时间。假设原记录 TTL 为 3600 秒:
| 时间 | 操作 | 原因 |
|---|---|---|
| 切换前一天 | 把 TTL 从 3600 改为 300 | 各处缓存的旧版本最长还要保留 3600 秒,等它们过期后,缓存里就都是 TTL 300 的版本 |
| 切换时 | 把 A 记录改成新 IP | 此时任何缓存最多再保留 5 分钟 |
| 切换后 5 分钟起 | 绝大部分访问到达新 IP | 个别不遵守 TTL 的解析器和客户端会更久,旧服务器先保留一段时间 |
| 稳定后 | TTL 改回 3600 或更长 | 减少查询量,权威服务器短暂故障时缓存还能撑一阵 |
还有一种容易被忽略的缓存:否定缓存。记录添加之前有人查过这个名字,递归服务器会把“不存在”(NXDOMAIN)也缓存起来,时长取该区域 SOA 记录本身的 TTL 与 SOA 最后一个字段中较小的那个(RFC 2308)。表现是“新加的子域名,别人都能解析,我这里就是查不到”。新增记录之前不要先去查它;查之前可以看一眼 SOA:
dig example.com SOA +short
# ns1.example.net. admin.example.com. 2026121701 3600 600 1209600 300
最后一个数字 300,就是否定应答最多会被缓存的秒数。
DNS 记录类型对照
| 记录 | 作用 | 记录值示例 | 注意 |
|---|---|---|---|
| A | 域名指向 IPv4 地址 | 203.0.113.10 | 一个名字可以有多条,解析器通常轮换返回顺序,访问会分散到各个地址 |
| AAAA | 域名指向 IPv6 地址 | 2001:db8::10 | 服务确实能经 IPv6 访问时再添加 |
| CNAME | 别名,指向另一个域名 | www.example.com.cdn.example.net |
有 CNAME 的名字不能再有其他记录;根域名(@)不能用 CNAME,部分服务商提供 CNAME 拉平或 ALIAS 记录 |
| MX | 指定接收邮件的服务器 | 10 mail.example.com | 值是主机名而不是 IP;数字越小优先级越高 |
| NS | 指定域名由哪些权威服务器负责 | ns1.example.net | 整个域名的 NS 要在注册商处修改才生效 |
| TXT | 任意文本 | v=spf1 ip4:203.0.113.10 -all | 用于 SPF、DKIM、域名所有权验证 |
| PTR | 反向解析,IP 指向域名 | mail.example.com | 归 IP 的持有者管理,机房服务器要向机房申请 |
| SOA | 区域的起始授权信息 | 主服务器、管理员邮箱、序列号、刷新与过期时间 | 自建 DNS 有从服务器时,每次修改都要增大序列号,否则从服务器不会同步 |
| CAA | 限定哪些证书机构可以为本域名签发证书 | 0 issue “letsencrypt.org” | 不设 CAA 时任何证书机构都可以签发 |
用 nslookup 和 dig 查询 DNS
nslookup 在 Windows 和 Linux 上都有,适合快速查一下;dig(Linux 上在 bind-utils 或 dnsutils 软件包里)输出完整,排查时更好用。
nslookup www.example.com # 用本机配置的 DNS 查询
nslookup www.example.com 119.29.29.29 # 指定 DNS 服务器查询
nslookup -type=mx example.com # 查 MX 记录
dig www.example.com # 完整输出
dig @119.29.29.29 www.example.com A +short
dig example.com NS +short # 查这个域名的权威服务器
dig -x 203.0.113.10 +short # 反向解析
nslookup 的结果上方常有一行 Non-authoritative answer(非权威应答),意思是答案由递归服务器代查或取自缓存,而不是权威服务器亲自回答,这是正常现象,不是报错。
dig 的完整输出里,有四处最值得看:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4660
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; Query time: 28 msec
;; SERVER: 223.5.5.5#53(223.5.5.5) (UDP)
- status:这次查询的结论。
NOERROR表示查询成功,但 ANSWER 为 0 时说明名字存在、只是没有这种类型的记录(比如只加了 A 却查 AAAA);NXDOMAIN表示域名不存在;SERVFAIL表示解析服务器没能完成查询,常见于权威服务器不响应或 DNSSEC 验证失败;REFUSED表示服务器拒绝回答,常见于向一台不负责该域名的权威服务器发起查询,或者递归服务器只为自己网段的客户端服务。 - flags:
rd表示请求了递归,ra表示服务器愿意递归,aa表示这是权威应答。直接问权威服务器时应当看到aa;问递归服务器时通常只有qr rd ra。 - SERVER:这次实际回答的是哪台服务器。本机配置了多个 DNS 时,用它确认用的是哪一台;Ubuntu 上显示 127.0.0.53,说明查询先交给了本机的 systemd-resolved,再由它转发出去。
- Query time:第一次查询通常几十到几百毫秒,紧接着再查一次降到个位数,说明第二次命中了缓存。
Windows 的 PowerShell 里可以用 Resolve-DnsName www.example.com -Server 223.5.5.5 查询,用 ipconfig /displaydns 查看本机缓存,ipconfig /flushdns 清空缓存。
建站时 DNS 解析不生效怎么查
按下面的顺序逐项排除,前一项确认没问题再看下一项:
| 检查项 | 命令或做法 | 常见问题 |
|---|---|---|
| 1. 域名实际由哪家权威服务器负责 | 直接问 .com 的 TLD 服务器:dig example.com NS @a.gtld-servers.net,看 AUTHORITY 段 |
在 A 服务商后台加了记录,注册商处的 NS 却还指向 B 服务商,记录永远不会生效 |
| 2. 权威服务器上有没有这条记录 | dig www.example.com @ns1.example.net +norec |
只加了 @ 没加 www;主机记录填成完整域名,结果变成 www.example.com.example.com |
| 3. 递归服务器拿到的是不是新值 | dig www.example.com @223.5.5.5,看剩余 TTL |
旧值或否定应答还在缓存里,等 TTL 到期 |
| 4. 本机有没有被 hosts 覆盖 | 查看 hosts 文件;Linux 用 getent hosts www.example.com |
测试时写进 hosts 的条目忘了删 |
| 5. 解析已经正确,网站还是打不开 | curl -I http://203.0.113.10 -H "Host: www.example.com" |
问题不在 DNS:端口没放行、Web 服务没绑定这个域名,或内地机房的网站还没完成 ICP 备案 |
使用了按运营商线路解析(智能解析)的域名,电信、联通、移动用户查到的地址本来就可能不同,排查时要用对应线路的 DNS 去查,不要拿一个结果代表所有访客。
机房内部要不要自建 DNS
服务器上了一定数量的机房,内网通常值得部署两台自己的解析服务器,解决三件事:
- 内网缓存:所有服务器的 DNS 地址指向内网解析器,重复查询在本地命中,延迟低,也不受公共 DNS 查询频率限制的影响。
- 内部名称:交换机、PDU、BMC 管理口、监控服务器用名字访问,地址变了只改一处。内部域名用自己已注册域名下的子域,如 dc.example.com,不要随意编造一个域名后缀,以免将来和公网上的真实域名冲突。
- 出口集中:只有这两台需要访问外部 DNS,出口防火墙的规则更简单。
下面是 Unbound 做缓存兼内部名称解析的最小配置(/etc/unbound/unbound.conf),地址按实际网段修改:
server:
interface: 10.0.0.53
access-control: 10.0.0.0/8 allow
access-control: 0.0.0.0/0 refuse
local-zone: "dc.example.com." static
local-data: "pdu-a01.dc.example.com. IN A 10.0.10.21"
local-data: "sw-core1.dc.example.com. IN A 10.0.0.2"
unbound-checkconf # 检查配置语法
systemctl restart unbound
dig @10.0.0.53 pdu-a01.dc.example.com +short
这份配置里最要紧的是 access-control:递归解析服务器绝不能对公网开放。开放递归的服务器会被利用做 DNS 反射放大攻击:攻击者伪造受害者的源地址发出小查询,你的服务器把大得多的应答打向受害者,机房出口带宽也一起被占用。从机房外的一台机器测一下(地址换成你的 DNS 服务器公网地址):
dig @198.51.100.53 www.example.com
如果返回了 A 记录、flags 里有 ra,就是开放递归,要立刻收紧;返回 status: REFUSED 或超时才对。对外提供权威解析的服务器,同样要关闭递归功能。
自建之后,还要让每台服务器知道该填哪个 DNS,这也是客户常问的问题。答案应当跟着地址段走:同一个段里的服务器,用同一组 DNS。Toplink DCIM 的 IP 地址管理 在每个地址段上记录两个 DNS 地址,和网关、VLAN 放在一起,运维给客户回复网络参数时,地址、网关和 DNS 从同一条记录里读出。内网建好了自己的解析服务器,把各段登记的 DNS 改成内网地址即可,不必逐台去记。
常见问题
DNS 地址填错了会怎样?
用 IP 地址访问一切正常,但域名全部解析失败或很慢:网页打不开、yum 和 apt 报无法解析主机、邮件发不出去。用 nslookup 域名 223.5.5.5 换一个 DNS 查询,能返回结果就说明是本机 DNS 地址的问题。
hosts 文件和 DNS 是什么关系?
hosts 文件是本机的静态对照表,Linux 的 /etc/hosts 和 Windows 的 C:\Windows\System32\drivers\etc\hosts 默认都比 DNS 优先。测试新服务器时常用它临时把域名指过去,测完要删掉,否则这台电脑会一直访问写死的地址。
什么是 DNS 劫持?
查询结果在途中或在解析服务器上被换成了别的地址,表现为同一个域名在不同网络里解析结果不同、网页被跳转。对比权威服务器和几个公共 DNS 的结果可以确认;网站一侧可以启用 DNSSEC,访客一侧可以改用 DNS over HTTPS 或 DNS over TLS。