Published on

域名解析的完整链条:从购买域名到访问网站

Authors
  • avatar
    Name
    Terry
    Twitter

引言

当你在浏览器输入 www.example.com 并按下回车,网页就神奇地显示出来了。这个看似简单的过程,背后其实经历了一系列复杂的步骤。今天我们就来拆解这个过程,看看一个域名是如何找到它对应的 IP 地址的。

第一步:购买域名

一切从购买域名开始。

1.1 选择域名注册商

域名注册商(Domain Registrar)是经过 ICANN(互联网名称与数字地址分配机构)认证的公司,常见的有:

  • GoDaddy
  • Namecheap
  • Cloudflare
  • 阿里云(万网)
  • 腾讯云

1.2 注册流程

假设你想注册 mysite.com

  1. 在注册商网站搜索域名是否可用
  2. 如果可用,支付年费(通常 $10-15/年)
  3. 填写域名所有者信息(WHOIS 信息)
  4. 完成注册

此时,你拥有了这个域名的使用权(通常是一年),但它还不能指向任何网站。

第二步:理解 DNS 系统

在配置域名之前,我们需要理解 DNS(Domain Name System)是什么。

2.1 DNS 的作用

DNS 就像互联网的电话簿,它的作用是:

域名(人类可读) → IP 地址(机器可读)
www.example.com93.184.216.34

2.2 DNS 的层级结构

DNS 是一个分层的系统:

.                          (根域名)
├── .com                   (顶级域名 TLD)
│   ├── example.com        (二级域名)
│   │   ├── www.example.com    (三级域名/子域名)
│   │   └── blog.example.com   (三级域名/子域名)
│   └── google.com
├── .org
└── .cn

第三步:配置 DNS 记录

购买域名后,你需要在域名注册商或 DNS 服务商那里配置 DNS 记录。

3.1 选择 DNS 服务商

你有两个选择:

  1. 使用注册商的 DNS 服务:大多数注册商提供免费的 DNS 服务
  2. 使用第三方 DNS 服务:如 Cloudflare、AWS Route 53、DNSPod

第三方 DNS 服务通常更快、更稳定,还提供额外功能(如 CDN、DDoS 防护)。

3.2 常见的 DNS 记录类型

A 记录(Address Record)

最基本的记录类型,将域名直接指向 IPv4 地址:

类型: A
名称: @(或留空,表示根域名)
: 76.76.21.21
TTL: 3600

A 记录必须指向 IP 地址,这里的 76.76.21.21 是什么?

  • 这是 Vercel 的负载均衡器 IP 地址
  • 当用户访问你的域名时,会直接连接到这个 IP
  • Vercel 在这个 IP 后面部署了多台服务器,通过负载均衡分发请求
  • 这个 IP 是 Vercel 专门为自定义域名提供的入口点

为什么不直接用你应用的真实 IP?

  1. 负载均衡:Vercel 有多台服务器,需要智能分发流量
  2. 高可用性:如果某台服务器故障,可以自动切换
  3. 全球 CDN:这个 IP 可能指向离用户最近的边缘节点
  4. 弹性扩容:后端服务器可以动态增减,不影响前端 IP

这意味着 mysite.com 指向 76.76.21.21

AAAA 记录

类似 A 记录,但指向 IPv6 地址:

类型: AAAA
名称: @
: 2001:0db8:85a3:0000:0000:8a2e:0370:7334
TTL: 3600

CNAME 记录(Canonical Name)

将域名指向另一个域名(别名):

类型: CNAME
名称: www
: cname.vercel-dns.com
TTL: 3600

CNAME 解析流程详解

