DNS 系统与智能解析

理解 DNS 解析的完整流程、记录类型与 CDN 调度原理,掌握 DNSSEC 安全扩展与智能解析的工程实践

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 记录类型

记录类型说明示例
AIPv4 地址www IN A 93.184.216.34
AAAAIPv6 地址www IN AAAA 2606:2800:220:1:248:1893:25c8:1946
CNAME别名blog IN CNAME www.example.com
MX邮件交换IN MX 10 mail.example.com
NS域名服务器IN NS ns1.example.com
TXT文本记录IN TXT "v=spf1 include:_spf.google.com ~all"
SRV服务定位_http._tcp IN SRV 10 5 80 www.example.com
PTR反向解析34.216.184.93.in-addr.arpa IN PTR www.example.com
SOA起始授权包含主 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 响应,指向恶意 IPHTTPS、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)

协议传输端口特点
DoHHTTPS443隐蔽性强,难以识别和拦截
DoTTLS853专用端口,易于管理
// 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/AAAA300-600s频繁变更时短 TTL,稳定后可延长
CNAME3600s变更较少
MX3600s邮件服务
TXT3600sSPF/DKIM 等
NS86400s极少变更

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 劫持,都可能直接影响用户体验和系统安全。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「network」更多文章

  1. 网络安全:TLS/SSL、证书与加密通信
  2. 负载均衡算法与高可用架构
  3. WebSocket 协议与实时通信