DNS

返回 计算机网络

DNS(Domain Name System)是互联网的”地址簿”,将人类可读的域名解析为 IP 地址,同时承载邮件路由、服务发现、安全验证等功能。


DNS 层级结构

.(根域,Root)
├── com(顶级域 TLD)
│   ├── example.com(二级域 SLD,注册域)
│   │   ├── www.example.com(子域)
│   │   └── mail.example.com
│   └── google.com
├── org
├── cn(国家代码 TLD)
│   └── baidu.com.cn
└── (约 1500+ 个 TLD)

域名实际上是倒着读的:www.example.com 完整写法是 www.example.com.(末尾有根点)

DNS 服务器角色

角色说明
根域名服务器13 组(A~M),全球 1000+ 节点(Anycast),知道所有 TLD 服务器地址
TLD 服务器管理 .com/.cn 等,知道该 TLD 下所有注册域的权威 NS
权威 DNS 服务器存储域名的实际记录(A/CNAME/MX 等),由域名所有者管理
递归解析器(Resolver)代替客户端完成完整查询,有缓存(ISP 提供或 8.8.8.8/1.1.1.1)

DNS 完整解析流程

浏览器输入 www.example.com:

① 浏览器缓存(有效期约 1 分钟)
② 操作系统缓存 + /etc/hosts 文件
③ 本地递归解析器(路由器/ISP/8.8.8.8)有缓存直接返回

④ 递归解析器向根服务器迭代查询:
   Resolver ──► 根服务器:".com 的 NS 在哪?"
   根服务器 ──► "去问 a.gtld-servers.net"

⑤ Resolver ──► .com TLD 服务器:"example.com 的 NS 在哪?"
   TLD 服务器 ──► "去问 ns1.example.com"(权威 NS)

⑥ Resolver ──► ns1.example.com:"www.example.com 的 A 记录?"
   权威 ──► "93.184.216.34,TTL=3600"

⑦ Resolver 缓存并返回给客户端
   客户端建立 TCP 连接到 93.184.216.34

递归 vs 迭代

模式发起方说明
递归查询客户端 → Resolver客户端问 Resolver,Resolver 帮你一路查到底并返回最终结果
迭代查询Resolver → 各权威服务器Resolver 每次只得到”去问谁”的指引,自己逐步查询

DNS 记录类型

常用记录

类型说明示例
A域名 → IPv4example.com. 3600 IN A 93.184.216.34
AAAA域名 → IPv6example.com. 3600 IN AAAA 2001:db8::1
CNAME别名 → 另一个域名www CNAME example.com.
MX邮件服务器(含优先级)example.com. MX 10 mail.example.com.
TXT任意文本SPF、DKIM、域名验证、Google Site Verify
NS权威 DNS 服务器example.com. NS ns1.example.com.
PTRIP → 域名(反向解析)34.216.184.93.in-addr.arpa. PTR example.com.

进阶记录

类型说明
SOA区域权威信息(序号、刷新间隔、重试、过期、否定缓存 TTL)
SRV服务发现,指定主机 + 端口 + 优先级(Kubernetes、SIP、XMPP 使用)
CAA授权哪些 CA 可以颁发此域名的证书(防止错误签发)
HTTPS / SVCBHTTPS 连接参数(端口、ECH 密钥、ALPN),HTTP/3 发现依赖此记录
DNSKEYDNSSEC 公钥
DS子区域 DNSKEY 的摘要,用于建立信任链
RRSIG资源记录的数字签名(DNSSEC)

区域文件格式(Zone File)

; example.com 区域文件
$ORIGIN example.com.
$TTL    86400
 
@    IN  SOA  ns1.example.com.  admin.example.com. (
              2024010101  ; 序号(Serial)
              3600        ; 刷新(Refresh)
              900         ; 重试(Retry)
              604800      ; 过期(Expire)
              300 )       ; 否定缓存 TTL(Negative TTL)
 
; NS 记录
     IN  NS   ns1.example.com.
     IN  NS   ns2.example.com.
 