当用户访问 www.mysite.com 时,DNS 解析过程是这样的:

  1. 第一次查询www.mysite.com → DNS 返回 cname.vercel-dns.com
  2. 第二次查询cname.vercel-dns.com → DNS 返回最终 IP 地址(如 76.76.21.21
  3. 建立连接:浏览器使用这个 IP 地址连接服务器

为什么 Vercel 使用 cname.vercel-dns.com

  1. 动态 IP 管理:Vercel 可以随时更改后端 IP,只需更新 cname.vercel-dns.com 的 A 记录
  2. 智能路由:根据用户地理位置返回不同的 IP(GeoDNS)
  3. 负载均衡:可以返回多个 IP 实现负载分担
  4. 故障转移:某个 IP 故障时,可以快速切换到备用 IP

CNAME vs A 记录的选择

  • A 记录:直接解析,速度快 1-2ms,但 IP 变化需要手动更新
  • CNAME:间接解析,多一次 DNS 查询,但 IP 变化时自动跟随

重要限制

  • CNAME 不能用于根域名(@
  • 一个域名只能有一个 CNAME 记录
  • CNAME 记录不能与其他记录类型共存

MX 记录(Mail Exchange)

指定邮件服务器:

类型: MX
名称: @
: mail.mysite.com
优先级: 10
TTL: 3600

TXT 记录

存储文本信息,常用于域名验证:

类型: TXT
名称: @
: "v=spf1 include:_spf.google.com ~all"
TTL: 3600

3.3 TTL(Time To Live)

TTL 是缓存时间,单位是秒:

  • 3600 = 1 小时
  • 86400 = 24 小时

TTL 越短,DNS 更新越快,但查询次数越多。

第四步:域名解析到访问的完整流程

让我们用你提到的具体例子,详细分析从域名解析到最终访问网站的完整过程。

4.0 配置示例分析

假设你的域名配置如下:

类型: A 
名称: @ 
: 76.76.21.21 
TTL: 3600

类型: CNAME
名称: www
: cname.vercel-dns.com
TTL: 3600

4.1 访问根域名的流程(example.com)

当用户在浏览器输入 example.com 时:

1. 浏览器发起 DNS 查询:example.com
2. DNS 服务器返回:A 记录 → 76.76.21.21
3. 浏览器直接连接到 76.76.21.21:443 (HTTPS)
4. Vercel 负载均衡器接收请求
5. 根据 Host 头(example.com)路由到对应的应用
6. 返回网页内容

关键点

  • 只需要 1 次 DNS 查询
  • 76.76.21.21 是 Vercel 的 入口 IP,不是你应用的真实服务器 IP
  • Vercel 在这个 IP 后面有多台服务器,通过内部负载均衡分发请求

4.2 访问 www 子域名的流程(www.example.com)

当用户访问 www.example.com 时:

1. 浏览器发起 DNS 查询:www.example.com
2. DNS 服务器返回:CNAME → cname.vercel-dns.com
3. 浏览器再次查询:cname.vercel-dns.com
4. DNS 服务器返回:A 记录 → 76.76.19.88 (可能与根域名不同)
5. 浏览器连接到 76.76.19.88:443
6. Vercel 负载均衡器接收请求
7. 根据 Host 头(www.example.com)路由到对应的应用
8. 返回网页内容

关键点

  • 需要 2 次 DNS 查询(CNAME + A 记录)
  • cname.vercel-dns.com 可能解析到不同的 IP,实现更灵活的负载均衡
  • Vercel 可以根据地理位置、服务器负载等因素动态返回最优 IP

4.3 为什么 Vercel 使用这种架构?

A 记录指向固定 IP(76.76.21.21)

  • 为根域名提供稳定的入口点
  • 满足 DNS 规范(根域名不能用 CNAME)
  • 提供基础的负载均衡能力

CNAME 指向动态域名(cname.vercel-dns.com)

  • 可以根据实时情况返回不同 IP
  • 支持 GeoDNS(地理位置路由)
  • 便于故障转移和扩容

4.4 关键问题:服务器如何知道访问的是哪个域名?

问题:如果多个域名(如 example.commyblog.comtest.com)都指向同一个 IP 76.76.21.21,服务器怎么知道用户访问的是哪个域名?

答案:通过 HTTP Host 头

4.5 HTTP 请求的完整过程

当用户在浏览器输入 example.com 时:

步骤 1:DNS 解析

用户输入: example.com
DNS 查询: example.com76.76.21.21

步骤 2:建立 TCP 连接

浏览器连接到: 76.76.21.21:443 (HTTPS)

步骤 3:发送 HTTP 请求(关键!)

GET / HTTP/1.1
Host: example.com          ← 这里!浏览器告诉服务器访问的域名
User-Agent: Mozilla/5.0...
Accept: text/html...

步骤 4:服务器处理请求

Vercel 负载均衡器接收请求
读取 Host: example.com
查找域名映射表:
  - example.com → project-abc123
  - myblog.com → project-def456  
  - test.com → project-ghi789
找到对应项目: project-abc123
转发到对应的应用服务器

4.6 Host 头的工作原理

同一个 IP,不同的域名

# 用户 A 访问 example.com
GET / HTTP/1.1
Host: example.com
→ 路由到项目 A

# 用户 B 访问 myblog.com  
GET / HTTP/1.1
Host: myblog.com
→ 路由到项目 B

# 用户 C 访问 test.com
GET / HTTP/1.1  
Host: test.com
→ 路由到项目 C

这就是虚拟主机(Virtual Host)的原理

  • 一个 IP 地址可以托管无数个网站
  • 服务器通过 Host 头区分不同的域名
  • 这是现代 Web 服务器的标准做法

4.7 Vercel 的域名路由系统

Vercel 内部维护一个域名映射表:

// Vercel 内部的域名映射(简化版)
const domainMapping = {
  'example.com': {
    projectId: 'prj_abc123',
    deploymentId: 'dpl_xyz789',
    serverPool: 'us-east-1'
  },
  'www.example.com': {
    projectId: 'prj_abc123',  // 同一个项目
    deploymentId: 'dpl_xyz789',
    serverPool: 'us-east-1'
  },
  'myblog.com': {
    projectId: 'prj_def456',
    deploymentId: 'dpl_uvw012',
    serverPool: 'eu-west-1'
  }
}

// 请求处理逻辑
function handleRequest(request) {
  const host = request.headers.host;  // 获取 Host 头
  const config = domainMapping[host];
  
  if (!config) {
    return '404 - Domain not found';
  }
  
  // 转发到对应的应用服务器
  return forwardToApp(config.projectId, request);
}

4.8 实际的网络包分析

让我们看看真实的 HTTP 请求:

访问 example.com 的请求

TCP 连接到 76.76.21.21:443
TLS 握手(SNI: example.com)
HTTP 请求:
   GET / HTTP/1.1
   Host: example.com
   User-Agent: Mozilla/5.0...
   
HTTP 响应:
   HTTP/1.1 200 OK
   Server: Vercel
   Content-Type: text/html
   
   <!DOCTYPE html>
   <html>...</html>

访问 myblog.com 的请求

TCP 连接到 76.76.21.21:443  (同一个 IP)
TLS 握手(SNI: myblog.com)
HTTP 请求:
   GET / HTTP/1.1
   Host: myblog.com           (不同的 Host 头!)
   User-Agent: Mozilla/5.0...
   
HTTP 响应:
   HTTP/1.1 200 OK
   Server: Vercel
   Content-Type: text/html
   
   <!DOCTYPE html>
   <html>...</html>          (完全不同的网站内容!)

4.9 为什么这样设计?

优势

  1. IP 地址节约:一个 IP 可以服务无数个域名
  2. 成本降低:不需要为每个域名分配独立 IP
  3. 负载均衡:可以在同一个负载均衡器后面部署多个应用
  4. 扩展性好:添加新域名不需要新的 IP 资源

技术要求

  • HTTP/1.1 协议必须包含 Host 头(RFC 2616)
  • HTTPS 需要 SNI(Server Name Indication)支持多证书
  • 服务器需要维护域名到应用的映射关系

这就是为什么

  • 你看到的 IP(76.76.21.21)不是你应用的真实 IP
  • 多个域名可以指向同一个 IP,通过 Host 头区分
  • Vercel 可以在不影响 DNS 的情况下,内部调整服务器部署
  • 现代 CDN 和云服务商都使用这种架构

4.10 如何验证 Host 头的工作?

你可以用命令行工具验证这个过程:

方法 1:使用 curl 测试不同域名

# 测试 example.com(假设都指向 76.76.21.21)
curl -H "Host: example.com" http://76.76.21.21

# 测试 myblog.com(同一个 IP,不同的 Host 头)
curl -H "Host: myblog.com" http://76.76.21.21

# 测试不存在的域名
curl -H "Host: nonexistent.com" http://76.76.21.21
# 可能返回 404 或默认页面

方法 2:查看实际的 HTTP 请求

# 使用 curl 显示完整的请求和响应
curl -v https://example.com

# 你会看到类似这样的输出:
# > GET / HTTP/1.1
# > Host: example.com          ← 这里是关键
# > User-Agent: curl/7.68.0
# > Accept: */*
# < HTTP/1.1 200 OK
# < server: Vercel             ← Vercel 的响应

方法 3:使用浏览器开发者工具

  1. 打开浏览器开发者工具(F12)
  2. 访问你的网站
  3. 查看 Network 标签
  4. 点击第一个请求,查看 Request Headers
  5. 找到 Host: your-domain.com

第五步:DNS 解析过程

现在我们来看 DNS 解析的技术细节。

5.1 完整的解析链条

假设用户访问 www.mysite.com

1. 浏览器缓存
    (未找到)
2. 操作系统缓存
    (未找到)
3. 本地 DNS 服务器(通常是 ISP 提供)
    (未找到)
4.DNS 服务器
    (返回 .comDNS 服务器地址)
5. 顶级域名服务器(.com)
    (返回 mysite.comDNS 服务器地址)
6. 权威 DNS 服务器(mysite.com)
    (返回最终的 IP 地址)
7. 返回给用户

5.2 递归查询 vs 迭代查询

递归查询:客户端只发一次请求,DNS 服务器负责完成所有查询工作。

用户 → 本地DNS → 根DNSTLD DNS → 权威DNS
                ← ← ← ← ← ← ← ← ← ← ← ← ←

迭代查询:DNS 服务器返回下一个应该查询的服务器地址,客户端自己继续查询。

用户 → 根DNS → 返回 TLD DNS 地址
用户 → TLD DNS → 返回权威 DNS 地址
用户 → 权威DNS → 返回 IP 地址

实际上,通常是递归+迭代的混合模式。

5.3 DNS 缓存

为了提高效率,DNS 查询结果会在多个层级缓存:

  1. 浏览器缓存:Chrome 缓存 60 秒
  2. 操作系统缓存:根据 TTL 设置
  3. 路由器缓存:家用路由器也会缓存
  4. ISP DNS 缓存:运营商的 DNS 服务器缓存

这就是为什么修改 DNS 记录后,不会立即生效的原因。

第六步:实战案例 - 部署 Next.js 应用到 Vercel

现在我们用一个真实案例,看看如何将域名指向 Next.js 应用。

6.1 场景描述

  • 你有一个域名:myblog.com
  • 你的 Next.js 应用部署在 Vercel 上
  • Vercel 给你分配了一个默认域名:myblog.vercel.app

6.2 配置步骤

步骤 1:在 Vercel 添加自定义域名

  1. 进入 Vercel 项目设置
  2. 点击 "Domains"
  3. 输入 myblog.comwww.myblog.com
  4. Vercel 会提示你需要配置的 DNS 记录

步骤 2:配置 DNS 记录

在你的 DNS 服务商(如 Cloudflare)添加以下记录:

方案 A:使用 A 记录(推荐用于根域名)

类型: A
名称: @
: 76.76.21.21
TTL: 3600

类型: CNAME
名称: www
: cname.vercel-dns.com
TTL: 3600

方案 B:使用 CNAME(仅适用于子域名)

类型: CNAME
名称: www
: myblog.vercel.app
TTL: 3600

注意:根域名(@)不能使用 CNAME,必须使用 A 记录。

步骤 3:等待 DNS 传播

DNS 记录更新后,需要等待传播:

  • 最快:几分钟
  • 通常:1-2 小时
  • 最慢:24-48 小时(极少见)

6.3 验证 DNS 配置

使用命令行工具验证:

# 查询 A 记录
dig myblog.com

# 查询 CNAME 记录
dig www.myblog.com

# 使用特定 DNS 服务器查询
dig @8.8.8.8 myblog.com

或者使用在线工具:

第七步:HTTPS 证书

配置好 DNS 后,还需要 HTTPS 证书。

7.1 Let's Encrypt

Vercel 会自动为你的域名申请免费的 Let's Encrypt 证书:

  1. DNS 记录生效后
  2. Vercel 自动向 Let's Encrypt 申请证书
  3. 证书自动续期

7.2 证书验证方式

Let's Encrypt 使用 DNS 验证或 HTTP 验证:

  • DNS 验证:在 DNS 中添加 TXT 记录
  • HTTP 验证:在网站根目录放置验证文件

Vercel 通常使用 HTTP 验证,所以你不需要手动操作。

第八步:高级配置

8.1 使用 Cloudflare 作为 CDN

如果你使用 Cloudflare:

  1. 将域名的 Nameserver 改为 Cloudflare 的
  2. 在 Cloudflare 添加 DNS 记录
  3. 开启 "Proxied" 模式(橙色云朵)

此时的解析链条变成:

用户 → Cloudflare CDNVercel 服务器

8.2 多区域部署

对于全球用户,可以使用 GeoDNS:

类型: A
名称: @
: 192.0.2.1 (美国服务器)
地理位置: 北美

类型: A
名称: @
: 198.51.100.1 (欧洲服务器)
地理位置: 欧洲

用户会自动连接到最近的服务器。

8.3 负载均衡

使用多个 A 记录实现简单的负载均衡:

类型: A
名称: @
: 192.0.2.1
TTL: 60

类型: A
名称: @
: 192.0.2.2
TTL: 60

DNS 会轮询返回不同的 IP 地址。

常见问题

Q1: 为什么 DNS 修改后没有立即生效?

因为 DNS 缓存。解决方法:

  • 等待 TTL 时间过期
  • 清除本地 DNS 缓存:ipconfig /flushdns(Windows)或 sudo dscacheutil -flushcache(Mac)
  • 使用隐私模式浏览器测试

Q2: A 记录和 CNAME 有什么区别?

  • A 记录:直接指向 IP 地址,速度快,但 IP 变化时需要手动更新
  • CNAME:指向另一个域名,IP 变化时自动跟随,但多一次 DNS 查询

Q3: 为什么根域名不能使用 CNAME?

因为 DNS 规范(RFC 1034)规定,如果一个域名有 CNAME 记录,就不能有其他记录(如 MX、TXT)。而根域名通常需要 MX 记录(邮件)和其他记录。

Q4: 如何加速 DNS 解析?

  1. 使用更快的 DNS 服务商(如 Cloudflare 1.1.1.1、Google 8.8.8.8)
  2. 减少 DNS 查询次数(减少外部资源)
  3. 使用 DNS 预解析:<link rel="dns-prefetch" href="//example.com">
  4. 适当增加 TTL 值

总结

域名解析的完整链条:

  1. 购买域名 → 从注册商获得域名使用权
  2. 配置 DNS → 添加 A/CNAME 等记录
  3. DNS 查询 → 浏览器通过多级 DNS 服务器查询 IP
  4. 建立连接 → 使用 IP 地址连接到服务器
  5. HTTPS 握手 → 验证证书,建立加密连接
  6. 传输数据 → 下载网页内容

整个过程看似复杂,但实际上只需要几百毫秒。理解这个过程,可以帮助你:

  • 更好地配置域名和 DNS
  • 排查网站访问问题
  • 优化网站性能
  • 理解互联网的基础设施

希望这篇文章能帮助你理解域名解析的全过程。如果你有任何问题,欢迎在评论区讨论。

参考资料