DNS(Domain Name System)是互联网的"电话簿",负责将人类可读的域名转换为机器可识别的 IP 地址。深入理解 DNS 的工作原理,对理解网络通信的底层逻辑至关重要。
一、DNS 解析流程 1.1 完整查询过程 用户查询 www.example.com 的完整流程:
用户设备
│
│ 1. 检查本地缓存(hosts / 浏览器缓存 / OS 缓存)
│
│ 2. 未命中 → 查询本地 DNS 解析器(ISP 提供或 8.8.8.8)
│
│ DNS Resolver
│ │
│ │ 3. 查询根域名服务器(.)
│ │ ←── 返回 .com TLD 服务器地址
│ │
│ │ 4. 查询 .com TLD 服务器
│ │ ←── 返回 example.com 权威 NS 地址
│ │
│ │ 5. 查询 example.com 权威 DNS
│ │ ←── 返回 www.example.com 的 A 记录
│ │
│ 缓存结果,返回给用户
│
│ 6. 用户拿到 IP,发起 HTTP 请求
迭代查询:Resolver 依次查询根 → TLD → 权威
递归查询:用户只发一次请求,Resolver 负责迭代查询
1.2 Java DNS 操作 // 基础域名解析
InetAddress address = InetAddress . getByName ( "www.example.com" );
System . out . println ( "IP: " + address . getHostAddress ());
// 获取所有 IP
InetAddress [] addresses = InetAddress . getAllByName ( "www.example.com" );
for ( InetAddress addr : addresses ) {
System . out . println ( addr . getHostAddress ());
}
// 反向解析(IP → 域名)
InetAddress byIp = InetAddress . getByName ( "93.184.216.34" );
System . out . println ( "Host: " + byIp . getCanonicalHostName ());
// DNS TTL 缓存控制
java . security . Security . setProperty ( "networkaddress.cache.ttl" , "10" ); // 10 秒
java . security . Security . setProperty ( "networkaddress.cache.negative.ttl" , "0" );
二、DNS 记录类型 记录类型 说明 示例 A IPv4 地址 www IN A 93.184.216.34AAAA IPv6 地址 www IN AAAA 2606:2800:220:1:248:1893:25c8:1946CNAME 别名 blog IN CNAME www.example.comMX 邮件交换 IN MX 10 mail.example.comNS 域名服务器 IN NS ns1.example.comTXT 文本记录 IN TXT "v=spf1 include:_spf.google.com ~all"SRV 服务定位 _http._tcp IN SRV 10 5 80 www.example.comPTR 反向解析 34.216.184.93.in-addr.arpa IN PTR www.example.comSOA 起始授权 包含主 DNS、序列号、刷新时间等
2.1 CNAME 与 A 记录的区别 A 记录(直接指向 IP):
www.example.com ──→ 93.184.216.34
CNAME 记录(别名指向域名):
blog.example.com ──→ www.example.com ──→ 93.184.216.34
⚠️ 注意:
- CNAME 不能与其他记录共存(如 MX 不能与 CNAME 共存)
- CNAME 增加一次查询,略微增加延迟
- CDN 场景下,CNAME 是标准做法
三、CDN 与智能解析 3.1 CDN 调度原理 用户请求 www.example.com → DNS 智能解析
DNS 智能解析系统
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
北京用户 上海用户 广州用户
│ │ │
▼ ▼ ▼
北京 CDN 节点 上海 CDN 节点 广州 CDN 节点
1.2.3.4 1.2.3.5 1.2.3.6
调度策略:
- 地理位置:返回最近节点
- 运营商:返回同运营商节点(电信→电信,联通→联通)
- 负载情况:返回负载较低的节点
- 节点健康:自动剔除故障节点
3.2 DNS 负载均衡策略 多 A 记录轮询:
www.example.com. IN A 1.2.3.4
www.example.com. IN A 1.2.3.5
www.example.com. IN A 1.2.3.6
Resolver 收到 3 个 IP,按轮询返回给客户端
→ 最简单的负载均衡,但不考虑节点健康状态
加权轮询:
www.example.com. IN A 1.2.3.4 (权重 5)
www.example.com. IN A 1.2.3.5 (权重 3)
www.example.com. IN A 1.2.3.6 (权重 2)
四、DNS 安全 4.1 DNS 劫持与污染 攻击类型 原理 防护 DNS 劫持 篡改 DNS 响应,指向恶意 IP HTTPS、DNSSEC DNS 污染 在 DNS 服务器缓存投毒 DNSSEC、EDNS DNS 隧道 利用 DNS 查询传输数据 防火墙检测异常查询
4.2 DNSSEC(DNS Security Extensions) DNSSEC 通过数字签名保证 DNS 响应的真实性:
根区域 (.)
│ 签名 KSK/ZSK
▼
TLD 区域 (.com)
│ 签名 KSK/ZSK
▼
权威区域 (example.com)
│ 签名 A/AAAA/MX 等记录
▼
记录集 (RRset) + RRSIG 签名
验证链条:
1. 验证根区域 KSK(预配置信任锚)
2. 验证 .com DNSKEY(用根 ZSK 签名)
3. 验证 example.com DNSKEY(用 .com ZSK 签名)
4. 验证 www.example.com A 记录(用 example.com ZSK 签名)
关键概念:
- KSK (Key Signing Key): 签名 DNSKEY 记录
- ZSK (Zone Signing Key): 签名区域数据
- DS (Delegation Signer): 父区域对子区域 KSK 的哈希
- RRSIG: 记录集的签名
4.3 DoH / DoT(加密 DNS) 协议 传输 端口 特点 DoH HTTPS 443 隐蔽性强,难以识别和拦截 DoT TLS 853 专用端口,易于管理
// Java 使用 DoH(需外部库或 JDK 内置支持)
// JDK 21+ 实验性支持
DnsClient client = DnsClient . newBuilder ()
. resolver ( Resolver . builder ()
. dohUri ( URI . create ( "https://cloudflare-dns.com/dns-query" ))
. build ())
. build ();
五、Java DNS 扩展 5.1 自定义 DNS 解析器 // 使用 dnsjava 库进行高级 DNS 查询
< dependency >
< groupId > dnsjava </ groupId >
< artifactId > dnsjava </ artifactId >
< version > 3 . 6 . 0 </ version >
</ dependency >
import org.xbill.DNS.* ;
public class DnsQueryExample {
public static void main ( String [] args ) throws Exception {
// A 记录查询
Lookup lookup = new Lookup ( "www.example.com" , Type . A );
Record [] records = lookup . run ();
for ( Record record : records ) {
ARecord a = ( ARecord ) record ;
System . out . println ( "A: " + a . getAddress ());
}
// MX 记录查询
Lookup mxLookup = new Lookup ( "example.com" , Type . MX );
Record [] mxRecords = mxLookup . run ();
for ( Record record : mxRecords ) {
MXRecord mx = ( MXRecord ) record ;
System . out . println ( "MX: " + mx . getTarget () + " (priority: " + mx . getPriority () + ")" );
}
// DNSSEC 验证
SimpleResolver resolver = new SimpleResolver ( "8.8.8.8" );
resolver . setEDNS ( 0 , 0 , ExtendedFlags . DO );
Lookup secLookup = new Lookup ( "www.isc.org" , Type . A );
secLookup . setResolver ( resolver );
secLookup . setCredibility ( Credibility . SECURE );
Record [] secRecords = secLookup . run ();
if ( secLookup . getResult () == Lookup . SUCCESSFUL ) {
System . out . println ( "DNSSEC 验证成功" );
}
}
}
六、DNS 调优 6.1 TTL 配置建议 记录类型 建议 TTL 说明 A/AAAA 300-600s 频繁变更时短 TTL,稳定后可延长 CNAME 3600s 变更较少 MX 3600s 邮件服务 TXT 3600s SPF/DKIM 等 NS 86400s 极少变更
6.2 DNS 缓存层次 缓存层次(从上到下,TTL 依次递减):
浏览器缓存
├── Chrome: chrome://net-internals/#dns
├── Firefox: about:networking#dns
操作系统缓存
├── Linux: systemd-resolved, nscd
├── macOS: mDNSResponder
├── Windows: DNS Client service
本地 DNS 解析器(ISP / 8.8.8.8 / 1.1.1.1)
DNS 转发器(企业内网)
权威 DNS 服务器(无缓存,直接返回记录)
七、总结 主题 关键要点 解析流程 递归 + 迭代查询,根 → TLD → 权威 记录类型 A/AAAA、CNAME、MX、TXT 各司其职 CDN 调度 基于地理位置、运营商、负载的智能解析 安全防护 DNSSEC 防篡改,DoH/DoT 加密传输 性能优化 合理的 TTL、多层缓存、预解析
DNS 看似简单,却是整个互联网基础设施中最关键的一环。一个域名的解析延迟、一次 DNS 劫持,都可能直接影响用户体验和系统安全。
继续阅读
探索更多技术文章 浏览归档,发现更多关于系统设计、工具链和工程实践的内容。