HTTP 域名解析一文吃透:从 DNS 到首包的完整路径(含排查清单)
本文从“输入域名到首包”完整拆解解析链路:系统 Resolver → 递归/权威 DNS → A/AAAA/CNAME/ALIAS → CDN CNAME 链 → TCP/TLS(SNI)/HTTP(含 HTTP/3/QUIC)。给出常用记录与 TTL 配置建议、浏览器 dns-prefetch/preconnect 优化、以及故障速查(NXDOMAIN/SERVFAIL/证书不匹配/根域不能 C
·
HTTP 域名解析一文吃透:从 DNS 到首包的完整路径(含排查清单)
目标:讲清楚“浏览器输入域名到拿到页面”的解析细节与常见坑,给可复制的命令与排查步骤。
读完可以:独立配置记录(A/AAAA/CNAME…)、理解 CDN/CNAME 链、定位 404/证书不匹配/“能 ping 不能开” 等问题。
文章目录
- HTTP 域名解析一文吃透:从 DNS 到首包的完整路径(含排查清单)
-
文章目录
- HTTP 域名解析一文吃透:从 DNS 到首包的完整路径(含排查清单)
0. 先把链路说清楚(HTTP 并不负责解析)
- 浏览器/客户端调用系统的 Resolver(如
getaddrinfo()
)发起 DNS 查询 - 递归解析器(本地 DNS/公共 DNS)解析域名 → 返回 IP(A/AAAA/CNAME…)
- 客户端基于返回的 IP 建立连接:
http://
:TCP 3 次握手 → 发送 HTTP/1.1 请求(带Host
头)https://
:TCP → TLS 握手(SNI 告诉服务器要哪个证书)→ 发起 HTTPh3://
(HTTP/3):QUIC/UDP 443 + TLS 1.3
- 服务器返回首包;后续可能走 HTTP/2 多路复用或 HTTP/3 0-RTT
关键词:DNS 只负责域名→IP;Host 头决定虚拟主机;SNI 决定 HTTPS 证书;HTTP/3 走 UDP。
1. 你要会配的记录类型与场景
类型 | 作用 | 场景/注意 |
---|---|---|
A | 域名 → IPv4 | 最常用 |
AAAA | 域名 → IPv6 | 推荐同时配置,配合 Happy Eyeballs 加快首包 |
CNAME | 别名 → 另一个域名 | 根域名不可 CNAME;CDN 常用(www 指向 xxx.cdn.com ) |
ALIAS/ANAME | 顶级域 CNAME 替代(DNS 提供商扩展) | 在 根域名使用 CDN 时选它 |
NS | 指定权威 DNS | 顶级域注册后需要在注册商设置 NS |
SOA | 授权信息/序列号 | 运维用 |
TXT | 文本/验证 | 域名验证、SPF、DKIM |
MX | 邮件 | 邮件相关 |
SRV/CAA | 服务定位/证书颁发限制 | 视业务需要 |
TTL(生存时间):
- 变更频繁的记录(灰度/切流)用 300–600s;稳定业务 1–4h。
- TTL 不是“全球传播时间”,而是每级缓存的有效期。
2. CDN 与 CNAME 链怎么跑
- 你的业务域名(如
www.example.com
)通常 CNAME 到 CDN 分配的域名(如abc.cdn.com
)。 - 递归解析器解析 CNAME 继续查下去直到 A/AAAA;CDN 据就近/负载返回边缘 IP(多用 Anycast)。
- 浏览器连到边缘节点,节点再回源到你服务器(按 CDN 的“源站配置”)。
常见坑
- 根域名不能设 CNAME → 用 ALIAS/ANAME 或让 CDN 提供“根域方案”。
- HTTPS 证书:域名接入 CDN 后,CDN 与源站都需要证书(视代理/回源方式)。
- CNAME 链太长导致解析慢 → 尽量控制在 1–2 跳。
3. 浏览器端优化(能省一次解析算一次)
- DNS 预解析:
<link rel="dns-prefetch" href="//static.example.com">
- 预连接(更激进,会建 TCP/TLS):
<link rel="preconnect" href="https://static.example.com" crossorigin>
- 多域名合并到同证书 + 同 IP:HTTP/2/3 下可减少连接数(注意证书 SAN 覆盖)。
4. 实操:5 步定位“域名打不开/很慢/证书错”
下面命令 macOS/Linux 可用;Windows 可装
dig
(BIND)或用nslookup
。
4.1 先看解析结果与链路
# 1) 当前递归解析器的查询
dig www.example.com +nocmd +noall +answer
# 2) 看 CNAME 链与 TTL
dig www.example.com +trace
# 3) 指定权威 NS 直接问(排除递归器问题)
dig @ns1.domain-dns.com www.example.com
# 4) 同时看 IPv6
dig AAAA www.example.com
4.2 建连与证书(HTTP/TLS)
# HTTP:带上 Host,排除反代/网关影响
curl -v http://www.example.com/ -H 'Host: www.example.com'
# HTTPS:看 SNI 告诉了谁、证书是否匹配域名
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
4.3 本机 DNS 缓存与 hosts
- 临时指向灰度机器:编辑
hosts
- Windows:
C:\Windows\System32\drivers\etc\hosts
- macOS/Linux:
/etc/hosts
- Windows:
- 清缓存
- Windows:
ipconfig /flushdns
- macOS:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
- systemd:
resolvectl flush-caches
或systemd-resolve --flush-caches
- Windows:
4.4 递归器与链路
- 公司/家庭网关可能劫持或无 ECS,换公共 DNS 试试(1.1.1.1 / 8.8.8.8 / 114 / 阿里…)。
traceroute
/mtr
观察到边缘节点的路由是否绕远。
4.5 常见返回码
NXDOMAIN
:记录不存在(看看是否拼错/还未生效/解析层级缺 NS)。SERVFAIL
:上游出错;权威 DNS 故障/配置有误。REFUSED
:拒绝查询;可能未开放外网递归。
5. 系统解析链与优先级(理解“能 ping 不能开”)
- 客户端先走 系统解析器(
/etc/nsswitch.conf
决定顺序),再访问/etc/hosts
、resolv.conf
指定的递归器(很多系统是本地 127.0.0.53 的 stub,再转发出去)。 - 浏览器拿到 多个 A/AAAA 会并发连(Happy Eyeballs),优先最快的;所以“能 ping 不能开”常是 TCP/443 被拦 或 证书/SNI 错,不是 DNS 问题。
6. 业务侧配置建议
- 分环境的子域名:
api.dev.example.com
、api.stg…
、api…
;不同 TTL。 - 灰度/回滚:提前把备用机器加入记录池(低权重/备用 CNAME),切流只改权重或指向。
- IPv6 提前打通:同时配 AAAA,确认负载/防火墙放行 443/80/UDP 443。
- DNSSEC(可选):高安全场景开启,避免投毒(注意链路完整性与维护成本)。
- 监控:定时
dig +trace
、首包时延、解析可用性;报警包含 权威 NS 状态。
7. 典型问题与速解
现象 | 可能原因 | 快速定位 | 解决 |
---|---|---|---|
刚改记录,外网还指向旧 IP | TTL 未过期/上游缓存 | dig 看 TTL;换公共 DNS 交叉验证 |
等 TTL、降 TTL 再变更 |
只能打开 http:// ,https:// 报证书错 |
SNI 对不上/证书未覆盖域名 | openssl s_client -servername |
重新签发证书或修 SNI/反代配置 |
根域接 CDN 失败 | 根域不能 CNAME | dig 看类型 |
用 ALIAS/ANAME 或让 CDN 提供根域方案 |
海外很慢 | Anycast/BGP/回源地域不合适 | mtr 、CDN 控制台 |
切 CDN 线路或设回源就近 |
IPv6 打不开 | 只配 AAAA 未开放 443/QUIC | curl -6 -v 、nmap -6 |
放通防火墙/监听 IPv6 |
8. 一键小脚本(Linux/macOS)
# dnscheck.sh 用法:./dnscheck.sh www.example.com
set -e
domain="$1"
echo "== dig answer =="
dig +nocmd +noall +answer "$domain" || true
echo
echo "== trace =="
dig +trace "$domain" | sed -n '1,60p'
echo
echo "== v4/v6 =="
dig A "$domain" +short; dig AAAA "$domain" +short
echo
echo "== HTTPS cert (SNI) =="
openssl s_client -connect "$domain:443" -servername "$domain" < /dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates || echo "no tls"
9. 代码示例:在应用里正确“解析并建连”
Node.js:dns.lookup
(尊重系统策略) vs dns.resolve4/6
(直接查)
// npm run node index.js
const dns = require('dns').promises;
const net = require('net');
(async () => {
const host = 'www.example.com';
// 1) 系统策略(含 /etc/hosts、v4/v6 优先级、Happy Eyeballs)
const addr = await dns.lookup(host, { all: true });
console.log('lookup(all):', addr);
// 2) 直接查权威结果(不走系统优先级)
const [a4, a6] = await Promise.allSettled([dns.resolve4(host), dns.resolve6(host)]);
console.log('resolve4:', a4.status === 'fulfilled' ? a4.value : []);
console.log('resolve6:', a6.status === 'fulfilled' ? a6.value : []);
// 3) 简单建连测试
const ip = (addr[0] || {}).address;
if (ip) {
const s = net.createConnection(80, ip, () => {
console.log('tcp connected to', ip);
s.end();
});
s.setTimeout(3000, () => { s.destroy(); console.error('timeout'); });
}
})();
Python:socket.getaddrinfo
(系统解析)
# python3 demo.py
import socket
host = "www.example.com"
infos = socket.getaddrinfo(host, 80, type=socket.SOCK_STREAM)
print("getaddrinfo:", infos[:3]) # 只打印前几个
生产里尽量用 系统解析(
lookup/getaddrinfo
),以遵循公司内网 DNS/hosts/缓存策略。
10. 备案/内外网双线/分裂视图(Split-Horizon)
- 内外网返回不同 IP(同一域名):常见于企业内网、K8s 集群 DNS、专线接入。
- 排查时要明确:你现在连的是哪个递归器(
/etc/resolv.conf
/网络配置),并分别在内外网测dig
。
11. Checklist(上线前最后确认)
- A 与 AAAA 都可用;HTTP/3 需要 UDP 443
- CDN CNAME 链长度 ≤2;根域使用 ALIAS/ANAME
- 证书覆盖全部域名(含
www
/根域),SNI 配置正确 - TTL 计划妥当:变更期 300s,稳定后 ≥3600s
- 监控:解析可用性、首包时延、证书到期告警
- 文档化:权威 NS、变更流程、回滚方案
结语
域名解析不是“神秘的黑盒”。只要牢记 “DNS 把名字变成 IP,HTTP/HTTPS 再承担传输” 这条主线,加上上面的命令组合拳与配置策略,你就能把 80% 的解析相关问题在几分钟内定位清楚、在几小时内无损回滚。
更多推荐
所有评论(0)