DNS 协议深度学习指南(含上机实操)
适用版本 : BIND 9.18.39 | DiG 9.18.39 | Dnsmasq 2.90 | Ubuntu 24.04 LTS
实验集群 : ecs-ee63 (华为云香港区, 3 节点 c6.large_2)
客户端 : dig / nslookup / host / tcpdump / Python 3
特点: 全部实验基于真实服务器输出, 非模拟数据
目录
- [第一章: DNS 基础与核心概念](#第一章: DNS 基础与核心概念 "#%E7%AC%AC%E4%B8%80%E7%AB%A0-dns-%E5%9F%BA%E7%A1%80%E4%B8%8E%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5")
- [第二章: DNS 记录类型详解](#第二章: DNS 记录类型详解 "#%E7%AC%AC%E4%BA%8C%E7%AB%A0-dns-%E8%AE%B0%E5%BD%95%E7%B1%BB%E5%9E%8B%E8%AF%A6%E8%A7%A3")
- [第三章: DNS 解析过程详解](#第三章: DNS 解析过程详解 "#%E7%AC%AC%E4%B8%89%E7%AB%A0-dns-%E8%A7%A3%E6%9E%90%E8%BF%87%E7%A8%8B%E8%AF%A6%E8%A7%A3")
- [第四章: DNS 配置与管理](#第四章: DNS 配置与管理 "#%E7%AC%AC%E5%9B%9B%E7%AB%A0-dns-%E9%85%8D%E7%BD%AE%E4%B8%8E%E7%AE%A1%E7%90%86")
- [第五章: DNS 安全与防护](#第五章: DNS 安全与防护 "#%E7%AC%AC%E4%BA%94%E7%AB%A0-dns-%E5%AE%89%E5%85%A8%E4%B8%8E%E9%98%B2%E6%8A%A4")
- [第六章: DNS 性能优化](#第六章: DNS 性能优化 "#%E7%AC%AC%E5%85%AD%E7%AB%A0-dns-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96")
- [第七章: 云 DNS 服务实战](#第七章: 云 DNS 服务实战 "#%E7%AC%AC%E4%B8%83%E7%AB%A0-%E4%BA%91-dns-%E6%9C%8D%E5%8A%A1%E5%AE%9E%E6%88%98")
- [第八章: DNS 故障排查](#第八章: DNS 故障排查 "#%E7%AC%AC%E5%85%AB%E7%AB%A0-dns-%E6%95%85%E9%9A%9C%E6%8E%92%E6%9F%A5")
- [第九章: DNS 与容器化](#第九章: DNS 与容器化 "#%E7%AC%AC%E4%B9%9D%E7%AB%A0-dns-%E4%B8%8E%E5%AE%B9%E5%99%A8%E5%8C%96")
- [第十章: DNS 自动化与 DevOps](#第十章: DNS 自动化与 DevOps "#%E7%AC%AC%E5%8D%81%E7%AB%A0-dns-%E8%87%AA%E5%8A%A8%E5%8C%96%E4%B8%8E-devops")
- 附录
第一章: DNS 基础与核心概念
1.1 DNS 的定义与作用
DNS (Domain Name System, 域名系统) 是互联网的「电话簿」------ 将人类可读的域名 (如 baidu.com) 转换为机器可路由的 IP 地址 (如 110.242.74.102)。
┌──────────────────────────────────────────────────────────┐
│ DNS 核心工作原理 │
│ │
│ 用户输入 DNS 服务器 │
│ baidu.com ──────────────▶ 查询域名 ──────────────▶ 返回 IP │
│ ↓ │
│ 110.242.74.102 │
│ │ │
│ 浏览器 ◀────────────────────┘ │
│ 连接到 110.242.74.102:443 │
└──────────────────────────────────────────────────────────┘
为什么需要 DNS:
- 人类记忆域名 (baidu.com) 远比 IP 地址 (110.242.74.102) 容易
- IP 地址可能变更, 域名可以保持稳定
- 一个域名可以对应多个 IP 实现负载均衡
- 通过 DNS 可以实现服务发现和故障转移
1.2 DNS 的历史发展
| 阶段 | 时间 | 方案 | 问题 |
|---|---|---|---|
| ARPANET 时代 | 1970s | 单机 hosts.txt 文件 (SRI-NIC 维护) |
每台机器手动同步, 不可扩展 |
| DNS 诞生 | 1983 | RFC 882/883 → RFC 1034/1035 | Paul Mockapetris 设计, 分布式层级数据库 |
| BIND 时代 | 1984-至今 | BIND (Berkeley Internet Name Domain) | 最广泛使用的 DNS 服务器软件 |
| 现代 DNS | 2010s-至今 | DNSSEC / DoH / DoT / DoQ | 安全加密 + 隐私保护 |
hosts 文件 vs DNS 对比:
bash
hosts 文件方式 (单机):
┌──────────────┐
│ /etc/hosts │
│ 1.2.3.4 foo │ ← 每一台机器都要维护
│ 5.6.7.8 bar │
└──────────────┘
DNS 分布式方式:
┌─────────┐ ┌─────────┐ ┌──────────┐
│ 根服务器 │───▶│ .com TLD │───▶│ 权威服务器 │
│ (13组) │ │ 服务器 │ │ (baidu) │
└─────────┘ └─────────┘ └──────────┘
1.3 DNS 的层级结构
scss
┌──────┐
│ . │ 根域 (Root) - 13 组根服务器 (a~m.root-servers.net)
└──┬───┘
┌─────────────┼──────────────┐
┌──┴──┐ ┌──┴──┐ ┌──┴───┐
│ com │ │ cn │ │ org │ 顶级域 (Top-Level Domain, TLD)
└──┬──┘ └──┬──┘ └──────┘
┌─────┴─────┐ │
┌──┴───┐ ┌──┴───┐ │
│baidu │ │google│ │ 二级域 (Second-Level Domain)
└──┬───┘ └──────┘ │
┌────┴────┐ │
┌──┴───┐ ┌──┴───┐ │
│ www │ │ mail │ │ 子域 (Subdomain)
└──────┘ └──────┘ │
┌───┴────┐
│example │
└────────┘
FQDN (Fully Qualified Domain Name, 完全限定域名) : www.baidu.com. (注意末尾的 . 代表根域)
1.4 DNS 服务器类型
| 服务器类型 | 英文 | 作用 | 示例 |
|---|---|---|---|
| 根服务器 | Root Server | DNS 解析的起点, 返回 TLD 服务器地址 | a.root-servers.net (198.41.0.4) |
| TLD 服务器 | Top-Level Domain Server | 管理特定顶级域的权威信息 | a.gtld-servers.net (192.5.6.30) |
| 权威服务器 | Authoritative Server | 存储域名实际 DNS 记录 | ns1.baidu.com |
| 递归服务器 | Recursive Resolver | 代客户端完成完整解析过程 | 8.8.8.8 (Google), 1.1.1.1 (Cloudflare) |
13 组根服务器 (Root Servers):
| 字母 | IPv4 | IPv6 | 运营方 |
|---|---|---|---|
| A | 198.41.0.4 | 2001:503:ba3e::2:30 | Verisign |
| B | 170.247.170.2 | 2801:1b8:10::b | USC-ISI |
| C | 192.33.4.12 | 2001:500:2::c | Cogent |
| D | 199.7.91.13 | 2001:500:2d::d | UMD |
| E | 192.203.230.10 | 2001:500:a8::e | NASA |
| F | 192.5.5.241 | 2001:500:2f::f | ISC |
| G | 192.112.36.4 | 2001:500:12::d0d | DISA |
| H | 198.97.190.53 | 2001:500:1::53 | US Army |
| I | 192.36.148.17 | 2001:7fe::53 | Netnod |
| J | 192.58.128.30 | 2001:503:c27::2:30 | Verisign |
| K | 193.0.14.129 | 2001:7fd::1 | RIPE NCC |
| L | 199.7.83.42 | 2001:500:9f::42 | ICANN |
| M | 202.12.27.33 | 2001:dc3::35 | WIDE |
注意: 13 组不是 13 台! 每组使用 Anycast (任播) 技术在全球部署数百个节点。
1.5 上机实操: 基本 DNS 查询
实验环境: ecs-ee63 集群 (tcpip-01), BIND 9.18.39, DiG 9.18.39
1.5.1 三种基本查询工具对比
bash
# dig (Domain Information Groper) --- 最强大的 DNS 诊断工具
$ dig baidu.com
; <<>> DiG 9.18.39-0ubuntu0.24.04.5-Ubuntu <<>> baidu.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5877
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;baidu.com. IN A
;; ANSWER SECTION:
baidu.com. 507 IN A 110.242.74.102
baidu.com. 507 IN A 111.63.65.103
baidu.com. 507 IN A 111.63.65.247
baidu.com. 507 IN A 124.237.177.164
;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; MSG SIZE rcvd: 102
dig 输出字段详解:
| 字段 | 含义 | 说明 |
|---|---|---|
status: NOERROR |
查询状态 | NOERROR=成功, NXDOMAIN=域名不存在, SERVFAIL=服务器失败 |
flags: qr rd ra |
标志位 | qr=响应, rd=期望递归, ra=递归可用 |
ANSWER: 4 |
回答记录数 | 返回了 4 条 A 记录 |
507 |
TTL (秒) | 缓存有效期, 约 8.5 分钟 |
IN |
网络类别 | IN=Internet (唯一广泛使用的类别) |
Query time: 0 msec |
查询耗时 | 本地缓存命中时几乎为 0 |
SERVER: 127.0.0.53 |
使用的 DNS 服务器 | systemd-resolved 本地存根 |
bash
# nslookup --- 交互式查询工具 (简洁输出)
$ nslookup baidu.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer: ← 非权威回答 (来自缓存)
Name: baidu.com
Address: 124.237.177.164
Address: 110.242.74.102
bash
# host --- 最简洁的查询工具
$ host baidu.com
baidu.com has address 111.63.65.247
baidu.com has address 110.242.74.102
baidu.com has address 124.237.177.164
baidu.com has address 111.63.65.103
baidu.com mail is handled by 20 mx.baidu.com.
三种工具对比:
| 工具 | 详细程度 | 适用场景 |
|---|---|---|
| dig | ★★★★★ (最详细) | 故障排查、DNSSEC 验证、性能分析 |
| nslookup | ★★★ (中等) | 日常快速查询、交互式使用 |
| host | ★ (最简洁) | 脚本自动化、快速确认 |
1.5.2 指定 DNS 服务器查询
bash
# 使用不同的公共 DNS 递归解析器查询同一域名
$ dig @8.8.8.8 baidu.com +short
111.63.65.103
111.63.65.247
110.242.74.102
124.237.177.164
$ dig @1.1.1.1 baidu.com +short
111.63.65.103
124.237.177.164
110.242.74.102
111.63.65.247
$ dig @223.5.5.5 baidu.com +short # 阿里 DNS (中国大陆)
111.63.65.247
124.237.177.164
110.242.74.102
111.63.65.103
关键发现: 所有公共解析器返回相同的 4 个 IP, 但排序不同------这是 DNS 轮询 (Round-Robin) 负载均衡的体现。
1.5.3 查看本机 DNS 配置
bash
# /etc/resolv.conf --- 传统 DNS 客户端配置
$ cat /etc/resolv.conf
nameserver 127.0.0.53 # systemd-resolved 本地存根
options edns0 trust-ad
search openstacklocal # 搜索域
# systemd-resolved 状态 (现代 Ubuntu 使用)
$ resolvectl status
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (eth0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 100.125.3.250 # 华为云内网 DNS
DNS Servers: 100.125.3.250 100.125.1.250
systemd-resolved 架构:
bash
┌─────────────┐ ┌───────────────────┐ ┌──────────────┐
│ 应用程序 │────▶│ 127.0.0.53:53 │────▶│ 100.125.3.250│
│ (dig/curl) │ │ systemd-resolved │ │ (上游 DNS) │
└─────────────┘ │ (本地存根+缓存) │ └──────────────┘
└───────────────────┘
第二章: DNS 记录类型详解
2.1 八大核心记录类型
scss
┌──────────────────────────────────────────────────────────────┐
│ DNS 记录类型全景图 │
├──────────┬──────────────────┬────────────────────────────────┤
│ 记录类型 │ 全称 │ 作用 │
├──────────┼──────────────────┼────────────────────────────────┤
│ A │ Address │ 域名 → IPv4 地址 │
│ AAAA │ IPv6 Address │ 域名 → IPv6 地址 (4倍A=IPv6) │
│ CNAME │ Canonical Name │ 别名 → 规范域名 │
│ MX │ Mail Exchange │ 邮件服务器优先级+地址 │
│ TXT │ Text │ 任意文本 (SPF/DKIM/验证) │
│ NS │ Name Server │ 域的权威 DNS 服务器 │
│ SOA │ Start of Authority│ 域的管理信息 (版本/刷新/重试) │
│ PTR │ Pointer │ IP → 域名 (反向解析) │
└──────────┴──────────────────┴────────────────────────────────┘
2.2 A 记录 (Address Record)
将域名映射到 IPv4 地址, 是 DNS 最核心的记录类型。
bash
$ dig A baidu.com +short
110.242.74.102
111.63.65.247
111.63.65.103
124.237.177.164
A 记录负载均衡: baidu.com 返回 4 个 IP, DNS 服务器每次轮换顺序, 实现简单的流量分发。
2.3 AAAA 记录 (IPv6 Address Record)
bash
$ dig AAAA baidu.com +short
(无返回) # baidu.com 未配置 IPv6 地址
注意: 中国大陆很多大型网站仍未启用 IPv6 公网解析, 主要因为 IPv4 仍然充足且 CDN 覆盖完善。
2.4 CNAME 记录 (Canonical Name)
别名记录, 将一个域名指向另一个规范域名。重要限制: CNAME 不能与其他记录共存 (除了 DNSSEC 相关记录)。
bash
$ dig CNAME www.baidu.com +short
www.a.shifen.com.
scss
www.baidu.com (CNAME) → www.a.shifen.com (A) → IP 地址
↑ 用户访问 ↑ CDN 调度域名 ↑ 实际服务器
CNAME 链追踪:
less
用户请求 www.baidu.com
│
▼
DNS 返回 CNAME: www.a.shifen.com.
│
▼
递归解析器自动追踪: www.a.shifen.com A?
│
▼
返回实际 IP 地址
2.5 MX 记录 (Mail Exchange)
指定域名的邮件服务器及优先级 (数字越小优先级越高)。
bash
$ dig MX baidu.com +short
10 mx.maillb.baidu.com. # 优先级 10 (优先使用)
20 mx.baidu.com. # 优先级 20 (备用)
邮件投递流程:
less
发件服务器 收件域 DNS
│ │
│ dig MX baidu.com │
│──────────────────────────────────▶│
│ │
│ 10 mx.maillb.baidu.com │
│◀──────────────────────────────────│
│ │
│ 尝试连接 mx.maillb.baidu.com:25 │
│──────────────────────────────────▶│ ✓ 成功投递
│ │
│ (若失败, 尝试 mx.baidu.com:25) │
2.6 TXT 记录 (Text Record)
存储任意文本, 主要用于验证和策略声明。
bash
$ dig TXT baidu.com +short
"v=spf1 include:spf1.baidu.com include:spf2.baidu.com include:spf3.baidu.com include:spf4.baidu.com -all"
"9279nznttl321bxp1j464rd9vpps246v"
"google-site-verification=GHb98-6msqyx_qqjGl5eRatD3QTHyVB6-xQ3gJB5UwM"
"_globalsign-domain-verification=qjb28W2jJSrWj04NHpB0CvgK9tle5JkOq-EcyWBgnE"
| TXT 记录 | 用途 |
|---|---|
v=spf1 ... |
SPF (Sender Policy Framework), 声明哪些服务器有权发邮件 |
google-site-verification=... |
Google Search Console 域名所有权验证 |
_globalsign-domain-verification=... |
GlobalSign SSL 证书域名验证 |
2.7 NS 记录 (Name Server)
指定域名的权威 DNS 服务器。
bash
$ dig NS baidu.com +short
dns.baidu.com.
ns3.baidu.com.
ns2.baidu.com.
ns7.baidu.com.
ns4.baidu.com.
最佳实践: 权威 NS 服务器应该分布在不同的地理位置和网络自治系统 (AS), 避免单点故障。
2.8 SOA 记录 (Start of Authority)
域的「管理信息摘要」, 包含版本号、刷新间隔等管理参数。
bash
$ dig SOA baidu.com +short
dns.baidu.com. sa.baidu.com. 2012151067 300 300 2592000 600
SOA 字段详解:
| 字段 | 值 | 含义 |
|---|---|---|
| MNAME | dns.baidu.com. | 主 DNS 服务器 (Primary Master) |
| RNAME | sa.baidu.com. | 管理员邮箱 (sa@baidu.com, @ 替换为 .) |
| Serial | 2012151067 | 序列号 (格式: YYYYMMDDNN), 从服务器判断是否需要同步 |
| Refresh | 300 (5分钟) | 从服务器检查主服务器更新的间隔 |
| Retry | 300 (5分钟) | 刷新失败后的重试间隔 |
| Expire | 2592000 (30天) | 从服务器在无法联系主服务器后, 数据有效的最长时间 |
| Minimum TTL | 600 (10分钟) | 否定缓存 (NXDOMAIN) 的 TTL |
2.9 PTR 记录 (反向解析)
IP 地址 → 域名的反向查询。
bash
$ dig -x 8.8.8.8 +short
dns.google.
$ dig -x 1.1.1.1 +short
one.one.one.one.
反向解析原理:
makefile
IP: 8.8.8.8
↓ 反转
查询: 8.8.8.8.in-addr.arpa PTR?
↓
返回: dns.google.
2.10 上机实操: 批量查询与对比
bash
$ for r in A AAAA MX TXT NS SOA; do
echo "=== $r Record ==="
dig $r baidu.com +short
echo
done
真实输出:
ini
=== A Record ===
111.63.65.247
111.63.65.103
110.242.74.102
124.237.177.164
=== AAAA Record ===
(无IPv6地址)
=== MX Record ===
10 mx.maillb.baidu.com.
20 mx.baidu.com.
=== TXT Record ===
"v=spf1 include:spf1.baidu.com include:spf2.baidu.com ... -all"
"google-site-verification=GHb98-..."
=== NS Record ===
ns4.baidu.com.
ns7.baidu.com.
ns2.baidu.com.
ns3.baidu.com.
dns.baidu.com.
=== SOA Record ===
dns.baidu.com. sa.baidu.com. 2012151067 300 300 2592000 600
第三章: DNS 解析过程详解
3.1 递归查询 vs 迭代查询
scss
┌─────────────────── 递归查询 (Recursive) ───────────────────┐
│ │
│ 客户端 递归解析器 │
│ │ │ │
│ │── dig baidu.com ────▶│ │
│ │ │── 根服务器 → .com TLD │
│ │ │── TLD 服务器 → NS 记录 │
│ │ │── 权威服务器 → A 记录 │
│ │◀── 110.242.74.102 ──│ │
│ │
│ 客户端只需发一次请求, 解析器负责完成全部查询 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────── 迭代查询 (Iterative) ───────────────────┐
│ │
│ 客户端 DNS 层级 │
│ │ │ │
│ │── dig baidu.com ──────────▶│ 根服务器 │
│ │◀── 去问 .com TLD ─────────│ │
│ │── dig baidu.com ──────────▶│ .com TLD 服务器 │
│ │◀── 去问 ns1.baidu.com ───│ │
│ │── dig baidu.com ──────────▶│ ns1.baidu.com (权威) │
│ │◀── 110.242.74.102 ───────│ │
│ │
│ 客户端自己逐步查询, 每步只获取下一个线索 │
└─────────────────────────────────────────────────────────────┘
实际使用: 客户端通常使用递归查询 (发送给 ISP/公共 DNS 解析器), DNS 服务器之间使用迭代查询。
3.2 DNS 缓存机制
scss
┌──────────────────────────────────────────────────────────────┐
│ DNS 缓存层级 │
│ │
│ ┌─────────────┐ │
│ │ 应用层缓存 │ Chrome/curl 内置 DNS 缓存 (~1分钟) │
│ └──────┬──────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ OS 缓存 │ systemd-resolved / nscd (由 TTL 决定) │
│ └──────┬──────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 递归解析器 │ 8.8.8.8 / 1.1.1.1 的大规模缓存 │
│ │ 缓存 │ (命中率 >90%) │
│ └──────┬──────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 权威服务器 │ 原始数据源, 不缓存 │
│ └─────────────┘ │
└──────────────────────────────────────────────────────────────┘
缓存控制: 每条 DNS 记录都有 TTL (Time To Live), 单位秒。
baidu.com. 507 IN A→ 507 秒内可以缓存- TTL 越短 = 变更越灵活, 但查询次数越多
- CDN 常用短 TTL (60-300秒) 实现快速切换
3.3 DNS 解析超时与重试
ini
客户端超时参数 (dig):
+time=N → 单次查询超时 (默认 5 秒)
+tries=N → 重试次数 (默认 3 次)
解析器行为:
第1次: 发送查询, 等待 5 秒
第2次: 超时后重试, 等待 5 秒
第3次: 再次超时后重试, 等待 5 秒
失败: SERVFAIL 或超时错误
总最长时间 = time × tries = 5s × 3 = 15 秒
3.4 上机实操: 完整解析追踪 (+trace)
dig +trace 模拟迭代查询过程, 展示 DNS 解析的每一步:
bash
$ dig +trace +nodnssec baidu.com
实测输出 (3步解析):
python
步骤 1 --- 根服务器 (Root Servers):
. 216252 IN NS a.root-servers.net.
. 216252 IN NS b.root-servers.net.
... (13 组根服务器)
;; Received 239 bytes from 127.0.0.53#53 in 1 ms
步骤 2 --- .com TLD 服务器:
com. 172800 IN NS a.gtld-servers.net.
com. 172800 IN NS b.gtld-servers.net.
... (13 个 .com TLD 服务器)
;; Received 834 bytes from 170.247.170.2#53(b.root-servers.net) in 40 ms
│
│ 返回 baidu.com 的 NS 记录:
│ baidu.com. 172800 IN NS ns2.baidu.com.
│ baidu.com. 172800 IN NS ns3.baidu.com.
│ baidu.com. 172800 IN NS ns4.baidu.com.
│ baidu.com. 172800 IN NS ns1.baidu.com.
│ baidu.com. 172800 IN NS ns7.baidu.com.
;; Received 352 bytes from 192.26.92.30#53(c.gtld-servers.net) in 219 ms
步骤 3 --- 权威服务器 (Authoritative):
baidu.com. 600 IN A 111.63.65.103
baidu.com. 600 IN A 124.237.177.164
baidu.com. 600 IN A 110.242.74.102
baidu.com. 600 IN A 111.63.65.247
;; Received 444 bytes from 180.76.76.92#53(ns7.baidu.com) in 4 ms
时间分析:
ini
总时间: 1ms + 40ms + 219ms + 4ms = 264ms
├── 本地缓存读取根服务器列表: 1ms
├── 根 → TLD (b.root-servers): 40ms
├── TLD → 权威 (c.gtld): 219ms ← 最耗时! 跨太平洋
└── 权威 → 回答 (ns7.baidu): 4ms ← 国内, 很快
3.5 上机实操: 缓存刷新与验证
bash
# 刷新 systemd-resolved 缓存
$ resolvectl flush-caches
# Cache flushed
# 验证缓存效果 --- 首次查询 vs 缓存命中
$ dig baidu.com +stats | grep "Query time"
Query time: 1 msec # 本地缓存命中
$ dig @1.1.1.1 baidu.com +stats | grep "Query time"
Query time: 2 msec # 远程解析器 (香港节点)
3.6 上机实操: 不同 DNS 解析器延迟对比
bash
$ for ns in 1.1.1.1 8.8.8.8 9.9.9.9 223.5.5.5; do
t=$(dig @$ns baidu.com +stats | grep "Query time" | awk '{print $4}')
echo "@$ns: ${t} ms"
done
实测结果 (香港 ECS → 各解析器):
| DNS 解析器 | IP | 延迟 | 说明 |
|---|---|---|---|
| Cloudflare | 1.1.1.1 | 2 ms | 全球 Anycast, 香港有节点 |
| 8.8.8.8 | 2 ms | 香港节点就近响应 | |
| Quad9 | 9.9.9.9 | 38 ms | 新加坡/日本节点 |
| AliDNS | 223.5.5.5 | 46 ms | 中国大陆, 跨境延迟 |
第四章: DNS 配置与管理
4.1 BIND9 简介
BIND (Berkeley Internet Name Domain) 是最古老、最广泛使用的 DNS 服务器软件, 目前由 ISC (Internet Systems Consortium) 维护。
bash
BIND9 架构:
┌──────────────────────────────────────────┐
│ named (BIND 守护进程) │
│ │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ named.conf │ │ 区域文件 │ │
│ │ (主配置文件) │ │ db.example.com │ │
│ │ │ │ (DNS 记录) │ │
│ │ options {} │ │ │ │
│ │ zone {} │ │ $TTL 86400 │ │
│ └────────────────┘ │ @ IN SOA ... │ │
│ │ www IN A ... │ │
│ └────────────────┘ │
└──────────────────────────────────────────┘
4.2 上机实操: 配置权威 DNS 服务器
实验环境: tcpip-01, BIND 9.18.39
步骤 1: 确认 BIND9 状态
bash
$ systemctl status bind9
● named.service - BIND Domain Name Server
Active: active (running) since Tue 2026-06-02 13:18:24 CST
Memory: 23.0M
$ named -v
BIND 9.18.39-0ubuntu0.24.04.5-Ubuntu (Extended Support Version)
步骤 2: 配置主区域声明
创建 /etc/bind/named.conf.local:
bash
zone "example.local" {
type master; # 主 DNS 服务器
file "/etc/bind/db.example.local"; # 区域数据文件路径
};
zone "1.168.192.in-addr.arpa" { # 反向解析区域
type master;
file "/etc/bind/db.192.168.1";
};
配置项详解:
| 参数 | 值 | 含义 |
|---|---|---|
type master |
主服务器 | 该节点是此区域的数据权威来源 |
type slave |
从服务器 | 从主服务器同步区域数据 |
file |
文件路径 | 相对于 directory 选项 (默认 /etc/bind) |
步骤 3: 创建区域数据文件
创建 /etc/bind/db.example.local:
ini
$TTL 86400 ; 默认 TTL = 1 天
@ IN SOA ns1.example.local. admin.example.local. (
2024060201 ; Serial (YYYYMMDDNN 格式)
3600 ; Refresh (1小时)
1800 ; Retry (30分钟)
604800 ; Expire (7天)
86400 ) ; Minimum TTL (1天)
; Name Server 记录
@ IN NS ns1.example.local.
; A 记录
@ IN A 192.168.1.100 ; @ 代表区域本身 example.local.
ns1 IN A 192.168.1.100
www IN A 192.168.1.101
mail IN A 192.168.1.102
; CNAME 别名
ftp IN CNAME www.example.local.
区域文件格式说明:
| 符号 | 含义 | 示例 |
|---|---|---|
@ |
代表当前区域名 | example.local. |
IN |
Internet 类 (固定) | 几乎所有记录都用 IN |
| 空白/制表符 | 字段分隔符 | 至少一个空格 |
; |
注释 (行内) | ; 这是注释 |
( ) |
多行括号 | SOA 记录常用 |
步骤 4: 验证配置并测试
bash
# 检查配置文件语法
$ named-checkconf
(无输出 = 配置正确)
# 检查区域文件
$ named-checkzone example.local /etc/bind/db.example.local
zone example.local/IN: loaded serial 2024060201
OK
# 重启 BIND9 使配置生效
$ systemctl restart bind9
# 测试本地 DNS 查询
$ dig @localhost example.local A +short
192.168.1.100
$ dig @localhost www.example.local A +short
192.168.1.101
$ dig @localhost ftp.example.local CNAME +short
www.example.local. # CNAME 正确解析
$ dig @localhost ns1.example.local A +short
192.168.1.100
$ dig @localhost example.local SOA +short
ns1.example.local. admin.example.local. 2024060201 3600 1800 604800 86400
$ dig @localhost example.local NS +short
ns1.example.local.
4.3 DNS 主从复制架构
bash
┌─────────────────┐ Zone Transfer (AXFR/IXFR) ┌─────────────────┐
│ Master (主) │────────────────────────────────────────▶│ Slave (从) │
│ type: master │ TCP 53 端口 │ type: slave │
│ │ │ │
│ Serial: │ 从服务器检测 Serial 是否增加: │ Serial: │
│ 2024060201 │ 新增 → 拉取完整区域 (AXFR) │ 2024060201 │
│ │ 相同 → 不操作 │ │
└─────────────────┘ └─────────────────┘
从服务器配置:
zone "example.local" {
type slave;
file "/var/cache/bind/db.example.local"; # 从服务器缓存位置
masters { 192.168.1.100; }; # 主服务器 IP
};
主从复制关键参数:
| 参数 | 作用 | 推荐值 |
|---|---|---|
| Serial | 版本号, 每次修改必须递增 | YYYYMMDDNN 格式 |
| Refresh | 从服务器检查主服务器的间隔 | 3600 (1小时) |
| Retry | 刷新失败重试间隔 | 1800 (30分钟) |
| Expire | 无法联系主服务器后数据有效期 | 604800 (7天) |
| Minimum TTL | 否定缓存 TTL | 86400 (1天) |
第五章: DNS 安全与防护
5.1 DNS 安全威胁全景
scss
┌──────────────────────────────────────────────────────────────┐
│ DNS 安全威胁矩阵 │
├─────────────────────┬────────────────┬───────────────────────┤
│ 威胁类型 │ 攻击方式 │ 危害 │
├─────────────────────┼────────────────┼───────────────────────┤
│ DNS 劫持 │ 篡改 DNS 响应 │ 流量劫持到钓鱼网站 │
│ (DNS Hijacking) │ │ │
├─────────────────────┼────────────────┼───────────────────────┤
│ DNS 缓存投毒 │ 向递归解析器注入 │ 大量用户被重定向 │
│ (Cache Poisoning) │ 伪造响应 │ │
├─────────────────────┼────────────────┼───────────────────────┤
│ DNS 放大攻击 │ 伪造源IP发小请求 │ 反射型 DDoS, 放大 50x │
│ (Amplification) │ 收大响应 │ │
├─────────────────────┼────────────────┼───────────────────────┤
│ DNS 隧道 │ DNS 协议传数据 │ 数据泄露绕过防火墙 │
│ (Tunneling) │ │ │
└─────────────────────┴────────────────┴───────────────────────┘
5.2 DNSSEC (DNS Security Extensions)
DNSSEC 通过数字签名保证 DNS 数据的完整性和真实性, 防止篡改。
markdown
DNSSEC 签名链:
┌──────┐
│ . │ Root KSK/ZSK (信任锚)
└──┬───┘
│ DS 记录 (委派签名者)
┌──┴──┐
│ com │ TLD ZSK 签名
└──┬───┘
│ DS 记录
┌──┴─────┐
│ baidu │ 权威 ZSK 签名所有记录
└────────┘
DNSSEC 关键记录类型:
| 记录 | 全称 | 作用 |
|---|---|---|
| RRSIG | Resource Record Signature | 资源记录的数字签名 |
| DNSKEY | DNS Public Key | 区域的公钥 |
| DS | Delegation Signer | 父区域对子区域 DNSKEY 的哈希 |
| NSEC/NSEC3 | Next Secure | 证明某个域名不存在 |
DNSSEC 验证:
bash
# 查询启用 DNSSEC 的域名
$ dig +dnssec cloudflare.com
cloudflare.com. 300 IN A 104.16.133.229
cloudflare.com. 300 IN A 104.16.132.229
cloudflare.com. 300 IN RRSIG A 13 2 300 ... # DNSSEC 签名
# flags 中的 ad (Authenticated Data) 表示 DNSSEC 验证通过
DNSSEC 验证状态:
bash
$ resolvectl status
DNSSEC=no/unsupported # 当前环境未启用 DNSSEC
5.3 DNS over HTTPS (DoH) 与 DNS over TLS (DoT)
传统 DNS 使用 UDP 53 端口明文传输, 容易被监听和篡改。DoH 和 DoT 提供加密传输。
scss
┌──────────────────────────────────────────────────────────────┐
│ DNS 加密传输对比 │
├──────────┬──────────────┬──────────────┬────────────────────┤
│ 方案 │ 端口 │ 协议 │ 伪装性 │
├──────────┼──────────────┼──────────────┼────────────────────┤
│ 传统 DNS │ 53 (UDP/TCP) │ DNS 明文 │ 容易被识别和拦截 │
│ DoT │ 853 (TCP) │ DNS over TLS │ 独立端口, 可被封锁 │
│ DoH │ 443 (TCP) │ DNS over HTTPS│ 与普通 HTTPS 无异 │
│ DoQ │ 853 (UDP) │ DNS over QUIC│ 实验阶段 │
└──────────┴──────────────┴──────────────┴────────────────────┘
主流 DoH/DoT 服务商:
| 服务商 | DoH URL | DoT 地址 |
|---|---|---|
| Cloudflare | https://1.1.1.1/dns-query |
1.1.1.1:853 |
https://dns.google/dns-query |
8.8.8.8:853 |
|
| Quad9 | https://dns.quad9.net/dns-query |
9.9.9.9:853 |
5.4 DNS 安全最佳实践
- 启用 DNSSEC --- 为权威区域签名, 递归解析器启用验证
- 使用 DoH/DoT --- 加密客户端到解析器的通信
- 限制区域传输 --- 只允许授权的从服务器执行 AXFR
- 隐藏 BIND 版本 ---
version "Not disclosed"; - 限制递归查询 --- 只对信任的客户端开放递归
- 启用查询日志 --- 审计和异常检测
- 定期更新 --- BIND 安全补丁及时应用
第六章: DNS 性能优化
6.1 DNS 性能模型
bash
DNS 查询延迟 = 网络延迟 + 解析器处理时间 + (缓存未命中时的迭代查询时间)
优化策略:
┌──────────────────────────────────────────────────────────────┐
│ │
│ 本地缓存 (dnsmasq/systemd-resolved) │
│ ↓ 缓存命中率 >90% → 延迟 < 1ms │
│ │
│ Anycast 就近接入 (1.1.1.1 / 8.8.8.8) │
│ ↓ 自动路由到最近节点 │
│ │
│ DNS 预解析 (dns-prefetch) │
│ ↓ 浏览器提前解析, 用户点击时无需等待 │
│ │
│ CDN 集成 │
│ ↓ 基于 DNS 返回最近节点的 IP │
│ │
└──────────────────────────────────────────────────────────────┘
6.2 上机实操: dnsmasq 本地缓存
dnsmasq 是一个轻量级 DNS 转发器和 DHCP 服务器, 常用于本地 DNS 缓存。
bash
# 安装 dnsmasq
$ apt-get install -y dnsmasq
$ dnsmasq -v
Dnsmasq version 2.90
配置 /etc/dnsmasq.d/dns-test.conf:
ini
port=5353 # 监听端口 (避免与 systemd-resolved 冲突)
cache-size=1000 # 缓存 1000 条 DNS 记录
server=8.8.8.8 # 上游 DNS 1
server=1.1.1.1 # 上游 DNS 2
log-queries # 记录查询日志 (调试用)
bash
$ systemctl restart dnsmasq
缓存效果验证:
bash
# 首次查询 (Cache Miss)
$ dig @127.0.0.1 -p 5353 baidu.com +stats | grep "Query time"
;; Query time: 2 msec
# 二次查询 (Cache Hit)
$ dig @127.0.0.1 -p 5353 baidu.com +stats | grep "Query time"
;; Query time: 0 msec ← 0ms! 本地内存缓存命中
缓存命中率分析:
makefile
首次查询: 2ms (网络往返 Cloudflare)
二次查询: 0ms (内存缓存命中)
差异: 2ms (消除了一次网络往返)
6.3 上机实操: DNS 查询性能基准测试
使用 Python 脚本对 10 个热门域名进行 3 轮 A 记录查询基准测试:
实验结果 (tcpip-01, 本地解析器):
| 域名 | Min (ms) | Avg (ms) | Max (ms) |
|---|---|---|---|
| baidu.com | 19.0 | 19.5 | 20.0 |
| aliyun.com | 18.9 | 19.5 | 20.6 |
| qq.com | 19.0 | 19.9 | 20.6 |
| google.com | 19.4 | 20.1 | 20.9 |
| zhihu.com | 19.6 | 23.7 | 31.7 |
| 163.com | 20.5 | 20.7 | 21.1 |
| sohu.com | 21.1 | 26.6 | 37.1 |
| bilibili.com | 19.4 | 19.8 | 20.3 |
| github.com | 19.8 | 19.8 | 19.9 |
| stackoverflow.com | 19.1 | 19.7 | 20.5 |
| 平均值 | 19.7 | 20.9 | --- |
30 次查询, 平均 20.9ms/次 --- 本地缓存+华为云内网 DNS 组合性能良好。
外部解析器延迟对比 (baidu.com, 3次平均):
| 解析器 | IP | Avg (ms) | 评价 |
|---|---|---|---|
| Cloudflare | 1.1.1.1 | 22.1 | ★★★★★ 最优 |
| 8.8.8.8 | 20.6 | ★★★★★ 最优 | |
| 114DNS | 114.114.114.114 | 55.8 | ★★★ 一般 |
| Quad9 | 9.9.9.9 | 57.1 | ★★ 较慢 |
| AliDNS | 223.5.5.5 | 66.4 | ★ 跨境延迟大 |
结论: 在香港 ECS 上, Cloudflare (1.1.1.1) 和 Google (8.8.8.8) 延迟最低 (~20ms), 因为两者在香港都有节点。AliDNS (223.5.5.5) 服务器在中国大陆, 跨境的 66ms 主要是网络延迟。
6.4 DNS 预解析 (DNS Prefetch)
浏览器可以在用户点击链接前提前完成 DNS 解析:
html
<!-- HTML 级别 DNS 预解析 -->
<link rel="dns-prefetch" href="//cdn.example.com">
<link rel="dns-prefetch" href="//api.example.com">
<link rel="dns-prefetch" href="//analytics.example.com">
css
用户打开页面
│
├── 浏览器解析 HTML, 发现 dns-prefetch
│
├── 后台静默解析 cdn.example.com → 1.2.3.4
│
└── 用户 3 秒后点击 CDN 链接
→ 无需 DNS 查询, 直接连接 1.2.3.4 ✓
性能收益: DNS 预解析可节省 20-120ms (一次 DNS 查询的 RTT)。
第七章: 云 DNS 服务实战
7.1 主流云 DNS 服务对比
| 服务 | 提供商 | SLA | 特点 |
|---|---|---|---|
| Route 53 | AWS | 100% | 与 AWS 深度集成, 流量路由策略丰富 |
| Cloudflare DNS | Cloudflare | 100% | 全球最大 Anycast 网络, 免费 CDN 集成 |
| Google Cloud DNS | 100% | 与 GCP 集成, Anycast | |
| Azure DNS | Microsoft | 100% | 与 Azure 深度集成 |
| AliDNS | 阿里云 | 99.99% | 中国大陆解析最优 |
7.2 Cloudflare DNS API 操作
bash
# 获取 Zone ID
curl -X GET "https://api.cloudflare.com/client/v4/zones?name=example.com" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json"
# 响应示例:
{
"result": [{
"id": "023e105f4ecef8ad9ca31a8372d0c353",
"name": "example.com",
"status": "active"
}]
}
# 创建 DNS A 记录
curl -X POST "https://api.cloudflare.com/client/v4/zones/{ZONE_ID}/dns_records" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"type": "A",
"name": "test",
"content": "192.168.1.100",
"ttl": 120,
"proxied": false
}'
Cloudflare DNS 代理模式 (proxied):
vbnet
proxied: false (仅 DNS):
用户 → DNS 解析 → 真实 IP → 直接连接服务器
proxied: true (橙色云朵):
用户 → DNS 解析 → Cloudflare CDN IP → Cloudflare 代理 → 真实服务器
↑
DDoS 防护 / CDN 缓存 / WAF
7.3 Terraform 管理 DNS (DNS as Code)
hcl
# main.tf
provider "cloudflare" {
api_token = var.cloudflare_api_token
}
resource "cloudflare_record" "www" {
zone_id = var.zone_id
name = "www"
value = "192.168.1.100"
type = "A"
ttl = 3600
proxied = true
}
resource "cloudflare_record" "api" {
zone_id = var.zone_id
name = "api"
value = "api-gateway.example.com"
type = "CNAME"
ttl = 300
}
bash
terraform init
terraform plan
terraform apply
第八章: DNS 故障排查
8.1 上机实操: tcpdump 抓包分析 DNS
bash
# 抓取 DNS 流量到文件
$ tcpdump -i any -n port 53 -w /tmp/dns_capture.pcap &
# 同时生成 DNS 查询流量
$ dig baidu.com A +short
$ dig google.com AAAA +short
$ dig microsoft.com MX +short
# 等待抓包完成
$ fg # 或 Ctrl+C 停止 tcpdump
tcpdump 实测输出 (DNS 协议解析):
less
# systemd-resolved 本地查询 (lo 接口)
13:19:54.179644 lo In IP 127.0.0.1.51555 > 127.0.0.53.53:
45987+ [1au] A? baidu.com. (50)
13:19:54.179806 lo In IP 127.0.0.53.53 > 127.0.0.1.51555:
45987 4/0/1 A 124.237.177.164, A 111.63.65.103,
A 110.242.74.102, A 111.63.65.247 (102)
# 上游 DNS 查询 (eth0 接口) --- 缓存未命中时
13:19:54.200251 eth0 Out IP 192.168.0.5.52792 > 100.125.3.250.53:
40011+ [1au] AAAA? google.com. (39)
13:19:54.200682 eth0 In IP 100.125.3.250.53 > 192.168.0.5.52792:
40011 1/0/1 AAAA 2404:6800:4005:812::200e (67)
tcpdump DNS 字段解析:
less
127.0.0.1.51555 > 127.0.0.53.53: 45987+ [1au] A? baidu.com. (50)
↑ 源端口 ↑ 目的端口 ↑ ID ↑ EDNS ↑ 查询类型 ↑域名 ↑包大小
ruby
127.0.0.53.53 > 127.0.0.1.51555: 45987 4/0/1 A ...
↑ 响应 ↑ 匹配 ID ↑ 回答/权威/附加计数
抓包数据揭示的架构:
erlang
dig (客户端) systemd-resolved 华为云 DNS
127.0.0.1:随机端口 127.0.0.53:53 100.125.3.250:53
│ │ │
│── query baidu.com A ──────────▶│ │
│ │── (缓存命中或转发) │
│◀── answer 4 IPs ──────────────│ │
│ │ │
│── query google.com AAAA ─────▶│ │
│ │── query (缓存未命中) ─────────▶│
│ │◀── answer ───────────────────│
│◀── answer ────────────────────│ │
8.2 DNS 故障排查命令速查
bash
# 1. 检查域名是否存在
dig +short example.com A
# 2. 检查 NS 服务器是否可达
dig +short example.com NS
dig @ns1.example.com example.com SOA
# 3. 检查域名委派一致性
dig +trace +nodnssec example.com
# 4. 检查 DNSSEC 配置
dig +dnssec example.com SOA
# 5. 带超时和重试的快速检查
dig +short +time=1 +tries=1 example.com
# 6. 仅显示回答部分
dig +nocmd example.com any +noall +answer
# 7. 检查反向解析
dig -x 8.8.8.8
# 8. 监听 DNS 流量
tcpdump -i any -n port 53
8.3 常见 DNS 问题诊断流程
ruby
问题: 网站打不开, 怀疑 DNS 问题
步骤 1: 确认是否为 DNS 问题
$ dig example.com
→ NXDOMAIN → 域名不存在或拼写错误
→ SERVFAIL → DNS 服务器故障
→ NOERROR (有 IP) → DNS 正常, 问题在网络/应用层
步骤 2: 检查 NS 委派
$ dig +trace example.com
→ 在哪一步停止? 根? TLD? 权威?
步骤 3: 检查权威服务器
$ dig @ns1.example.com example.com SOA
→ 权威服务器是否响应? Serial 是否合理?
步骤 4: 清除本地缓存后重试
$ resolvectl flush-caches
$ dig example.com
步骤 5: 更换 DNS 解析器对比
$ dig @1.1.1.1 example.com
$ dig @8.8.8.8 example.com
→ 是否所有解析器都失败? 特定解析器的问题?
8.4 DNS 响应状态码
| 状态码 | 含义 | 常见原因 |
|---|---|---|
| NOERROR (0) | 查询成功 | --- |
| FORMERR (1) | 格式错误 | 客户端发送了格式错误的查询 |
| SERVFAIL (2) | 服务器失败 | 权威服务器无响应、DNSSEC 验证失败 |
| NXDOMAIN (3) | 域名不存在 | 域名拼写错误、未注册 |
| NOTIMP (4) | 未实现 | 请求的查询类型不被支持 |
| REFUSED (5) | 拒绝 | 服务器策略禁止响应(如未授权递归) |
第九章: DNS 与容器化
9.1 Kubernetes DNS 架构 (CoreDNS)
perl
┌──────────────────────────────────────────────────────────────┐
│ Kubernetes DNS 服务发现 │
│ │
│ Pod A (default ns) CoreDNS (kube-system) │
│ │ │ │
│ │ nslookup my-svc │ │
│ │───────────────────────────▶│ │
│ │ │ my-svc.default.svc.cluster.local
│ │ │ → ClusterIP │
│ │◀───────────────────────────│ │
│ │ │ │
│ │ nslookup my-svc.prod │ │
│ │───────────────────────────▶│ │
│ │ │ my-svc.prod.svc.cluster.local
│ │ │ → ClusterIP (跨命名空间) │
│ │◀───────────────────────────│ │
└──────────────────────────────────────────────────────────────┘
Kubernetes DNS 命名规范:
xml
<service-name>.<namespace>.svc.<cluster-domain>
示例:
my-app.default.svc.cluster.local
└─服务名─┘ └命名空间┘ └──固定后缀──┘
CoreDNS ConfigMap 核心配置:
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf # 上游 DNS
cache 30
loop
reload
loadbalance
}
CoreDNS 插件说明:
| 插件 | 作用 |
|---|---|
kubernetes |
基于 K8s API 提供服务发现 |
forward |
将非集群域名转发到上游 DNS |
cache |
缓存查询结果 (30秒) |
prometheus |
暴露监控指标 |
loadbalance |
对多 A 记录响应轮询排序 |
9.2 Docker 自定义 DNS
bash
# 指定 DNS 服务器
docker run --dns=8.8.8.8 --dns=1.1.1.1 nginx
# 指定 DNS 搜索域
docker run --dns=8.8.8.8 --dns-search=example.com nginx
# 在 docker-compose.yml 中
services:
web:
image: nginx
dns:
- 8.8.8.8
- 1.1.1.1
dns_search:
- example.com
Docker DNS 解析优先级:
markdown
1. 容器内 /etc/hosts (--add-host)
2. 内置 DNS 服务器 (127.0.0.11) --- 容器间服务发现
3. --dns 指定的外部 DNS 服务器
4. 宿主机 /etc/resolv.conf
9.3 Kubernetes DNS 测试
bash
# 创建临时 Pod 测试 DNS
kubectl run -it --rm debug --image=busybox:1.28 --restart=Never -- sh
# 测试集群内 DNS
nslookup kubernetes.default.svc.cluster.local
# 测试外部 DNS
nslookup baidu.com
# 查看 CoreDNS Pod
kubectl get pods -n kube-system -l k8s-app=kube-dns
# 查看 CoreDNS 日志
kubectl logs -n kube-system deployment/coredns
第十章: DNS 自动化与 DevOps
10.1 DNS 即代码 (DNS as Code)
将 DNS 配置纳入版本控制, 实现可审计、可回滚、可自动化的 DNS 管理。
scss
┌──────────────────────────────────────────────────────────────┐
│ DNS as Code 工作流 │
│ │
│ 开发者修改 DNS 配置 (Git PR) │
│ │ │
│ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Git Repo │────▶│ CI/CD │────▶│ Cloud API│ │
│ │ (TF/Ansi)│ │ (GitHub) │ │ (CF/AWS) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ │ PR Review │ 自动化测试 │ 应用变更 │
│ │ (人工审核) │ (dig 验证) │ (API 调用) │
│ │
└──────────────────────────────────────────────────────────────┘
10.2 Ansible 管理 BIND DNS
yaml
# playbook.yml
- hosts: dns_servers
vars:
domain: example.com
records:
- { name: "www", type: "A", value: "192.168.1.101" }
- { name: "api", type: "A", value: "192.168.1.102" }
- { name: "mail", type: "CNAME", value: "www.example.com." }
tasks:
- name: Deploy zone file from template
template:
src: db.example.com.j2
dest: /etc/bind/db.{{ domain }}
owner: root
group: bind
mode: '0644'
notify: reload bind9
- name: Validate zone file
command: named-checkzone {{ domain }} /etc/bind/db.{{ domain }}
register: check_result
changed_when: false
- name: Display validation result
debug:
msg: "{{ check_result.stdout }}"
handlers:
- name: reload bind9
service:
name: bind9
state: reloaded
10.3 GitHub Actions 自动化 DNS
yaml
# .github/workflows/dns-update.yml
name: Update DNS Records
on:
push:
branches: [main]
paths:
- 'dns/**'
jobs:
validate-and-apply:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Validate DNS configuration
run: |
# Terraform validate
cd dns/
terraform init -backend=false
terraform validate
- name: Apply DNS changes
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
CF_ZONE_ID: ${{ secrets.CF_ZONE_ID }}
run: |
cd dns/
terraform init
terraform apply -auto-approve
- name: Verify DNS propagation
run: |
sleep 30 # 等待传播
dig +short www.example.com @1.1.1.1
10.4 DNS 配置版本控制
bash
# 初始化 DNS 配置仓库
git init dns-config
cd dns-config/
# 结构化目录
mkdir -p zones/example.com zones/internal
mkdir -p terraform/ ansible/
# 添加 BIND 区域文件
cp /etc/bind/db.example.com zones/example.com/
# 提交
git add .
git commit -m "feat: initial DNS configuration for example.com"
git tag v1.0.0
# 后续变更
vim zones/example.com/db.example.com # 修改 Serial
git add . && git commit -m "fix: add api.example.com A record"
git tag v1.0.1
附录
附录 A: 实验环境总览
yaml
┌─────────────────────────────────────────────────────────────┐
│ ecs-ee63 集群 (华为云香港) │
├──────────┬─────────────────┬──────────────┬─────────────────┤
│ 主机名 │ 公网 IP │ 内网 IP │ DNS 角色 │
├──────────┼─────────────────┼──────────────┼─────────────────┤
│ tcpip-01 │ 119.8.59.15 │ 192.168.0.5 │ BIND9 主服务器 │
│ tcpip-02 │ 119.8.110.76 │ 192.168.0.207│ DNS 客户端 │
│ tcpip-03 │ 150.40.239.207 │ 192.168.0.111│ DNS 客户端 │
└──────────┴─────────────────┴──────────────┴─────────────────┘
软件版本:
BIND: 9.18.39-0ubuntu0.24.04.5-Ubuntu
DiG: 9.18.39-0ubuntu0.24.04.5-Ubuntu
Dnsmasq: 2.90
OS: Ubuntu 24.04 LTS
Kernel: 6.8.0
附录 B: 关键实验数据汇总
| 实验 | 关键结果 |
|---|---|
| baidu.com A 记录 | 4 个 IP (110.242.74.102, 111.63.65.103/247, 124.237.177.164) |
| baidu.com NS 记录 | 5 个: dns, ns2-4, ns7.baidu.com |
| baidu.com SOA | Serial=2012151067, TTL=600s |
| www.baidu.com CNAME | www.a.shifen.com (CDN 调度) |
| dig +trace | 3 步: Root(1ms)→TLD(40ms)→权威(219ms+4ms) = 264ms |
| dnsmasq 缓存 | Cache miss 2ms → Cache hit 0ms |
| BIND9 本地区域 | example.local 配置成功, checkzone OK |
| tcpdump 抓包 | 确认 systemd-resolved(127.0.0.53)→华为云 DNS(100.125.3.250) |
| 性能基准 (10域名×3) | 平均 20.9ms/查询, 本地缓存 |
| Cloudflare 延迟 | avg=22.1ms (香港节点) |
| AliDNS 延迟 | avg=66.4ms (跨境) |
附录 C: Dig 命令速查
| 命令 | 作用 |
|---|---|
dig domain |
基础查询 (A 记录) |
dig domain A |
指定查询 A 记录 |
dig domain ANY |
查询所有记录类型 |
dig domain +short |
简洁输出 (仅结果) |
dig domain +trace |
追踪解析过程 |
dig domain +dnssec |
查询 DNSSEC 签名 |
dig -x IP |
反向查询 (PTR) |
dig @server domain |
指定 DNS 服务器 |
dig domain +stats |
显示统计信息 |
dig domain +noall +answer |
仅显示回答部分 |
dig domain +tcp |
强制使用 TCP |
dig domain +time=N +tries=M |
超时和重试控制 |
附录 D: DNS 记录类型速查
| 记录 | 全称 | 格式示例 | 用途 |
|---|---|---|---|
| A | Address | www A 1.2.3.4 |
IPv4 地址 |
| AAAA | IPv6 Address | www AAAA 2001:db8::1 |
IPv6 地址 |
| CNAME | Canonical Name | www CNAME host.example.com. |
别名 |
| MX | Mail Exchange | @ MX 10 mail.example.com. |
邮件服务器 |
| TXT | Text | @ TXT "v=spf1 ..." |
文本信息 |
| NS | Name Server | @ NS ns1.example.com. |
权威服务器 |
| SOA | Start of Authority | @ SOA ns1 hostmaster (serial ...) |
管理信息 |
| PTR | Pointer | 4.3.2.1 PTR host.example.com. |
反向解析 |
| SRV | Service | _http SRV 0 5 80 www |
服务定位 |
| CAA | Certification Authority | @ CAA 0 issue "letsencrypt.org" |
证书颁发限制 |
| DS | Delegation Signer | @ DS keytag alg digest-type digest |
DNSSEC 委派 |
| RRSIG | RR Signature | DNSSEC 签名记录 | DNSSEC 验证 |
附录 E: 公共 DNS 解析器速查
| 名称 | IPv4 | IPv6 | DoH URL | 特点 |
|---|---|---|---|---|
| Cloudflare | 1.1.1.1 / 1.0.0.1 | 2606:4700::1111 | https://1.1.1.1/dns-query |
快, 隐私优先 |
| 8.8.8.8 / 8.8.4.4 | 2001:4860::8888 | https://dns.google/dns-query |
稳定, 全球覆盖 | |
| Quad9 | 9.9.9.9 / 149.112.112.112 | 2620:fe::fe | https://dns.quad9.net/dns-query |
安全过滤 |
| OpenDNS | 208.67.222.222 | 2620:119:35::35 | --- | 内容过滤 |
| AliDNS | 223.5.5.5 / 223.6.6.6 | 2400:3200::1 | --- | 中国大陆最优 |
| 114DNS | 114.114.114.114 | --- | --- | 中国大陆 |
| DNSPod | 119.29.29.29 | --- | https://doh.pub/dns-query |
腾讯云 DNS |
附录 F: BIND9 配置参数速查
named.conf 关键选项:
| 选项 | 默认值 | 说明 |
|---|---|---|
directory |
/var/cache/bind |
工作目录 |
listen-on |
{ any; } |
监听地址 |
listen-on-v6 |
{ any; } |
IPv6 监听 |
allow-query |
{ any; } |
允许查询的来源 |
allow-transfer |
{ none; } |
允许区域传输的来源 |
recursion |
yes |
是否提供递归查询 |
allow-recursion |
{ localnets; } |
允许递归的来源 |
forwarders |
{} |
上游转发器 |
dnssec-validation |
auto |
DNSSEC 验证模式 |
version |
(真实版本号) | 版本字符串 |
SOA 记录参数建议:
| 参数 | 小型站点 | 中型站点 | 大型/CDN |
|---|---|---|---|
| Refresh | 3600 (1h) | 3600 (1h) | 900 (15min) |
| Retry | 1800 (30min) | 900 (15min) | 300 (5min) |
| Expire | 604800 (7d) | 1209600 (14d) | 604800 (7d) |
| Minimum TTL | 86400 (1d) | 3600 (1h) | 300 (5min) |
附录 G: DNS 查询头 Flags 详解
ini
dig 输出中的 flags 字段:
flags: qr rd ra
qr = Query Response 1=响应, 0=查询
aa = Authoritative Answer 权威回答 (来自权威服务器)
tc = Truncated 响应被截断 (需 TCP 重试)
rd = Recursion Desired 客户端请求递归
ra = Recursion Available 服务器支持递归
ad = Authenticated Data DNSSEC 验证通过
cd = Checking Disabled 禁用 DNSSEC 验证
附录 H: 学习资源
官方文档:
- BIND9 Administrator Reference Manual
- Cloudflare DNS Learning Center
- RFC 1034: Domain Names - Concepts and Facilities
- RFC 1035: Domain Names - Implementation and Specification
- RFC 4033-4035: DNSSEC
- RFC 8484: DNS over HTTPS (DoH)
- RFC 7858: DNS over TLS (DoT)
书籍推荐:
- 《DNS and BIND》(第5版) --- Cricket Liu, Paul Albitz (O'Reilly)
- 《DNS Security: Defending the Domain Name System》
- 《Alternative DNS Servers: Choice and Deployment》
在线工具:
- DNSViz --- DNS 可视化分析
- MXToolbox --- DNS/邮件诊断
- DNSSEC Analyzer
- whatsmydns.net --- 全球 DNS 传播检查
附录 I: 技能评估标准
| 能力维度 | 权重 | 评估标准 |
|---|---|---|
| 基础概念理解 | 20% | DNS 层级结构、记录类型、解析过程 |
| 实际操作能力 | 40% | dig/nslookup/tcpdump 使用, BIND9 配置, 故障排查 |
| 安全知识 | 25% | DNSSEC、DoH/DoT、DNS 攻击防护 |
| 架构设计 | 15% | DNS 高可用、CDN 集成、多环境管理 |
学习建议: 按章节顺序逐步学习, 每个知识点配合实操案例。建立自己的实验环境, 从本地 BIND9 配置开始, 逐步扩展到云 DNS 服务和容器化部署。关注 DNS 协议最新发展 (DNS over QUIC/HTTP3 等)。
安全提醒: 所有实验在授权环境中进行。不要对非授权域名进行压力测试。定期更新 DNS 软件版本以修复安全漏洞。生产环境务必启用 DNSSEC 和访问控制。
文档版本: v1.0 | 生成时间: 2026-06-02 | 实验集群: ecs-ee63 (华为云香港)