DNS:互联网的"电话簿"是怎么进化来的
没有 DNS 的年代:hosts 文件的痛
TCP/IP 通信靠的是 IP 地址 + 端口号 。但 IP 地址是一串数字,人记不住。于是早期人们用 hosts 文件 来维护"主机名 → IP"的映射。
用户输入 host-a,计算机查 hosts 文件,发现它对应 172.20.2.1,然后才去通信。
问题在哪?最初这个 hosts 文件由 SRI-NIC 统一管理。每台新计算机入网、每个 IP 变更,都得去信息中心申请更新;其他计算机还要定期下载新版 hosts 文件。 这就像全公司共用一本电话簿,每来一个新同事,所有人都得重新打印一本------根本不可持续。
DNS 的诞生就是为了解决这个"集中管理"的瓶颈:把域名解析的权力下放,由各个组织自己维护自己域内的映射关系,用户查询时自动去问 DNS 服务器。
但 hosts 文件并没有消失。 你的电脑上至今仍然保留着它,而且在域名解析时,hosts 文件的优先级高于 DNS 查询。
域名的层级结构:从右往左读
以 www.baidu.com 为例:
| 部分 | 名称 | 含义 |
|---|---|---|
com |
一级域名(顶级域) | 表示企业类域名,同级的还有 net、org、cn 等 |
baidu |
二级域名 | 公司名,通常由企业自己管理和注册 |
www |
三级域名/主机名 | 习惯用法,早期用来表示"这个主机提供 Web 服务" |
域名的层级是从右向左 逐级细化的。根服务器在最右边(通常省略不写,表现为末尾的点),往下依次是顶级域、二级域、三级域......越往右,管理权限越高;越往左,越接近具体的某台机器。
域名解析的完整过程
拆成两条主线来理解:
主线一:客户端 → 本地 DNS 服务器(递归查询)
你电脑上的"DNS 客户端"并不直接去问根服务器。它只做一件事:向本地 DNS 服务器(通常是运营商提供的,比如电信/移动的 DNS,或者你手动设的 8.8.8.8)发出请求,然后等着最终答案。 这叫递归查询------我托你办这件事,你负责给我最终结果,中间你跑了哪些地方我不管。
主线二:本地 DNS 服务器 → 各级 DNS 服务器(迭代查询)
本地 DNS 服务器拿到 www.baidu.com 的查询后,如果自己的缓存里没有,就开始"层层问路":
-
问根服务器 :"
.com谁管?" 根服务器不直接给百度 IP,而是回答:".com顶级域服务器地址是 xxx,你去问它。" -
问
.com服务器 :"baidu.com谁管?".com服务器同样不直接给答案,而是说:"baidu.com的权威服务器地址是 xxx,你去问它。" -
问
baidu.com权威服务器 :"www.baidu.com的 IP 是多少?" 这次终于拿到了最终答案。
这个过程叫迭代查询------每次问一个人,他要么给你答案,要么告诉你"下一个该问谁",你自己接着跑。
拿到答案后 ,本地 DNS 服务器把 IP 返回给你的电脑,同时把这条记录缓存起来 。下次再有人问 www.baidu.com,只要缓存没过期,直接返回,不用再跑一遍全程。
用 dig 看 DNS 到底返回了什么
;; ANSWER SECTION:
www.baidu.com. 1057 IN CNAME www.a.shifen.com.
www.a.shifen.com. 40 IN A 115.239.210.27
www.a.shifen.com. 40 IN A 115.239.211.112
注意这里有两步:www.baidu.com 先被解析成一个别名(CNAME) www.a.shifen.com,然后 www.a.shifen.com 才被解析成两个 IP 地址。这是百度用 CDN 的常见做法------同一个域名背后可能对应多个 IP,就近分配。
status: NOERROR 表示查询成功。SERVER: 100.100.2.136#53 告诉你这次是谁回答的(阿里云的公共 DNS)。如果你看到 status 不是 NOERROR,那就要排查是不是域名不存在、DNS 服务器拒绝响应等问题了。
浏览器输入 URL 后,DNS 只是第一步
"浏览器输入 URL 后发生了什么"。DNS 解析只是整个链条的前置环节。简单串一下:
-
浏览器查自己的 DNS 缓存(有没有刚访问过这个域名?)
-
查操作系统缓存 / hosts 文件
-
发起 DNS 查询(就是上面讲的递归 + 迭代)
-
拿到 IP 后,建立 TCP 连接(三次握手;如果是 HTTPS,还要 TLS 握手)
-
发送 HTTP 请求
-
服务器处理并返回响应
-
浏览器解析 HTML、加载资源、渲染页面
DNS 之所以重要,是因为如果第一步卡住了,后面所有事都无从谈起。这也是为什么 DNS 故障往往表现为"网页打不开但 QQ 能上"------QQ 可能已经缓存了服务器 IP,而浏览器需要重新解析域名。
ICMP:IP 协议的"通讯员"
为什么需要 ICMP
IP 协议的设计哲学是 "尽力而为" :它只管把数据包往目的地扔,不保证送到,也不保证按顺序到达。如果中途路由器发现"下一跳网络不可达",或者目标主机电源关了,IP 协议本身不会通知发送方。
这就像你寄了一封信,邮局发现地址写错了,直接把信销毁,不会退回来告诉你哪里错了 。ICMP 就是那个退信通知单:当 IP 包出问题时,路由器或目标主机用 ICMP 报文告诉发送方"包没送到,原因是 XXX"。
关键理解 :ICMP 虽然是网络层协议(和 IP 一起工作),但它不是传输层协议 。TCP/UDP 才有端口号的概念,ICMP 根本不关心端口 。所以那个面试陷阱------"ping 走哪个端口?"------答案是:ping 不走端口,它基于 ICMP,在网络层。
ICMP 报文的分类
ICMP 报文分成两大类:
差错报告类(通知出了什么问题)
| 类型值 | 名称 | 典型场景 |
|---|---|---|
| 3 | 目标不可达(Destination Unreachable) | 网络/主机/协议/端口不可达 |
| 11 | 超时(Time Exceeded) | TTL 减到 0,包被丢弃 |
| 5 | 重定向(Redirect) | 告诉发送方"下次走另一个路由器更快" |
| 4 | 源点抑制(Source Quench) | 拥塞控制(已废弃,现代网络很少用) |
查询/诊断类(主动探测网络状态)
| 类型值 | 名称 | 用途 |
|---|---|---|
| 8 / 0 | 回送请求 / 回送应答(Echo Request / Reply) | ping 的核心 |
| 13 / 14 | 时间戳请求 / 应答 | 测量时间同步 |
| 17 / 18 | 地址掩码请求 / 应答 | 获取子网掩码(早期使用) |
ping:最熟悉的 ICMP 工具
ping www.baidu.com 做的事情极其简单:
-
先通过 DNS 把
www.baidu.com解析成 IP(ping 的是域名,不是 URL)。 -
向目标 IP 发送 ICMP Echo Request(类型 8)。
-
目标主机收到后,返回 ICMP Echo Reply(类型 0)。
-
ping 统计往返时间(RTT)和丢包率。
ping 能通说明什么? 说明你的机器到目标 IP 的网络层路径是通的 ,目标主机也开机并响应 ICMP。但 ping 通不代表服务可用------比如目标主机的 Web 服务挂了,但机器还活着,ping 照样通。
traceroute:利用 TTL 的"路痴导航"
traceroute(Windows 下叫 tracert)是一个网络诊断工具 ,用来追踪你的电脑到目标主机之间,数据包经过了哪些路由器,以及每一跳的延迟是多少。
你可以把它理解成:给数据包装了一个"行程记录仪",看它从你家到目标服务器,中途经过了哪些"驿站"。
它解决什么问题?
假设你访问某个网站很慢,ping 显示延迟很高,但你不知道是你家路由器的问题 、运营商骨干网的问题 ,还是目标服务器机房的问题 。traceroute 能帮你把路径一段一段拆开,定位到底是哪一跳开始变慢或丢包。
你的电脑 → 家用路由器 → 运营商网关 → 城域网 → 骨干网 → 目标机房 → 目标服务器
跳1 跳2 跳3 跳4 跳5 跳6
traceroute 就是把上面这条链路上的每一个节点 IP 和响应时间列出来。
它是怎么做到的?(核心原理:利用 TTL)
traceroute 的巧妙之处在于利用了 IP 包头里的 TTL 字段。
TTL(Time To Live,生存时间) 的规则是:数据包每经过一个路由器,TTL 减 1;当 TTL 减到 0 时,路由器丢弃这个包,并返回一个 ICMP 超时报文(Type 11,Time Exceeded)给发送方。
traceroute 就是故意利用这个"报错"来探测路径:
| 步骤 | 发送的包 | 发生了什么 | traceroute 学到什么 |
|---|---|---|---|
| 第1步 | TTL = 1 的探测包 | 到达第1个路由器,TTL 减为 0,路由器丢弃并返回 ICMP 超时 | 第1跳的 IP 和往返时间 |
| 第2步 | TTL = 2 的探测包 | 经过第1个路由器(TTL→1),到达第2个路由器(TTL→0),第2个路由器返回 ICMP 超时 | 第2跳的 IP 和往返时间 |
| 第3步 | TTL = 3 的探测包 | 依次类推,到达第3个路由器时 TTL 归零,返回超时 | 第3跳的 IP |
| ... | ... | ... | ... |
| 最后一步 | TTL 足够大 | 包到达目标主机 ,目标主机不会返回"超时",而是返回 ICMP Port Unreachable (传统 UDP 模式)或 Echo Reply(ICMP 模式) | 到达终点,停止探测 |
一句话总结 :traceroute 通过逐步增大 TTL ,让路径上的每一跳依次"暴露"自己------每一跳都以为自己是因为 TTL 耗尽才丢包的,于是老老实实把 ICMP 超时报文发回来,traceroute 就记录下这一跳的 IP。
原理讲的是"怎么找出每一跳的 IP",可我要的是"哪一跳开始变慢/丢包",这俩是怎么挂上钩的?
答案就在 traceroute 的输出格式 里:它不只是记录 IP,它给每一跳都发了多个探测包,并记录每个包的往返时间(RTT)和有没有收到回复。 这两个数据,就是判断"慢"和"丢"的依据。
怎么判断"哪一跳开始变慢"
核心方法:沿着跳数从上往下看,找延迟"台阶式跃升"的那个位置。
比如:
1 192.168.1.1 1 ms 1 ms 1 ms
2 10.0.0.1 3 ms 2 ms 3 ms
3 202.97.1.1 15 ms 14 ms 16 ms
4 202.97.2.1 16 ms 15 ms 17 ms
5 61.135.1.1 180 ms 182 ms 179 ms ← 延迟突然从 16ms 跳到 180ms
6 61.135.2.1 181 ms 180 ms 183 ms
7 61.135.169.121 182 ms 181 ms 180 ms ← 目标
解读 :第 4 跳还是 16ms,第 5 跳突然变成 180ms,并且后面每一跳都维持在高位 。这说明瓶颈出现在第 4 跳到第 5 跳之间的链路(很可能是第 5 跳路由器所在的网络或它上游的链路拥塞/绕路)。
注意两个坑:
-
不能只看单独一跳的延迟 。如果第 5 跳显示 180ms,但第 6 跳又回到 20ms,那第 5 跳的高延迟很可能只是它自己回 ICMP 报文的 CPU 处理慢 (路由器处理"报错信"是低优先级任务),不代表数据转发慢 。要看从哪一跳开始"持续"高。
-
延迟要结合地理距离看 。国内到美国 150ms 是正常的,国内城际 10ms 才是正常。单纯一个数字没意义,要看跳变。
怎么判断"哪一跳开始丢包"
看 * 出现的位置,以及后续跳是否恢复。
情况 A:中间某跳 * * *,但后面跳正常
3 202.97.1.1 15 ms 14 ms 16 ms
4 * * *
5 61.135.1.1 18 ms 17 ms 19 ms
6 61.135.169.121 20 ms 19 ms 18 ms
解读 :第 4 跳不回复,但第 5、6 跳都正常回复。这说明路径是通的 ,只是第 4 跳那台路由器不响应 ICMP 超时报文 (安全策略/限速)。这不叫丢包,叫"沉默的路由器"。数据包实际上顺利穿过了它,否则后面的跳不可能有回复。
情况 B:从某一跳开始,后面全部 * * *
3 202.97.1.1 15 ms 14 ms 16 ms
4 202.97.2.1 16 ms 15 ms *
5 * * *
6 * * *
7 * * *
解读 :第 4 跳开始出现 *,之后再也没有任何一跳回复 ,连目标都没到达。这说明问题出在第 4 跳之后 ------要么第 4 跳到第 5 跳的链路断了,要么第 5 跳及之后的路由器全部静默(概率低),要么目标主机不可达。结合 ping 一起看 :如果 ping 目标也不通,那基本可以断定从第 4 跳往后就断了。
情况 C:目标跳 * * *,但前面都正常
5 61.135.1.1 18 ms 17 ms 19 ms
6 * * *
解读 :能到达第 5 跳,但目标主机不回复 。常见原因:目标主机关了/防火墙禁止 ICMP/目标主机只响应 TCP。这时候 traceroute 看不到终点,不代表网络不通 ,可能只是目标不搭理 ICMP。用 tcptraceroute 或直接 telnet 目标IP 端口 验证更准。
关键注意事项(避免误判)
延迟高 ≠ 这一跳有问题
路由器处理 ICMP 超时报文本身是低优先级的 ,CPU 忙的时候回复慢,所以某一跳显示 200ms 可能只是它"回信慢",实际转发数据包并不慢。要看从哪一跳开始"持续"变慢,而不是单看某一跳的数值。
* * * 后恢复正常是常见现象
很多骨干路由器不响应 ICMP,但后续跳正常返回,说明路径没问题,只是中间有"沉默的路由器"。
路径可能不对称
去程和回程走的路由器可能完全不同。traceroute 只测去程(以及回程的 ICMP 报文路径),所以看到的是单向路径。
不同系统的默认探测方式不同
-
Linux
traceroute:默认用 UDP 高端口探测(目标返回 Port Unreachable 作为终点标志); -
Windows
tracert:默认用 ICMP Echo Request(和 ping 一样); -
还有 TCP traceroute (如
tcptraceroute),用 TCP SYN 探测,能绕过 ICMP 被禁用的防火墙,穿透性更好。
和 ping 的关系
| ping | traceroute | |
|---|---|---|
| 目的 | 测试到目标是否通、延迟多少 | 测试路径上每一跳的情况 |
| 协议 | ICMP Echo Request/Reply | ICMP 超时报文(+ UDP/ICMP/TCP 探测) |
| 回答的问题 | "能不能到?多快?" | "经过了谁?在哪一跳出问题?" |
| 典型用法 | 先 ping 确认通不通 | ping 不通或延迟高时,用 traceroute 定位断在哪 |
实战顺序通常是 :先 ping 目标 → 不通或很慢 → 再 traceroute 看卡在哪一跳 → 判断是本地网络、运营商还是目标机房的问题。