; A 记录
@    IN  A    93.184.216.34
www  IN  A    93.184.216.34
api  IN  A    10.0.0.100
 
; CNAME
blog IN  CNAME  www.example.com.
 
; MX 记录(优先级 10 < 20,越小越优先)
@    IN  MX  10  mail1.example.com.
@    IN  MX  20  mail2.example.com.
 
; SRV(_service._proto.domain 优先级 权重 端口 目标)
_https._tcp  IN  SRV  0 5 443  www.example.com.
 
; TXT(SPF 邮件防伪造)
@    IN  TXT  "v=spf1 mx ~all"
 
; CAA(只允许 Let's Encrypt 签发证书)
@    IN  CAA  0 issue "letsencrypt.org"

TTL 与缓存策略

  • TTL 大(3600~86400s):缓存时间长,减少查询,改动传播慢(等待旧缓存过期)
  • TTL 小(60~300s):改动快速生效,但查询频率高,权威服务器压力大

域名迁移 TTL 策略

迁移前 2 天:将 TTL 从 86400 → 300(让旧缓存快速过期)
迁移当天:   修改 A 记录指向新 IP
迁移后 2 天:将 TTL 改回 86400

否定缓存(Negative Caching)

NXDOMAIN(域名不存在)响应也会被缓存,缓存时间由 SOA 的最小 TTL 决定,防止对不存在域名的重复查询。


DNS 负载均衡

轮询 DNS(Round-Robin DNS)

同一域名配置多条 A 记录,解析器每次轮流返回不同 IP:

www  IN  A  1.2.3.4
www  IN  A  1.2.3.5
www  IN  A  1.2.3.6

缺点:无法感知后端健康状态,客户端缓存导致分配不均。

GeoDNS / 智能 DNS

根据查询者的地理位置返回不同 IP(CDN 和国内外分流的基础):

中国用户 DNS 查询 example.com → 返回 114.x.x.x(国内 CDN 节点)
美国用户 DNS 查询 example.com → 返回 1.2.x.x(美国 CDN 节点)

Anycast DNS

8.8.8.8、1.1.1.1 等公共 DNS 使用 Anycast:同一 IP 部署在全球多个节点,BGP 路由自动将请求导向最近节点,实现就近响应 + 高可用。


DNSSEC(DNS 安全扩展)

为 DNS 记录添加数字签名,防止缓存污染和中间人篡改:

信任链

根区域(.)
  └── KSK 签名 ZSK → DNSKEY 记录
  └── ZSK 签名所有 RR → RRSIG 记录
        │
      DS 记录(父区域存储子区域 DNSKEY 的哈希摘要)
        │
      .com TLD
        └── DS → example.com DNSKEY
              └── example.com A/MX/... 的 RRSIG

验证流程:递归解析器从根区域的信任锚(Trust Anchor)出发,逐级验证 DS → DNSKEY → RRSIG,确保整条链上每个签名都有效。

# 验证域名是否启用 DNSSEC
dig example.com +dnssec
dig example.com DNSKEY
 
# 检查 DS 记录(在父区域查)
dig example.com DS @a.gtld-servers.net

加密 DNS

明文 DNS(UDP 53)可被监听和篡改,加密 DNS 方案:

协议端口说明
DoT(DNS over TLS)853/TCP在 TLS 通道内传输 DNS,操作系统级支持(Android 9+、iOS)
DoH(DNS over HTTPS)443/TCPDNS 查询封装为 HTTPS,穿越防火墙,浏览器内置支持
DoQ(DNS over QUIC)853/UDP基于 QUIC,更低延迟,新兴标准

配置 DoH(以 Firefox 为例)

设置 → 常规 → 网络设置 → 启用基于 HTTPS 的 DNS
DoH 提供商:
  Cloudflare:https://cloudflare-dns.com/dns-query
  Google:    https://dns.google/dns-query
  NextDNS:   https://dns.nextdns.io/<profile-id>

Linux 系统级 DoT(systemd-resolved)

# /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google
DNSOverTLS=yes
DNSSEC=yes

Split-Horizon DNS(分离解析)

同一域名对内网和外网返回不同结果:

内网用户查询 api.example.com → 返回 10.0.0.100(内网地址,直连)
外网用户查询 api.example.com → 返回 1.2.3.4(公网地址,经过 NAT)

实现方式:内网 DNS 服务器(如 BIND 的 view 配置)对内返回私有 IP,权威 DNS 对外返回公网 IP。


Kubernetes 中的 DNS(CoreDNS)

K8s 内每个 Pod 通过集群内 DNS(CoreDNS)解析 Service 名称:

Service 解析规则:
  <service-name>.<namespace>.svc.cluster.local
  例:redis.default.svc.cluster.local → 10.96.0.100

Pod 间通信:
  kubectl exec pod-a -- nslookup redis
  → Server: 10.96.0.10(CoreDNS ClusterIP)
  → Address: 10.96.0.100

/etc/resolv.conf(Pod 内):
  nameserver 10.96.0.10
  search default.svc.cluster.local svc.cluster.local cluster.local
  options ndots:5

ndots:5 含义:域名中少于 5 个点时,先拼接 search 域尝试,再作为绝对域名查询。这是 K8s 内频繁 DNS 查询的根源,可通过 FQDN(末尾加 .)或减小 ndots 优化。


常用工具与调试

dig 命令详解

# 基础查询(A 记录)
dig example.com
 
# 指定记录类型
dig example.com MX
dig example.com TXT
dig example.com NS
 
# 指定 DNS 服务器查询
dig @8.8.8.8 example.com
 
# 反向解析(PTR)
dig -x 93.184.216.34
 
# 追踪完整解析路径(从根开始)
dig +trace example.com
 
# 精简输出(只看 ANSWER SECTION)
dig +short example.com
 
# 不使用缓存查询
dig +norecurse @ns1.example.com example.com
 
# 查看 TTL 剩余时间
dig +ttlunits example.com

dig 输出解读

; <<>> DiG 9.16 <<>> example.com A
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;example.com.                IN    A

;; ANSWER SECTION:
example.com.    3600  IN    A     93.184.216.34
                ↑TTL  ↑类   ↑类型  ↑值

;; Query time: 12 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)

