做运维和开发这些年,我遇到最多的一句求助就是:"IP能ping通,网络显示正常,但网页就是打不开。"十次里有八次,问题都出在DNS上。但你要问对方DNS到底是什么,大多数人只能答出半句:"把域名解析成IP地址。"
这话没错,可远远不够。域名解析远不是"查一下记录"那么简单,它背后是浏览器缓存、操作系统解析器、递归服务器、根服务器、顶级域服务器、权威服务器一整条链路的接力协作。任何一个环节出问题,症状都很有迷惑性:一会儿能开一会儿打不开、换个网络就好、手机能上电脑不行、微信能发消息但网页白屏——这些都是典型的DNS故障脸谱。
这篇文章就把域名解析的全流程彻底拆开讲一遍:从DNS为什么存在、域名结构怎么设计,到一次查询请求具体经过哪些节点、每一步返回什么,再到Linux和Windows下怎么配DNS、公共DNS怎么选、常见的故障怎么定位。适合正在补网络基础的后端和运维新人,也适合被"DNS玄学问题"折磨过、想真正搞懂原理的老手。
1. DNS设计的底层逻辑:为什么域名解析不是"查表"那么简单
1.1 没有DNS的世界:hosts文件和它的天花板
互联网早期确实没有DNS。那时候全网主机数量非常少,每台机器本地维护一个叫hosts的文件,里面手工记录"主机名-IP"的映射关系,大家定期同步。这种方式在节点只有几百台时完全够用,但随着主机数量爆炸式增长,一个集中式hosts文件根本无力维护——哪怕只做每日更新,分发流量都能把网络撑垮。
这就引出了域名解析系统要解决的核心矛盾:映射数据量巨大、更新频繁,但查询必须足够快、足够可靠。如果沿用"一个大电话本"的思路,会同时撞上三堵墙:单点故障——电话本服务器挂了全行业瘫痪;性能瓶颈——所有查询挤一个入口;数据一致性——各地副本永远对不上。
所以DNS最终采用了分布式、分层、可缓存的架构。分层解决"数量"问题,缓存解决"速度"问题,分布式冗余解决"可靠性"问题。把这个设计意图装进脑子里,再看后面的解析流程,你会发现每一步都不是凭空来的,而是在给某一种问题兜底。
1.2 域名的层级结构:从根到叶子
域名看起来就是一段用点分隔的字符串,比如 www.example.com,但它的结构是严格分层的。完整域名(FQDN)从右往左拆:最右侧隐性的点代表根域,是整棵树的顶部;com、org、cn 这类是顶级域;example.com 是二级域;www 是三级主机名。每一级都由上一级授权管理,形成一棵倒置的树。
为什么解析方向是从右往左?因为域名系统采用的是"上级告诉你去哪找下级"的授权模式。根服务器完全不关心 www.example.com 的IP是多少,它只负责告诉你".com 的权威服务器在哪";.com 的服务器也不存 example.com 的详细解析记录,但它知道 example.com 的权威服务器是谁。逐级授权让每一层只需要维护自己下一级的信息,一个海量规模的问题就被拆解成了若干个小问题。
1.3 三种服务器的分工
要把流程讲明白,得先分清三类角色:
- 权威服务器(Authoritative DNS Server):域名数据的最终来源。你买了一个域名,在云服务商后台配置的那几条解析记录,最终就是同步到权威服务器上的。
- 递归服务器(Recursive Resolver):替终端用户跑腿查询的服务器。它自己不生产数据,但会缓存结果,运营商DNS、公共DNS都属于这一类。
- 终端解析器(Stub Resolver):电脑和手机里的解析程序。它通常不自己做完整查询,而是把请求丢给网卡配置的那个递归服务器地址。
这里有个高频误区:日常说的"本地DNS",指的是电脑网卡里配置的那个递归服务器地址,不是你本机。它可能远在运营商机房,也可能是114.114.114.114或223.5.5.5。很多人把"本地DNS"当成自己电脑,排查问题时就会绕进死胡同。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 域名解析全流程拆解:从输入网址到拿到IP
2.1 本地关卡:浏览器缓存、hosts和操作系统缓存
整个解析流程的第一步,根本不会出网。你在浏览器地址栏敲下 www.example.com 回车后,浏览器首先查自己的内存缓存——如果你之前访问过这个域名,且缓存还没过期,直接就拿着IP去建连接了,整个过程可能连1毫秒都用不到。
浏览器缓存没命中,接着查hosts文件。这个文件在Windows里位于 C:\Windows\System32\drivers\etc\hosts,Linux和macOS在 /etc/hosts。它拥有最高的本地优先级,写进去的映射会直接生效。很多开发环境里把 127.0.0.1 dev.example.com 写进hosts,就是利用这个机制。
hosts也没命中,再查操作系统级的DNS缓存。Windows上用 ipconfig /displaydns 可以查看全部缓存记录,Linux的systemd-resolved环境用 resolvectl statistics 或 resolvectl query 查看。缓存没命中,系统才真正向网卡配置的递归服务器发出DNS查询请求。
注意:浏览器缓存、系统缓存的层级顺序在细节上因系统而异,Chrome有自己的异步DNS解析器,Firefox甚至默认启用DoH会跳过系统配置的DNS。真遇到"浏览器打不开但命令行能解析"这种怪事,优先往这个方向查。
2.2 递归服务器的"脏活累活"
请求到了递归服务器这里,才算是真正进入互联网DNS体系。递归服务器收到 www.example.com 的查询后,先查自己的缓存——大部分热门域名在这里就能直接命中,响应非常快。这也是为什么公共DNS会在全国部署大量节点,节点离你越近,网络延迟越低。
如果缓存没命中,递归服务器就要开始做"脏活"了:它要去问根服务器、问顶级域服务器、最后问权威服务器,把结果一层层拼出来。这个过程对终端用户完全透明——你的电脑只需要和递归服务器这一方通信,剩下的路它自己跑。
从这个角度说,递归服务器就像一个旅行社。你自己地图都不会看,它替你规划好路线、买好票、把你送到目的地,然后把"怎么走"的结果告诉你。旅行社的行程单写得对不对,取决于它手里的信息新不新,这就是缓存和TTL要解决的问题。
2.3 从根到权威:一次经典的迭代查询
以查询 www.example.com 且递归服务器缓存全空为例,完整链路是这样的:
- 递归服务器先访问根服务器(13个IP,全球任播部署)。根服务器收到查询
www.example.com后,自己并没有答案,但它知道com顶级域的NS记录和对应IP,于是返回:com的权威服务器在a.gtld-servers.net,地址是192.5.6.30,你去问它。 - 递归服务器转问
.com顶级域服务器。顶级域服务器也不存example.com的具体记录,但它知道example.com的权威服务器是谁,于是返回NS记录:example.com的权威服务器是ns1.example.com,地址是203.0.113.10。 - 递归服务器转问
example.com的权威服务器。这台服务器才真正存着www这个主机名对应的A记录,于是返回www.example.com的IP93.184.216.34。 - 递归服务器拿到最终结果,一方面返回给你的电脑,另一方面按照该记录附带的TTL值在本地缓存一份,下次再有用户查询就直接命中。
这个从根服务器到顶级域服务器再到权威服务器的过程,专业术语叫迭代查询。整个过程中,递归服务器一直在"问别人",根服务器和顶级域服务器则各自只回答"下一站去哪",所有具体答案都由权威服务器给出。
2.4 用实例把全流程走一遍
纸上谈兵没意思,直接上命令。在机器上安装 dnsutils(Debian/Ubuntu)或 bind-utils(CentOS/RHEL)之后,用 dig 就能观察每一步细节:
bash复制# 先看递归服务器缓存为空时的完整查询过程
dig www.example.com
# 指定从根服务器开始追踪
dig @a.root-servers.net www.example.com
# 查看返回的权威区段
dig www.example.com +trace
+trace 参数会模拟递归服务器视角,从根服务器一路问到权威服务器,每一步都会打印出服务器返回的NS记录和A记录,非常直观。我第一次完整跑通这个命令的时候,才真正理解"分层解析"到底是什么意思——原来每次查询远不止一个请求,而是一条链上的接力。
还有一个值得试的操作:用 dig 直接指定某台服务器查询,比对结果:
bash复制# 对比不同递归服务器返回的结果
dig @223.5.5.5 example.com
dig @114.114.114.114 example.com
dig @8.8.8.8 example.com
如果不同公共DNS返回的IP不一样,说明存在解析不统一的问题,这在故障排查里是极重要的线索。
3. DNS记录与关键参数:真正看懂解析配置
3.1 核心记录类型速查
在权威服务器上配置的解析记录,类型远比大家以为的丰富。下面是实际工作中最高频用到的几种:
| 记录类型 | 全称 | 作用 | 配置示例 |
|---|---|---|---|
| A | Address Record | 将域名指向IPv4地址 | www 300 IN A 93.184.216.34 |
| AAAA | IPv6 Address Record | 将域名指向IPv6地址 | www 300 IN AAAA 2606:2800:220:1:... |
| CNAME | Canonical Name | 域名别名,指向另一个域名 | www 300 IN CNAME example.com |
| MX | Mail Exchange | 邮件服务器记录,含优先级 | example.com 300 IN MX 10 mail.example.com |
| NS | Name Server | 指定域名的权威服务器 | example.com 300 IN NS ns1.example.com |
| TXT | Text Record | 任意文本,常用于验证和SPF | example.com 300 IN TXT "v=spf1 include:... -all" |
| SOA | Start of Authority | 区域起始记录,描述主权威服务器和刷新参数 | 一般在区域的起始位置 |
| PTR | Pointer Record | 反向解析,从IP找域名 | 34.216.184.93.in-addr.arpa 300 IN PTR www.example.com |
日常开发接触最多的是A和CNAME。A记录直接给IP,CNAME则是指向另一个域名的别名。举个例子,如果你给 www 配了CNAME指向 cdn.example.com,那么用户请求 www 时,DNS会先解析出 cdn.example.com 的IP再返回。CNAME很方便,但有个硬性限制:CNAME 记录不能和其他记录共存在这个主机名上。你不能同时给 www 配CNAME又配A记录,也不能让MX邮件记录挂在有CNAME的域名上,否则可能出现不可预期的行为。
MX记录是邮箱服务的关键。它带一个优先级数字,数值越小优先级越高。如果配置了多个MX记录,发件方会先尝试最高优先级(数值最小)的服务器,失败后才尝试次优先级的。很多企业邮箱收不到信的排查,最后都落到"MX记录被无意中删掉或优先级配错"上。
TXT记录早些年主要用于SPF反垃圾邮件验证,现在则大量用于域名所有权验证,比如在微信、支付宝、云服务商后台要求添加一条TXT记录来证明"这个域名是你的"。这类记录看起来不起眼,但漏配直接导致验证失败。
3.2 TTL:缓存时间的双刃剑
TTL(Time To Live)是DNS体系中最容易被忽略、却影响深远的参数。它告诉递归服务器和终端解析器:"这条记录可以缓存多久。"单位是秒,常见取值有60、300、3600、86400。
TTL设大,比如86400(24小时),优点是查询压力小、解析响应快,缺点是一旦你要更换服务器IP,旧IP最长可能要过24小时才在全世界彻底失效,这期间部分用户还会被引导到旧地址。TTL设小,比如60秒,优点自然是迁移和故障切换极快,适合频繁调整的环境,缺点是所有递归服务器都会更频繁地回源到权威服务器,权威服务器的QPS压力会明显上升。
我的习惯是:平时把网站主域名的TTL设在300~600秒之间,既不产生过多回源压力,又能在需要更换IP时快速生效。真到要换IP的前两天,再临时把TTL调到60秒,等迁移完成、确认全球解析稳定后,再调回正常值。这个"先降TTL,再换IP,后恢复"的顺序,是运维老手公认的平滑迁移标准动作。
3.3 解析配置的常见坑
第一个坑是泛解析滥用。有人图省事配一条 *.example.com 泛解析,确实能覆盖所有子域名,但也会带来两个问题:一是无法再给具体子域名单独配记录,二是一些恶意扫描工具会借助泛解析探测你的服务器。更麻烦的是,如果主机配置了自动获取SSL证书,攻击者可以用任意随机子域名来消耗你的证书签发额度。
第二个坑是CNAME与MX共存。前文提过CNAME不能与其他记录共存,这条规则会导致一个隐蔽故障:如果主域名 example.com 配置了CNAME(虽然不建议在主域上用CNAME),同时又想配MX记录收邮件,你会发现部分邮件服务商会拒收。正确做法是主域名用A记录,www 才用CNAME。
第三个坑在新版本工具链里越来越常见。某些代理工具和网络软件的DNS模块正在调整选项格式,升级后会打印类似 warn[0000] 'independent_cache' dns option is deprecated 的警告日志。遇到这种日志不用慌,它的含义只是"这一个旧参数已废弃",系统会自动采用新方案,不会影响正常解析,但建议尽快对照软件文档调整配置,免得以后大版本升级时行为发生变化。
4. 不同场景下的DNS配置实战
4.1 Linux修改DNS:临时、持久与"重启还原"
Linux下的DNS配置,是现代运维绕不开的基本功。先分清两种情况:临时修改和永久修改。
临时修改最简单,直接编辑 /etc/resolv.conf:
bash复制# 查看当前DNS配置
cat /etc/resolv.conf
# 临时修改
sudo vim /etc/resolv.conf
nameserver 223.5.5.5
nameserver 114.114.114.114
但问题在于,很多现代Linux发行版使用 systemd-resolved 或 NetworkManager 管理网络,/etc/resolv.conf 往往是一个软链接,指向systemd生成的动态文件。你手动改完,重启网络服务甚至过几分钟就会被打回原形。这个"修改DNS后重启网络就还原"的经典问题,安装系统后几乎总会遇到一次。
正确的永久修改方式分发行版:
- 使用NetworkManager的系统(桌面Linux、以及部分服务器版本)推荐通过nmcli修改:
bash复制# 查看连接名称
nmcli connection show
# 修改指定连接的IPv4 DNS
sudo nmcli connection modify "Wired Connection" ipv4.dns "223.5.5.5 114.114.114.114" ipv4.ignore-auto-dns yes
# 生效
sudo nmcli connection up "Wired Connection"
- 使用systemd-resolved的系统,通过配置文件管理:
bash复制sudo mkdir -p /etc/systemd/resolved.conf.d
sudo vim /etc/systemd/resolved.conf.d/dns.conf
内容写法自行按发行版手册来,但思路一样:不要直接动 /etc/resolv.conf,要从源头配置。我见过太多同事在 /etc/resolv.conf 里反复改、反复丢,最后发现是NetworkManager在每次重连时自动覆盖。搞懂"谁在管理 resolv.conf",比记住任何一条命令都重要。
4.2 Windows与服务器场景:从图形界面到AD域控
Windows上的DNS设置,大部分情况下图形界面就够用:控制面板 → 网络连接 → 属性 → IPv4属性,填上首选DNS和备用DNS。命令行也有等价方式,适合批量操作:
powershell复制# 用PowerShell设置IP和DNS
Set-DnsClientServerAddress -InterfaceAlias "以太网" -ServerAddresses ("223.5.5.5","114.114.114.114")
# 查看所有网卡DNS
Get-DnsClientServerAddress
但在企业网络里,DNS的意义远不止"上网解析"。搭建Windows域控、Exchange邮件服务、vCenter虚拟化平台时,DNS是基础设施级别的前置依赖。域控服务器要求域内DNS支持动态注册,客户端通过SRV记录定位域控位置,一旦DNS配置错误,域成员会出现"找不到域控""组策略不生效"等一系列连锁问题。
vCenter这类企业平台在安装时更是对DNS有严格校验:安装前必须确保主机名能通过DNS正反向解析。实际部署中很多人因为还没搭好内部DNS就急着装vCenter,装到一半报"无法解析主机名"而卡住。这类产品对DNS的强依赖,核心原因在于它们内部的证书签发、组件间通信都需要通过主机名互相访问,而不依赖可能变化的IP。
所以我的建议是:在生产环境里,要么先搭好内部DNS域,要么至少在hosts文件里把关键主机名和IP写全,再启动平台安装。否则排查起来会让你怀疑人生。
4.3 公共DNS怎么选:本地运营商还是大厂
这是每次聊DNS都会吵起来的话题。运营商给的本地DNS优势是延迟极低、离你物理距离近,理论上解析速度最快;缺点是偶尔会做广告拦截或强制跳转,而且在跨网解析和热点域名CDN调度上可能不够精准。公共DNS则胜在稳定、中立、全球节点多,尤其在跨运营商或普通家庭宽带场景下,解析结果的IP往往更合理。
几家常见公共DNS,我结合长期使用感受整理如下:
| DNS服务 | 地址 | 特点 |
|---|---|---|
| 阿里DNS | 223.5.5.5 / 223.6.6.6 | 国内节点多,访问国内网站快 |
| 腾讯DNSPod | 119.29.29.29 / 182.254.116.116 | 与CDN调度结合好 |
| 114DNS | 114.114.114.114 / 114.115.115.115 | 稳定老牌,拦截钓鱼网站 |
| Cloudflare | 1.1.1.1 / 1.0.0.1 | 全球性强,对国外站点友好 |
| 8.8.8.8 / 8.8.4.4 | 全球认知度高,国内访问延迟不稳定 |
关于"8.8.8.8有危险吗"这个热门问题,答案其实很朴素:Google DNS本身是正规的公共递归服务,不会因为你用了它就被"监控",但它是一个国外的服务节点,在国内网络的通信质量受国际链路和国际出口影响,经常出现丢包和延迟。真正值得警惕的不是8.8.8.8这个IP有什么后门,而是你所有的DNS查询流量都会经过它——从隐私角度看,选用任何第三方公共DNS都等于把自己访问过哪些域名交给了这家公司。在意隐私的话,更稳妥的选择是自建递归解析,或者启用DoH/DoT加密查询,避免DNS请求在网络上明文裸奔。
"DNS优选"的正确思路不是盲目跟随评测文章,而是按场景组合:访问国内外站用国内公共DNS,开发调试用运营商DNS,出海场景才考虑国外公共DNS。最优配置往往是双备:主DNS用延迟最低的,备用DNS用解析最稳的。
5. DNS故障排查:从现象到根因的实战路径
5.1 先看是不是网的问题,再看是不是DNS的问题
排查网络故障,第一件事永远是区分"网络层不通"和"DNS解析失败"。最简单的判断方法:
bash复制# 直接访问IP,绕开DNS
curl -v http://93.184.216.34 --resolve www.example.com:80:93.184.216.34
# 或者直接ping IP
ping 223.5.5.5
如果IP能通,但域名访问不了,问题几乎可以锁定在DNS链路。如果IP都不通,那就是路由、网关、物理链路的事,别在DNS上浪费时间。
很多人遇到的"DNS Client事件1014后断网",属于Windows系统记录的一类典型故障:系统日志显示 DNS Client Events 1014: 名称解析超时,随后网络看起来就"断了"。这个现象的本质是DNS查询超时,导致所有依赖域名访问的应用全部失败——浏览器白屏、消息收不到、应用连不上服务器。遇到这个情况,先重启网络适配器或者 ipconfig /flushdns 清空缓存,然后测试 nslookup 是否正常。如果 nslookup 也超时,大概率是递归服务器本身的问题,换个DNS再试。这类问题很多时候就是运营商DNS节点故障或本地路由器DNS缓存拥塞引起的。
还有一个非常常见、排查起来却很迷惑的现象:路由器能上网,电脑连上路由器却打不开网页,提示"无法找到DNS地址"。这通常是路由器自动下发的DNS地址在局域网内被运营商劫持或过滤,或者路由器自身的DNS代理缓存出了问题。最快的验证办法是在电脑上手动把DNS改成公共DNS,如果立刻恢复,那就确认是路由器/DHCP下发的DNS不可靠。解决手段是进路由器后台修改WAN口DNS,而不是只改电脑。
5.2 浏览器报错和系统诊断信息的含义
浏览器报错是DNS故障最直观的窗口。Chrome提示 DNS_PROBE_STARTED,意思是"系统开始做域名探测,但还没有得到结果",通常意味着DNS请求发出去了但响应超时。如果紧接着出现 DNS_PROBE_FINISHED_NXDOMAIN,那就是明确的"域名不存在":服务器返回了结果,但记录里没有这个域名。N固DOMAIN 经常被误解为"域名真的不存在",实际上很多情况下是递归服务器缓存了过期的NXDOMAIN结果,或者你多打了一个字母。
Windows断网诊断时会提示"dns 地址。正在诊断该问题。",这是系统在尝试解析一个检测域名但失败了,属于通用兜底提示。看到这段说明要把重点放到根因排查上,而不是跟提示较劲。Mac下对应的是网络诊断工具里的"DNS服务器无响应"。
浏览器层面的报错还有一个容易被忽视的原因:浏览器自身开了安全DNS(DoH),导致系统配置的DNS全被绕过。前面提到过Firefox默认可能启用DoH,Chrome也会在某些系统上启用安全DNS。你以为改的是系统DNS,实际上浏览器根本没走系统配置,这种"配置了但没生效"的尴尬,在Windows上尤其多。
5.3 排查工具速查与典型思路
排查DNS问题,我常用的工具就是这么几样:
| 工具 | 命令示例 | 适用场景 |
|---|---|---|
| nslookup | nslookup -debug example.com |
Windows和Linux通用,日常最快 |
| dig | dig @223.5.5.5 www.example.com +trace |
完整查看查询链路 |
| host | host -a example.com |
快速查看解析记录合集 |
| resolvectl | resolvectl query example.com |
systemd-resolved环境查系统解析 |
| ipconfig | ipconfig /flushdns / ipconfig /displaydns |
Windows清缓存、看缓存 |
| tcpdump | tcpdump -i eth0 port 53 |
抓DNS流量包,看请求是否发出 |
排查的通用顺序,我总结成一条固定的路:
- 先
nslookup目标域名,确认当前使用的服务器能不能解析。 - 再换一台递归服务器(比如
nslookup www.example.com 114.114.114.114),判断是不是原有DNS的问题。 - 判断是不是缓存污染:
flushdns后重试。 - 抓包看53端口有没有请求发出、有没有响应返回,确认到底是请求没出去还是响应没回来。
- 最后检查hosts文件和网卡配置,排除本地因素。
这套流程走下来,95%的DNS异常都能定位到一个环节。
5.4 几条实战口诀
经验多了以后,我把DNS排查压缩成了几句口诀:
- 先看本地,后看远端。hosts、网卡DNS配置、系统缓存永远是第一嫌疑对象。
- 换一台DNS验证一切。不要只盯着配置里那个DNS,换公共DNS立刻能区分"配置坏了"和"服务商坏了"。
- 判断解析结果对不对,不只是通不通。域名解析到错误的IP,照样能通,但网站是错的。用
dig对比多家DNS返回的IP,不一致就是有大问题。 - 不要忽略IPv6。很多"时好时坏"的奇怪故障,是IPv6 DNS设置异常引起的。如果不想排查IPv6,可以先在网卡上禁用IPv6测试,确定是否由它引发。
6. 写在最后:一点个人体会
把DNS全流程彻底搞懂,你会发现网络世界很多"玄学问题"瞬间就有了合理的解释。有一次我深夜处理一个客户报障,说是"网站间歇性打不开",远程排查了二十分钟都没头绪,最后用 dig +trace 一看,发现是上游权威服务器某条NS记录指向的IP已经失效,导致部分公共DNS刷新失败返回SERVFAIL。问题本身不复杂,但如果没有对解析链路的清晰认知,这种问题真的会让人无从下手。
最后再分享一个小技巧:改动任何DNS配置之前,先记录旧值。不管是Linux下的resolv.conf、Windows的网卡设置,还是域名服务商后台的解析记录,改动前截图或打印一下当前配置。DNS这类基础服务的特点是"改错不易察觉,恢复还特别麻烦",留好备份是你对同事和未来的自己最大的善意。