nslookup / host

nslookup example.com          # 交互或单次查询
nslookup -type=MX example.com
host example.com               # 简洁输出
host -t MX example.com

修改本机 DNS

# Linux(临时)
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
 
# Linux(systemd-resolved 持久化)
resolvectl dns eth0 8.8.8.8 1.1.1.1
resolvectl status
 
# Windows
Set-DnsClientServerAddress -InterfaceAlias "以太网" -ServerAddresses 8.8.8.8,1.1.1.1

常见 DNS 问题

问题症状排查
NXDOMAIN域名不存在确认记录已添加、TTL 已过期、拼写正确
SERVFAIL服务器故障权威服务器异常或 DNSSEC 验证失败
DNS 缓存污染解析到错误 IP刷新缓存、换用 DoH/DoT、检查 DNSSEC
DNS 劫持国内特定域名无法解析使用加密 DNS 或指定境外 DNS
解析慢第一次加载慢DNS 预解析(<link rel="dns-prefetch">)、提高 TTL
ndots 频繁查询K8s Pod DNS 延迟FQDN 末尾加点,或降低 ndots 值
# 清除本机 DNS 缓存
ipconfig /flushdns              # Windows
sudo systemd-resolve --flush-caches  # Linux (systemd)
sudo killall -HUP mDNSResponder # macOS

相关

  • 网络性能 — DNS 解析在完整请求链路中的延迟占比
  • IP与路由 — IP 地址,DNS 解析后的目标
  • HTTP — HTTP 请求前必须先完成 DNS 解析
  • TLS — CAA 记录控制 TLS 证书签发权限
  • HTTPS — HTTPS 站点部署
  • CDN — CDN 通过 GeoDNS / CNAME 将流量引导至最近节点
  • 网络安全 — DNS 劫持、DNS 放大攻击与防护
  • 代理 — 内网 split-horizon DNS 配合代理分流