找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4118

积分

0

好友

580

主题
发表于 13 小时前 | 查看: 5| 回复: 0

一、DNS核心原理深度剖析

1.1 DNS是什么?为什么如此重要?

┌─────────────────────────────────────────────────────────────────┐
│                        DNS 在互联网中的位置                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   用户输入              DNS 解析              建立连接           │
│  ┌────────┐          ┌──────────┐         ┌──────────┐        │
│  │ www.   │ ───────▶ │  DNS     │ ──────▶ │  192.    │        │
│  │ example│          │  Server  │         │  0.2.1   │        │
│  │ .com   │          │          │         │          │        │
│  └────────┘          └──────────┘         └──────────┘        │
│     │                      │                      │            │
│     │ 域名(人类可读)      │ 查询请求              │ IP 地址     │
│     │                      │                      │            │
└─────────────────────────────────────────────────────────────────┘

没有 DNS,互联网将退回到 IP 地址时代!

DNS 的核心作用:

  • 域名 → IP 地址映射(正向解析)
  • IP 地址 → 域名映射(反向解析)
  • 邮件服务器定位(MX 记录)
  • 服务发现(SRV 记录)
  • 域名别名(CNAME 记录)

1.2 DNS 层次结构

                        ┌─────────┐
                        │   .     │  根域名
                        │ (Root)  │
                        └────┬────┘
                             │
        ┌────────────────────┼────────────────────┐
        │                    │                    │
        ▼                    ▼                    ▼
   ┌─────────┐         ┌─────────┐         ┌─────────┐
   │   .com  │         │   .org  │         │   .cn   │  顶级域名 (TLD)
   └────┬────┘         └────┬────┘         └────┬────┘
        │                    │                    │
        │         ┌──────────┴──────────┐        │
        │         │                     │        │
        ▼         ▼                     ▼        ▼
   ┌─────────┐ ┌─────────┐       ┌─────────┐ ┌─────────┐
   │ google  │ │ example │       │ example │ │ 163     │  二级域名
   └─────────┘ └────┬────┘       └────┬────┘ └─────────┘
                    │                  │
                    ▼                  ▼
               ┌─────────┐       ┌─────────┐
               │   www   │       │   mail  │  主机名
               └─────────┘       └─────────┘

完整域名:www.example.com.

1.3 DNS 记录类型详解

┌─────────────────────────────────────────────────────────────────┐
│                      常见 DNS 记录类型                            │
├──────────┬──────────────────────────────────────────────────────┤
│ 记录类型  │ 说明与示例                                           │
├──────────┼──────────────────────────────────────────────────────┤
│ A        │ IPv4 地址记录                                         │
│          │ example.com. 300 IN A 192.0.2.1                      │
├──────────┼──────────────────────────────────────────────────────┤
│ AAAA     │ IPv6 地址记录                                         │
│          │ example.com. 300 IN AAAA 2001:db8::1                 │
├──────────┼──────────────────────────────────────────────────────┤
│ CNAME    │ 别名记录(Canonical Name)                            │
│          │ www.example.com. 300 IN CNAME example.com.           │
├──────────┼──────────────────────────────────────────────────────┤
│ MX       │ 邮件交换记录(Mail Exchange)                         │
│          │ example.com. 300 IN MX 10 mail.example.com.          │
├──────────┼──────────────────────────────────────────────────────┤
│ NS       │ 域名服务器记录(Name Server)                         │
│          │ example.com. 300 IN NS ns1.example.com.              │
├──────────┼──────────────────────────────────────────────────────┤
│ TXT      │ 文本记录(常用于 SPF、DKIM 验证)                     │
│          │ example.com. 300 IN TXT "v=spf1 include:_spf.google.com ~all" │
├──────────┼──────────────────────────────────────────────────────┤
│ PTR      │ 反向解析记录(Pointer)                               │
│          │ 1.2.0.192.in-addr.arpa. 300 IN PTR example.com.      │
├──────────┼──────────────────────────────────────────────────────┤
│ SRV      │ 服务定位记录(Service)                               │
│          │ _http._tcp.example.com. 300 IN SRV 10 5 80 www.example.com. │
├──────────┼──────────────────────────────────────────────────────┤
│ SOA      │ 起始授权记录(Start of Authority)                    │
│          │ 包含域管的权威信息、序列号、刷新间隔等                 │
└──────────┴──────────────────────────────────────────────────────┘

1.4 DNS 查询流程详解

┌─────────────────────────────────────────────────────────────────┐
│                    DNS 递归查询完整流程                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  客户端                                                         │
│    │                                                            │
│    │ 1. 查询 www.example.com                                    │
│    ▼                                                            │
│  ┌─────────┐                                                    │
│  │ 本地    │ 2. 有缓存?───有──▶ 返回结果                       │
│  │ DNS 缓存 │           │                                      │
│  └─────────┘           无                                       │
│    │                 │                                          │
│    │ 3. 查询本地 DNS 服务器  │                                  │
│    ▼                 │                                          │
│  ┌──────────────────────┴──────────────────────────────────┐   │
│  │                    本地 DNS 服务器                         │   │
│  │    ┌─────────┐                                           │   │
│  │    │ 递归    │ 4. 查询根服务器 (.com 在哪里?)             │   │
│  │    │ 解析器  │      ▼                                     │   │
│  │    └─────────┘  ┌─────────┐                              │   │
│  │                  │ 根服务器 │ 5. .com 在 192.5.6.30         │   │
│  │                  └─────────┘                              │   │
│  │                       │                                     │   │
│  │                       ▼                                     │   │
│  │                  ┌─────────┐                              │   │
│  │                  │ .com    │ 6. example.com 在 192.0.2.1    │   │
│  │                  │ TLD 服务器│                              │   │
│  │                  └─────────┘                              │   │
│  │                       │                                     │   │
│  │                       ▼                                     │   │
│  │                  ┌─────────┐                              │   │
│  │                  │ 权威    │ 7. www.example.com = 93.184.216.34 │
│  │                  │ DNS 服务器│                              │   │
│  │                  └─────────┘                              │   │
│  │                       │                                     │   │
│  │ 8. 返回结果 ◀────────┘                                     │   │
│  └───────────────────────────────────────────────────────────┘   │
│    │                                                            │
│    │ 9. 返回结果 + 缓存                                          │
│    ▼                                                            │
│  客户端获得 IP: 93.184.216.34                                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

总耗时:通常 20-100ms(有缓存则 <1ms)

二、Linux DNS 配置详解

2.1 /etc/resolv.conf - DNS 配置核心文件

# 查看当前 DNS 配置
cat /etc/resolv.conf

# 典型配置示例
nameserver 8.8.8.8        # 首选 DNS 服务器
nameserver 8.8.4.4        # 备用 DNS 服务器
nameserver 1.1.1.1        # 第三 DNS 服务器(最多 3 个)
search example.com local  # 搜索域(域名补全)
options timeout:2         # 查询超时时间(秒)
options attempts:3        # 重试次数
options rotate            # 轮询使用 DNS 服务器
options ndots:1           # 点号阈值(决定何时使用搜索域)

配置参数详解

┌─────────────────────────────────────────────────────────────────┐
│                    /etc/resolv.conf 参数详解                      │
├──────────────────┬──────────────────────────────────────────────┤
│ 参数              │ 说明                                         │
├──────────────────┼──────────────────────────────────────────────┤
│ nameserver       │ DNS 服务器 IP(最多 3 个,按顺序使用)           │
│ search           │ 搜索域列表(主机名补全用)                     │
│ domain           │ 本地域名(与 search 互斥)                      │
│ options timeout  │ 查询超时,默认 5 秒                            │
│ options attempts │ 重试次数,默认 2 次                            │
│ options rotate   │ 轮询 nameserver(负载均衡)                    │
│ options ndots    │ 点号阈值,决定搜索域使用策略                    │
│ options edns0    │ 启用 EDNS0 扩展(支持更大响应)                  │
│ options single-request │ 串行查询(避免 IPv4/IPv6 竞争)          │
└──────────────────┴──────────────────────────────────────────────┘

ndots 参数详解(重要!)

# ndots 决定域名中点号数量达到多少时,直接使用完整域名查询
# 否则先尝试搜索域补全

# 示例:ndots:1
# 查询 “host“(0 个点,小于 ndots)
#   1. 先查 host.example.com
#   2. 再查 host.local
#   3. 最后查 host.

# 查询 “host.sub“(1 个点,等于 ndots)
#   1. 直接查 host.sub.
#   2. 失败后再尝试搜索域

# 生产建议:
options ndots:1    # 默认值,适合大多数场景
options ndots:2    # 减少不必要的搜索域查询
options ndots:0    # 总是使用完整域名

2.2 /etc/nsswitch.conf - 名称解析顺序

# 查看名称解析配置
cat /etc/nsswitch.conf

# hosts 行配置(关键!)
hosts:      files dns myhostname
#           │     │    │
#           │     │    └── 本机主机名
#           │     └────── DNS 查询
#           └──────────── /etc/hosts 文件

# 解析顺序:/etc/hosts → DNS → 本机主机名

# 常见问题:
# 如果配置为:hosts: dns files
# 会导致即使 /etc/hosts 有配置,也会先查 DNS
# 可能引起解析延迟或失败

2.3 /etc/hosts - 本地主机名映射

# 查看本地 hosts 配置
cat /etc/hosts

# 典型配置
127.0.0.1   localhost localhost.localdomain
::1         localhost localhost.localdomain ip6-localhost ip6-loopback
fe80::1     ip6-allnodes

# 自定义主机名映射
192.168.1.10    api.example.com api
192.168.1.11    db.example.com db
192.168.1.12    cache.example.com cache

# 屏蔽域名(广告拦截)
0.0.0.0     ads.example.com
0.0.0.0     tracker.example.com

hosts 与 DNS 优先级

┌─────────────────────────────────────────────────────────────────┐
│                    名称解析优先级                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. /etc/hosts(本地文件,最快)                                 │
│     │                                                           │
│     ▼                                                           │
│  2. DNS 查询(网络请求,较慢)                                   │
│     │                                                           │
│     ▼                                                           │
│  3. mDNS/LLMNR(本地多播,备用)                                 │
│                                                                 │
│ 通过 nsswitch.conf 控制顺序:                                    │
│  hosts: files dns    # hosts 优先(推荐)                         │
│  hosts: dns files    # DNS 优先(不推荐)                          │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

2.4 systemd-resolved - 现代 Linux DNS 管理

# 检查 systemd-resolved 状态
systemctl status systemd-resolved

# 查看 DNS 配置状态
resolvectl status

# 查看 DNS 缓存统计
resolvectl statistics

# 刷新 DNS 缓存
resolvectl flush-caches

# 查询特定域名
resolvectl query www.example.com

# 查看当前 DNS 服务器
resolvectl | grep “DNS Servers“

systemd-resolved 配置

# /etc/systemd/resolved.conf
[Resolve]
# DNS 服务器列表(空格分隔)
DNS=8.8.8.8 1.1.1.1 9.9.9.9

# 备用 DNS 服务器
FallbackDNS=208.67.222.222 208.67.220.220

# 搜索域
Domains=example.com local

# LLMNR 支持(本地链路多播名称解析)
LLMNR=yes

# 多播 DNS
MulticastDNS=yes

# DNSSEC 验证
DNSSEC=yes

# DNS over TLS(加密 DNS)
#DNSOverTLS=no

# 缓存大小(0=禁用,其他=条目数)
Cache=yes
CacheSize=15MB

常见问题:/etc/resolv.conf 被覆盖

# 问题:修改 /etc/resolv.conf 后重启被还原
# 原因:systemd-resolved 或 NetworkManager 管理

# 解决方案 1:修改 systemd-resolved 配置
vim /etc/systemd/resolved.conf
# 修改后重启服务
systemctl restart systemd-resolved

# 解决方案 2:创建符号链接
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

# 解决方案 3:禁用 systemd-resolved 管理
# 编辑 NetworkManager 配置
vim /etc/NetworkManager/NetworkManager.conf
[main]
dns=none  # 禁用 NM 的 DNS 管理

# 解决方案 4:锁定文件(不推荐)
chattr +i /etc/resolv.conf

2.5 NetworkManager DNS 管理

# 查看当前网络连接
nmcli connection show

# 查看 DNS 配置
nmcli device show eth0 | grep DNS

# 手动设置 DNS
nmcli connection modify eth0 ipv4.dns “8.8.8.8 8.8.4.4“
nmcli connection modify eth0 ipv4.ignore-auto-dns yes
nmcli connection up eth0

# 自动获取 DNS(DHCP)
nmcli connection modify eth0 ipv4.ignore-auto-dns no
nmcli connection up eth0

# 删除 DNS 配置
nmcli connection modify eth0 ipv4.dns ““

三、DNS 解析工具与排查实战

3.1 dig - DNS 查询利器

# 基础查询
dig www.example.com

# 指定 DNS 服务器查询
dig @8.8.8.8 www.example.com
dig @ns1.example.com www.example.com

# 指定记录类型
dig example.com MX           # 邮件记录
dig example.com TXT          # 文本记录
dig example.com NS           # 域名服务器
dig example.com SOA          # 起始授权
dig example.com AAAA         # IPv6 记录
dig -x 192.0.2.1             # 反向查询

# 简洁输出(适合脚本)
dig +short www.example.com
dig +noall +answer www.example.com

# 完整输出
dig +noall +answer +authority +additional www.example.com

# 追踪解析链
dig +trace www.example.com

# 查询统计
dig +stats www.example.com

# 批量查询
dig -f domains.txt

# 示例输出解析
$ dig www.example.com

; <<>> DiG 9.16.1 <<>> www.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512

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

;; ANSWER SECTION:
www.example.com.    300    IN    CNAME    example.com.
example.com.        300    IN    A    93.184.216.34

;; Query time: 25 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sat Jan 15 10:00:00 UTC 2024
;; MSG SIZE  rcvd: 68

3.2 nslookup - 传统 DNS 工具

# 基础查询
nslookup www.example.com

# 指定 DNS 服务器
nslookup www.example.com 8.8.8.8

# 交互模式
nslookup
> server 8.8.8.8          # 切换 DNS 服务器
> set type=MX             # 设置查询类型
> example.com
> set type=TXT
> example.com
> exit

# 查询所有记录
nslookup -query=ANY example.com

3.3 host - 简洁 DNS 工具

# 基础查询
host www.example.com

# 指定记录类型
host -t MX example.com
host -t TXT example.com
host -t NS example.com

# 反向查询
host 93.184.216.34

# 详细输出
host -a www.example.com

# 简洁输出
host -w www.example.com

3.4 工具对比

┌─────────────────────────────────────────────────────────────────┐
│                    DNS 查询工具对比                               │
├──────────┬──────────────────────────────────────────────────────┤
│ 工具      │ 特点与适用场景                                        │
├──────────┼──────────────────────────────────────────────────────┤
│ dig      │ ✅ 功能最强大,输出详细                                │
│          │ ✅ 支持 +trace 追踪解析链                               │
│          │ ✅ 适合故障排查和脚本使用                               │
│          │ ⚠️ 输出较复杂,新手不易阅读                            │
├──────────┼──────────────────────────────────────────────────────┤
│ nslookup │ ✅ 交互模式方便                                       │
│          │ ✅ 输出相对简洁                                       │
│          │ ⚠️ 功能不如 dig 丰富                                   │
│          │ ⚠️ 已标记为废弃,建议用 dig 替代                        │
├──────────┼──────────────────────────────────────────────────────┤
│ host     │ ✅ 输出最简洁                                         │
│          │ ✅ 适合快速查询                                       │
│          │ ⚠️ 功能有限                                           │
└──────────┴──────────────────────────────────────────────────────┘

推荐:日常使用 dig +short,故障排查用 dig +trace

3.5 高级排查技巧

# ============================================================
# 技巧 1:追踪完整解析链
# ============================================================
dig +trace www.example.com

# 输出示例:
# .  518400 IN NS a.root-servers.net.
# com.  172800 IN NS a.gtld-servers.net.
# example.com.  172800 IN NS ns1.example.com.
# www.example.com.  300 IN A 93.184.216.34

# ============================================================
# 技巧 2:检查 DNS 传播
# ============================================================
# 在多个公共 DNS 上查询
for dns in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
    echo “=== $dns ===“
    dig @$dns www.example.com +short
done

# ============================================================
# 技巧 3:检查 DNSSEC
# ============================================================
dig +dnssec example.com
dig +cd example.com  # 禁用 DNSSEC 验证

# ============================================================
# 技巧 4:测量解析延迟
# ============================================================
time dig @8.8.8.8 www.example.com +short

# ============================================================
# 技巧 5:批量查询域名
# ============================================================
cat > domains.txt << EOF
www.google.com
www.facebook.com
www.amazon.com
EOF

dig -f domains.txt +short

# ============================================================
# 技巧 6:检查 DNS 缓存
# ============================================================
# 第一次查询(无缓存)
time dig www.example.com +short

# 第二次查询(有缓存)
time dig www.example.com +short

# 查看 systemd-resolved 缓存
resolvectl statistics | grep -A 5 “Cache“

# ============================================================
# 技巧 7:模拟不同地区解析
# ============================================================
# 使用不同地区的 DNS 服务器
dig @8.8.8.8 www.example.com +short      # 美国
dig @1.1.1.1 www.example.com +short      # 全球
dig @114.114.114.114 www.example.com +short  # 中国

四、DNS 缓存机制深度解析

4.1 Linux DNS 缓存层级

┌─────────────────────────────────────────────────────────────────┐
│                    Linux DNS 缓存层级                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  应用层缓存                                                     │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ 浏览器缓存 (Chrome/Firefox)                              │   │
│  │ glibc DNS 缓存 (getaddrinfo)                             │   │
│  └─────────────────────────────────────────────────────────┘   │
│                            │                                    │
│                            ▼                                    │
│  系统层缓存                                                     │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ systemd-resolved 缓存                                    │   │
│  │ nscd (Name Service Cache Daemon) 缓存                    │   │
│  │ dnsmasq 缓存                                             │   │
│  └─────────────────────────────────────────────────────────┘   │
│                            │                                    │
│                            ▼                                    │
│  网络层缓存                                                     │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ 本地 DNS 服务器缓存                                       │   │
│  │ ISP DNS 服务器缓存                                       │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4.2 各层缓存刷新方法

# ============================================================
# systemd-resolved 缓存
# ============================================================
# 刷新所有缓存
resolvectl flush-caches

# 刷新特定接口缓存
resolvectl flush-caches eth0

# 查看缓存统计
resolvectl statistics

# ============================================================
# nscd 缓存
# ============================================================
# 刷新 hosts 缓存
nscd -i hosts

# 刷新所有缓存
nscd -i hosts -i passwd -i group

# 重启 nscd 服务
systemctl restart nscd

# 查看缓存状态
nscd -g

# ============================================================
# dnsmasq 缓存
# ============================================================
# 刷新缓存
killall -USR2 dnsmasq

# 或重启服务
systemctl restart dnsmasq

# 查看缓存统计
# dnsmasq 启动时加 --log-queries 参数
tail -f /var/log/syslog | grep dnsmasq

# ============================================================
# 浏览器缓存
# ============================================================
# Chrome: chrome://net-internals/#dns
# Firefox: about:networking#dns

# 命令行刷新 Chrome 缓存
curl http://localhost:9222/json/new?chrome://net-internals/#dns

# ============================================================
# glibc 缓存
# ============================================================
# glibc 2.x 有内置缓存,无法直接刷新
# 重启应用或等待 TTL 过期

4.3 TTL(Time To Live)详解

┌─────────────────────────────────────────────────────────────────┐
│                     DNS TTL 详解                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  TTL 定义:DNS 记录在缓存中的存活时间(秒)                        │
│                                                                 │
│  TTL 值选择:                                                    │
│  ┌──────────────┬─────────────────────────────────────────┐   │
│  │ TTL 值         │ 适用场景                                 │   │
│  ├──────────────┼─────────────────────────────────────────┤   │
│  │ 30-300 秒     │ 频繁变更的记录(如 CDN、负载均衡)         │   │
│  │ 3600 秒 (1h)  │ 一般网站记录                              │   │
│  │ 86400 秒 (1d) │ 稳定不变的记录                            │   │
│  │ 604800 秒 (7d)│ 极少变更的记录                            │   │
│  └──────────────┴─────────────────────────────────────────┘   │
│                                                                 │
│  TTL 变更注意事项:                                              │
│  1. 降低 TTL 需要提前操作(等待旧 TTL 过期)                      │
│  2. 迁移 DNS 前先将 TTL 调低                                     │
│  3. 迁移完成后可将 TTL 调高                                     │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

# 查看 DNS 记录 TTL
dig www.example.com | grep “ANSWER SECTION“ -A 2

# 输出示例:
# ;; ANSWER SECTION:
# www.example.com.        299    IN    A    93.184.216.34
#                       ^^^
#                       剩余 TTL(秒)

4.4 DNS 缓存优化策略

# ============================================================
# 策略 1:合理设置 TTL
# ============================================================
# 生产环境记录
www.example.com.  3600  IN  A  192.0.2.1

# 经常变更的记录(如 CDN)
cdn.example.com.  300  IN  CNAME  cdn-provider.com.

# 邮件记录(稳定)
example.com.  86400  IN  MX  10  mail.example.com.

# ============================================================
# 策略 2:部署本地 DNS 缓存
# ============================================================
# 安装 dnsmasq
apt install dnsmasq

# 配置 dnsmasq
cat > /etc/dnsmasq.conf << EOF
# 监听地址
listen-address=127.0.0.1

# 上游 DNS 服务器
server=8.8.8.8
server=8.8.4.4

# 缓存大小(0=禁用)
cache-size=10000

# 最小 TTL(防止过短 TTL)
min-cache-ttl=60

# 最大 TTL(防止过长 TTL)
max-cache-ttl=86400

# 记录查询日志
log-queries

# 启用 DNSSEC
dnssec
dnssec-check-dummies
EOF

systemctl restart dnsmasq

# 修改系统 DNS 配置
echo “nameserver 127.0.0.1“ > /etc/resolv.conf

# ============================================================
# 策略 3:使用 nscd 缓存
# ============================================================
# 安装 nscd
apt install nscd

# 配置 nscd
cat > /etc/nscd.conf << EOF
persistent hosts yes
shared hosts yes
max-db-size hosts 33554432
positive-time-to-live hosts 3600
negative-time-to-live hosts 20
suggested-size hosts 211
check-files hosts yes
EOF

systemctl restart nscd

# ============================================================
# 策略 4:应用层缓存优化
# ============================================================
# Go 语言 DNS 缓存示例
package main

import (
    “context“
    “fmt“
    “net“
    “time“
)

// 带缓存的 DNS 解析器
type CachedResolver struct {
    cache map[string]cacheEntry
    ttl   time.Duration
}

type cacheEntry struct {
    ips      []string
    expireAt time.Time
}

func NewCachedResolver(ttl time.Duration) *CachedResolver {
    return &CachedResolver{
        cache: make(map[string]cacheEntry),
        ttl:   ttl,
    }
}

func (r *CachedResolver) Lookup(ctx context.Context, host string) ([]string, error) {
    // 检查缓存
    if entry, ok := r.cache[host]; ok {
        if time.Now().Before(entry.expireAt) {
            return entry.ips, nil
        }
        delete(r.cache, host)
    }

    // DNS 查询
    ips, err := net.LookupHost(host)
    if err != nil {
        return nil, err
    }

    // 存入缓存
    r.cache[host] = cacheEntry{
        ips:      ips,
        expireAt: time.Now().Add(r.ttl),
    }

    return ips, nil
}

五、DNS 安全与攻击防护

5.1 DNS 安全威胁

┌─────────────────────────────────────────────────────────────────┐
│                      DNS 安全威胁全景                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────┐                                               │
│  │ DNS 欺骗    │ 攻击者伪造 DNS 响应,返回恶意 IP                   │
│  │ (Spoofing)  │ 危害:用户被导向钓鱼网站                         │
│  └─────────────┘                                               │
│                                                                 │
│  ┌─────────────┐                                               │
│  │ DNS 缓存    │ 污染 DNS 服务器缓存,影响所有用户                  │
│  │ 投毒      │ 危害:大规模用户被重定向                         │
│  │ (Poisoning) │                                               │
│  └─────────────┘                                               │
│                                                                 │
│  ┌─────────────┐                                               │
│  │ DNS 隧道    │ 利用 DNS 协议传输数据,绕过防火墙                  │
│  │ (Tunneling) │ 危害:数据泄露、C&C 通信                        │
│  └─────────────┘                                               │
│                                                                 │
│  ┌─────────────┐                                               │
│  │ DDoS 攻击   │ 大量 DNS 请求耗尽服务器资源                       │
│  │ (Amplification)│ 危害:服务不可用                            │
│  └─────────────┘                                               │
│                                                                 │
│  ┌─────────────┐                                               │
│  │ 域名劫持    │ 篡改域名注册信息或 DNS 配置                       │
│  │ (Hijacking) │ 危害:整个域名被控制                           │
│  └─────────────┘                                               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

5.2 DNSSEC - DNS 安全扩展

┌─────────────────────────────────────────────────────────────────┐
│                    DNSSEC 工作原理                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  传统 DNS(无签名):                                            │
│  客户端 ──▶ DNS 服务器 ──▶ 返回结果(无法验证真伪)                │
│                                                                 │
│  DNSSEC(数字签名):                                            │
│  客户端 ──▶ DNS 服务器 ──▶ 返回结果 + 数字签名                     │
│     │                        │                                  │
│     │                        │ 签名链:                          │
│     │                        │ 根 → TLD → 权威                   │
│     │                        ▼                                  │
│     │                  ┌───────────┐                          │
│     │                  │ DNSKEY    │ 公钥                        │
│     │                  │ RRSIG     │ 资源记录签名                │
│     │                  │ DS        │ 委托签名者                  │
│     │                  └───────────┘                          │
│     │                                                           │
│     └──────▶ 验证签名(信任链验证)                              │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

DNSSEC 配置与验证

# ============================================================
# 检查域名是否启用 DNSSEC
# ============================================================
# 方法 1:使用 dig
dig +dnssec example.com | grep flags
# 输出:flags: qr rd ra ad;  # ad 标志表示 DNSSEC 验证通过

# 方法 2:使用 dnssec-analyzer
dnssec-analyzer.com example.com

# 方法 3:使用 Verisign 工具
# https://dnssec-debugger.verisignlabs.com/

# ============================================================
# 启用 DNSSEC(以 Bind 为例)
# ============================================================
# 1. 生成密钥
dnssec-keygen -a RSASHA256 -b 2048 -n ZONE example.com

# 2. 签名区域
dnssec-signzone -S -3 $(head -c 100 /dev/urandom | sha1sum | cut -b 1-16) example.com

# 3. 配置 Bind
cat >> /etc/bind/named.conf << EOF
zone “example.com“ {
    type master;
    file “/etc/bind/db.example.com.signed“;
    auto-dnssec maintain;
    inline-signing yes;
};
EOF

# 4. 重启 Bind
systemctl restart bind9

# ============================================================
# 客户端启用 DNSSEC 验证
# ============================================================
# systemd-resolved 配置
cat > /etc/systemd/resolved.conf << EOF
[Resolve]
DNSSEC=yes
DNSOverTLS=yes
EOF

systemctl restart systemd-resolved

# 验证 DNSSEC
resolvectl status | grep DNSSEC

5.3 DNS over TLS/HTTPS - 加密 DNS

┌─────────────────────────────────────────────────────────────────┐
│                  加密 DNS 协议对比                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  传统 DNS (UDP 53):                                            │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ 查询:www.example.com                                   │   │
│  │        │                                                │   │
│  │        ▼                                                │   │
│  │  明文传输(可被监听、篡改)                               │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  DNS over TLS (TCP 853):                                      │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ 查询:[TLS 加密] www.example.com                        │   │
│  │        │                                                │   │
│  │        ▼                                                │   │
│  │  TLS 加密通道(防监听、防篡改)                            │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  DNS over HTTPS (TCP 443):                                    │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ 查询:[HTTPS 加密] www.example.com                      │   │
│  │        │                                                │   │
│  │        ▼                                                │   │
│  │  HTTPS 请求(伪装成普通 Web 流量)                         │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

DoT/DoH 配置

# ============================================================
# systemd-resolved 启用 DNS over TLS
# ============================================================
cat > /etc/systemd/resolved.conf << EOF
[Resolve]
# 支持 DoT 的 DNS 服务器
DNS=1.1.1.1 1.0.0.1 8.8.8.8
# DNS over TLS 模式
DNSOverTLS=yes
# DNSSEC 验证
DNSSEC=yes
EOF

systemctl restart systemd-resolved

# 验证
resolvectl status

# ============================================================
# 使用 stubby(DoT 代理)
# ============================================================
# 安装 stubby
apt install stubby

# 配置 stubby
cat > /etc/stubby/stubby.yml << EOF
resolution_type: GETDNS_RESOLUTION_STUB
dns_transport_list:
  - GETDNS_TRANSPORT_TLS
tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
tls_query_padding_blocksize: 256
edns_client_subnet_private: 1
idle_timeout: 10000
listen_addresses:
  - 127.0.0.1
  - 0::1
round_robin_upstreams: 1
upstream_recursive_servers:
  # Cloudflare
  - address_data: 1.1.1.1
    tls_auth_name: “cloudflare-dns.com“
  - address_data: 1.0.0.1
    tls_auth_name: “cloudflare-dns.com“
  # Google
  - address_data: 8.8.8.8
    tls_auth_name: “dns.google“
  - address_data: 8.8.4.4
    tls_auth_name: “dns.google“
EOF

systemctl restart stubby

# 修改系统 DNS
echo “nameserver 127.0.0.1“ > /etc/resolv.conf

# ============================================================
# 使用 dnsmasq + DoH
# ============================================================
# 安装 cloudflared(Cloudflare DoH 代理)
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
chmod +x cloudflared-linux-amd64
mv cloudflared-linux-amd64 /usr/local/bin/cloudflared

# 创建 systemd 服务
cat > /etc/systemd/system/cloudflared.service << EOF
[Unit]
Description=cloudflared DNS over HTTPS proxy
After=network.target

[Service]
Type=simple
User=nobody
ExecStart=/usr/local/bin/cloudflared proxy-dns \
  --port 5053 \
  --upstream https://1.1.1.1/dns-query \
  --upstream https://1.0.0.1/dns-query
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable cloudflared
systemctl start cloudflared

# 配置 dnsmasq 使用 DoH
cat > /etc/dnsmasq.conf << EOF
server=127.0.0.1#5053
EOF

systemctl restart dnsmasq

5.4 DNS 攻击防护

# ============================================================
# 防护 1:防止 DNS 放大攻击
# ============================================================
# 在 Bind 配置中禁用递归查询(对非信任客户端)
cat >> /etc/bind/named.conf.options << EOF
options {
    # 限制递归查询
    allow-recursion {
        127.0.0.1;
        192.168.0.0/16;
        10.0.0.0/8;
    };

    # 禁用版本信息
    version “not disclosed“;

    # 限制查询速率
    rate-limit {
        responses-per-second 10;
        window 5;
    };
};
EOF

# ============================================================
# 防护 2:检测 DNS 隧道
# ============================================================
# 使用 dnsdetect 检测异常 DNS 流量
apt install dnsdetect

# 监控 DNS 查询频率
watch -n 1 ‘dig @localhost +short | wc -l‘

# 检查异常长的 DNS 查询
tail -f /var/log/bind9/query.log | grep -E “.{50,}\.example\.com“

# ============================================================
# 防护 3:防止 DNS 劫持
# ============================================================
# 锁定 /etc/resolv.conf
chattr +i /etc/resolv.conf

# 监控 DNS 配置变更
inotifywait -m /etc/resolv.conf -e modify

# 使用静态 DNS 配置
cat > /etc/resolv.conf << EOF
nameserver 8.8.8.8
nameserver 8.8.4.4
EOF

# ============================================================
# 防护 4:监控 DNS 安全
# ============================================================
# 安装 OSSEC(入侵检测系统)
apt install ossec-hids

# 配置 DNS 变更告警
cat >> /var/ossec/etc/ossec.conf << EOF
<syscheck>
  <directories check_all=“yes“ report_changes=“yes“>/etc/resolv.conf</directories>
</syscheck>
EOF

# 使用 fail2ban 防止 DNS 暴力破解
apt install fail2ban

cat > /etc/fail2ban/jail.d/dns.conf << EOF
[dns-servers]
enabled = true
filter = dns-servers
logpath = /var/log/bind9/query.log
maxretry = 100
bantime = 3600
EOF

六、DNS 服务器搭建实战

6.1 Bind9 - 经典 DNS 服务器

安装与基础配置

# ============================================================
# 安装 Bind9
# ============================================================
# Debian/Ubuntu
apt update && apt install bind9 bind9utils bind9-doc

# CentOS/RHEL
yum install bind bind-utils

# 检查状态
systemctl status bind9
systemctl enable bind9

# ============================================================
# 基础配置
# ============================================================
# 主配置文件
cat > /etc/bind/named.conf.options << EOF
options {
    directory “/var/cache/bind“;

    # 监听地址
    listen-on port 53 { 127.0.0.1; 192.168.1.1; };
    listen-on-v6 port 53 { ::1; };

    # 允许查询的客户端
    allow-query { localhost; 192.168.1.0/24; };

    # 允许递归查询的客户端
    allow-recursion { localhost; 192.168.1.0/24; };

    # 上游 DNS 服务器
    forwarders {
        8.8.8.8;
        8.8.4.4;
    };

    # DNSSEC
    dnssec-validation auto;

    # 日志
    querylog yes;
};
EOF

# 重启服务
systemctl restart bind9

# 测试配置
named-checkconf

# ============================================================
# 配置本地域名
# ============================================================
# 添加区域配置
cat >> /etc/bind/named.conf.local << EOF
zone “example.local“ {
    type master;
    file “/etc/bind/db.example.local“;
};

zone “1.168.192.in-addr.arpa“ {
    type master;
    file “/etc/bind/db.192“;
};
EOF

# 创建区域文件
cat > /etc/bind/db.example.local << EOF
\$TTL 86400
@   IN  SOA ns1.example.local. admin.example.local. (
            2024011501  ; Serial
            3600        ; Refresh
            1800        ; Retry
            604800      ; Expire
            86400 )     ; Minimum TTL

; 名称服务器
@       IN  NS      ns1.example.local.
@       IN  NS      ns2.example.local.

; A 记录
@       IN  A       192.168.1.1
ns1     IN  A       192.168.1.1
ns2     IN  A       192.168.1.2
www     IN  A       192.168.1.10
api     IN  A       192.168.1.11
db      IN  A       192.168.1.12
cache   IN  A       192.168.1.13

; CNAME 记录
mail    IN  CNAME   @
ftp     IN  CNAME   www

; MX 记录
@       IN  MX  10  mail.example.local.
EOF

# 检查配置
named-checkzone example.local /etc/bind/db.example.local

# 重启服务
systemctl restart bind9

# ============================================================
# 测试 DNS 服务器
# ============================================================
# 修改本地 DNS
echo “nameserver 192.168.1.1“ > /etc/resolv.conf

# 查询测试
dig @localhost example.local
dig @localhost www.example.local
dig @localhost -x 192.168.1.10

6.2 dnsmasq - 轻量级 DNS 服务器

# ============================================================
# 安装 dnsmasq
# ============================================================
apt install dnsmasq

# ============================================================
# 基础配置
# ============================================================
cat > /etc/dnsmasq.conf << EOF
# 监听地址
listen-address=127.0.0.1
listen-address=192.168.1.1

# 绑定到特定接口
interface=eth0
except-interface=lo

# 上游 DNS 服务器
server=8.8.8.8
server=8.8.4.4
server=1.1.1.1

# 缓存配置
cache-size=10000
min-cache-ttl=60
max-cache-ttl=86400

# 本地域名
local=/example.local/
domain=example.local
expand-hosts

# 读取 /etc/hosts
addn-hosts=/etc/hosts

# DHCP 配置(可选)
dhcp-range=192.168.1.100,192.168.1.200,12h
dhcp-option=3,192.168.1.1
dhcp-option=6,192.168.1.1

# 日志
log-queries
log-facility=/var/log/dnsmasq.log

# DNSSEC
dnssec
dnssec-check-dummies
EOF

# 重启服务
systemctl restart dnsmasq

# ============================================================
# 添加自定义 DNS 记录
# ============================================================
# 方法 1:添加到 /etc/hosts
cat >> /etc/hosts << EOF
192.168.1.10    www.example.local
192.168.1.11    api.example.local
192.168.1.12    db.example.local
EOF

# 方法 2:使用 addn-hosts
echo “192.168.1.20    test.example.local“ >> /etc/hosts.custom

# 方法 3:直接在配置文件中
cat >> /etc/dnsmasq.conf << EOF
address=/dev.example.local/192.168.1.30
address=/staging.example.local/192.168.1.31
EOF

systemctl restart dnsmasq

# ============================================================
# 测试 dnsmasq
# ============================================================
# 查询测试
dig @localhost www.example.local
dig @localhost +short example.local

# 查看缓存
killall -USR2 dnsmasq
tail -f /var/log/dnsmasq.log

# 监控查询
tail -f /var/log/dnsmasq.log | grep query

6.3 CoreDNS - 云原生 DNS 服务器

# ============================================================
# CoreDNS 特点
# ============================================================
# ✅ 云原生设计,Kubernetes 默认 DNS
# ✅ 插件化架构,灵活扩展
# ✅ 支持多种后端(文件、etcd、Kubernetes 等)
# ✅ 支持 Prometheus 监控
# ✅ 支持 DNS over TLS/HTTPS

# ============================================================
# 安装 CoreDNS
# ============================================================
# 下载二进制
wget https://github.com/coredns/coredns/releases/latest/download/coredns_linux_amd64.tgz
tar xzf coredns_linux_amd64.tgz
mv coredns /usr/local/bin/

# ============================================================
# 基础配置
# ============================================================
cat > /etc/coredns/Corefile << EOF
# 全局配置
{
    log
    errors
    health
    prometheus :9153
    cache 30
    reload
}

# example.local 区域
example.local {
    file /etc/coredns/db.example.local
    errors
    log
}

# 转发其他查询到上游 DNS
. {
    forward . 8.8.8.8 8.8.4.4
    cache 30
}
EOF

# 创建区域文件
cat > /etc/coredns/db.example.local << EOF
\$TTL 3600
@   IN  SOA ns1.example.local. admin.example.local. (
            2024011501
            3600
            1800
            604800
            86400 )

@       IN  NS      ns1.example.local.
ns1     IN  A       192.168.1.1
www     IN  A       192.168.1.10
api     IN  A       192.168.1.11
EOF

# ============================================================
# 创建 systemd 服务
# ============================================================
cat > /etc/systemd/system/coredns.service << EOF
[Unit]
Description=CoreDNS
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/coredns -conf /etc/coredns/Corefile
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable coredns
systemctl start coredns

# ============================================================
# Kubernetes 中的 CoreDNS
# ============================================================
# 查看 CoreDNS 配置
kubectl get configmap coredns -n kube-system -o yaml

# 编辑 CoreDNS 配置
kubectl edit configmap coredns -n kube-system

# 添加自定义域名
# .:53 {
#     forward . 8.8.8.8
#     cache 30
# }
# example.local {
#     kubernetes cluster.local in-addr.arpa ip6.arpa
#     forward . 192.168.1.1
# }

# 测试 CoreDNS
kubectl run -it --rm dns-test --image=busybox:1.28 --restart=Never -- nslookup kubernetes

七、故障排查实战案例

7.1 案例 1:域名解析超时

问题现象

# 用户报告:访问网站很慢,有时超时
curl -v https://www.example.com
# 输出:Trying... 长时间等待

# 检查 DNS 解析时间
time dig www.example.com
# 输出:Query time: 5000 msec(异常慢)

排查步骤

# 步骤 1:检查本地 DNS 配置
cat /etc/resolv.conf
# 检查 nameserver 是否可达

# 步骤 2:测试 DNS 服务器连通性
for dns in $(grep nameserver /etc/resolv.conf | awk ‘{print $2}‘); do
    echo “Testing $dns...“
    time dig @$dns www.example.com +short
done

# 步骤 3:检查 DNS 服务器响应
systemctl status systemd-resolved
resolvectl statistics

# 步骤 4:检查网络连接
ping -c 3 8.8.8.8
mtr 8.8.8.8

# 步骤 5:检查是否有 DNS 污染
dig @8.8.8.8 www.example.com +short
dig @114.114.114.114 www.example.com +short
# 比较结果是否一致

# 步骤 6:检查本地缓存
resolvectl flush-caches
time dig www.example.com +short

解决方案

# 方案 1:更换 DNS 服务器
cat > /etc/resolv.conf << EOF
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 1.1.1.1
options timeout:2
options attempts:2
options rotate
EOF

# 方案 2:部署本地 DNS 缓存
apt install dnsmasq
systemctl restart dnsmasq
echo “nameserver 127.0.0.1“ > /etc/resolv.conf

# 方案 3:优化 nsswitch 配置
cat /etc/nsswitch.conf | grep hosts
# 确保:hosts: files dns myhostname

# 方案 4:禁用 IPv6 DNS(如果不需要)
cat > /etc/gai.conf << EOF
precedence ::ffff:0:0/96  100
EOF

7.2 案例 2:内部域名无法解析

问题现象

# 用户报告:内部系统无法访问
curl http://api.internal.example.com
# 输出:Could not resolve host

# 外部域名正常
curl http://www.google.com
# 正常访问

排查步骤

# 步骤 1:检查域名类型
domain=api.internal.example.com
dots=$(echo “$domain“ | tr -cd ‘.‘ | wc -c)
echo “Domain has $dots dots“

# 步骤 2:检查 ndots 设置
grep options /etc/resolv.conf
# 如果 ndots 设置过高,可能导致问题

# 步骤 3:检查搜索域配置
cat /etc/resolv.conf | grep search

# 步骤 4:测试完整域名查询
dig api.internal.example.com +short

# 步骤 5:检查 /etc/hosts
grep “api.internal“ /etc/hosts

# 步骤 6:检查内部 DNS 服务器
dig @internal-dns.example.com api.internal.example.com

解决方案

# 方案 1:添加搜索域
cat > /etc/resolv.conf << EOF
nameserver 192.168.1.1
search internal.example.com example.com
options ndots:2
EOF

# 方案 2:添加到 /etc/hosts
echo “192.168.1.11    api.internal.example.com api“ >> /etc/hosts

# 方案 3:配置 dnsmasq 处理内部域名
cat >> /etc/dnsmasq.conf << EOF
# 内部域名直接转发到内部 DNS
server=/internal.example.com/192.168.1.1
EOF
systemctl restart dnsmasq

# 方案 4:使用 split-horizon DNS
# 在 Bind 中配置视图
cat >> /etc/bind/named.conf << EOF
view “internal“ {
    match-clients { 192.168.0.0/16; localhost; };
    zone “example.com“ {
        file “/etc/bind/db.example.internal“;
    };
};

view “external“ {
    match-clients { any; };
    zone “example.com“ {
        file “/etc/bind/db.example.external“;
    };
};
EOF

7.3 案例 3:DNS 解析不一致

问题现象

# 不同服务器解析结果不同
# Server 1
dig www.example.com +short
# 输出:192.0.2.1

# Server 2
dig www.example.com +short
# 输出:192.0.2.2

# 用户报告:有时访问正常,有时 404

排查步骤

# 步骤 1:检查多台服务器 DNS 配置
for server in server1 server2 server3; do
    echo “=== $server ===“
    ssh $server “cat /etc/resolv.conf“
    ssh $server “dig www.example.com +short“
done

# 步骤 2:检查 DNS 轮询
dig www.example.com +noall +answer
# 查看是否有多个 A 记录

# 步骤 3:检查 CDN 配置
# CDN 通常会根据地理位置返回不同 IP

# 步骤 4:检查 DNS 缓存
for server in server1 server2 server3; do
    ssh $server “resolvectl flush-caches“
done

# 步骤 5:追踪解析链
dig +trace www.example.com

解决方案

# 方案 1:统一 DNS 配置
# 在所有服务器上使用相同的 DNS 配置
cat > /etc/resolv.conf << EOF
nameserver 8.8.8.8
nameserver 8.8.4.4
EOF

# 方案 2:使用 DNS 轮询(负载均衡)
# 在 DNS 服务器配置多个 A 记录
www.example.com.  300  IN  A  192.0.2.1
www.example.com.  300  IN  A  192.0.2.2
www.example.com.  300  IN  A  192.0.2.3

# 方案 3:使用 GeoDNS
# 根据地理位置返回不同 IP
# 需要 DNS 服务商支持

# 方案 4:应用层处理
# 在应用中使用固定的服务发现机制
# 如 Consul、etcd 等

7.4 案例 4:Kubernetes 中 DNS 解析失败

问题现象

# Pod 内无法解析服务名
kubectl exec -it my-pod -- nslookup kubernetes
# 输出:nslookup: can‘t resolve ‘kubernetes‘

# 无法解析外部域名
kubectl exec -it my-pod -- nslookup www.google.com
# 输出:nslookup: can‘t resolve ‘www.google.com‘

排查步骤

# 步骤 1:检查 CoreDNS Pod 状态
kubectl get pods -n kube-system -l k8s-app=kube-dns

# 步骤 2:查看 CoreDNS 日志
kubectl logs -n kube-system -l k8s-app=kube-dns

# 步骤 3:检查 CoreDNS 配置
kubectl get configmap coredns -n kube-system -o yaml

# 步骤 4:检查 Pod DNS 配置
kubectl exec my-pod -- cat /etc/resolv.conf

# 步骤 5:测试 CoreDNS 连通性
kubectl exec -it my-pod -- dig @10.96.0.10 kubernetes

# 步骤 6:检查 NetworkPolicy
kubectl get networkpolicy -A

解决方案

# 方案 1:重启 CoreDNS
kubectl rollout restart deployment coredns -n kube-system

# 方案 2:修复 CoreDNS 配置
kubectl edit configmap coredns -n kube-system
# 确保配置正确

# 方案 3:增加 CoreDNS 副本
kubectl scale deployment coredns -n kube-system --replicas=3

# 方案 4:调整 Pod DNS 策略
cat > pod-dns-config.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
  name: dns-test
spec:
  dnsPolicy: ClusterFirst
  dnsConfig:
    options:
      - name: ndots
        value: “2“
      - name: timeout
        value: “2“
  containers:
  - name: test
    image: busybox
    command: [“sleep“, “3600“]
EOF
kubectl apply -f pod-dns-config.yaml

# 方案 5:检查节点 DNS 配置
# 确保节点 /etc/resolv.conf 正确
cat /etc/resolv.conf

八、生产环境最佳实践

8.1 DNS 配置检查清单

□ 使用可靠的公共 DNS 或自建 DNS 服务器
□ 配置至少 2 个 DNS 服务器(主备)
□ 启用 DNSSEC 验证
□ 部署本地 DNS 缓存(dnsmasq/systemd-resolved)
□ 合理设置 TTL 值
□ 配置 nsswitch.conf 确保 hosts 优先
□ 监控 DNS 解析延迟和成功率
□ 定期审计 DNS 配置
□ 实施 DNS 查询日志
□ 配置 DNS 告警阈值

8.2 DNS 监控方案

# ============================================================
# 方案 1:使用 Prometheus + Blackbox Exporter
# ============================================================
# 安装 Blackbox Exporter
wget https://github.com/prometheus/blackbox_exporter/releases/latest/download/blackbox_exporter-linux-amd64.tar.gz
tar xzf blackbox_exporter*.tar.gz
mv blackbox_exporter /usr/local/bin/

# 配置
cat > /etc/blackbox_exporter/config.yml << EOF
modules:
  dns_tcp:
    prober: dns
    timeout: 5s
    dns:
      transport_protocol: “tcp“
      query_type: “A“
      query_name: “www.example.com“

  dns_udp:
    prober: dns
    timeout: 5s
    dns:
      transport_protocol: “udp“
      query_type: “A“
      query_name: “www.example.com“
EOF

# Prometheus 配置
cat >> /etc/prometheus/prometheus.yml << EOF
scrape_configs:
  - job_name: ‘blackbox_dns‘
    metrics_path: /probe
    params:
      module: [dns_udp]
    static_configs:
      - targets:
        - 8.8.8.8
        - 8.8.4.4
        - 1.1.1.1
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: localhost:9115
EOF

# ============================================================
# 方案 2:自定义 DNS 监控脚本
# ============================================================
cat > /usr/local/bin/dns-monitor.sh << ‘EOF‘
#!/bin/bash

DOMAINS=(“www.example.com“ “api.example.com“ “db.example.local“)
DNS_SERVERS=(“8.8.8.8“ “8.8.4.8“ “1.1.1.1“)
LOG_FILE=“/var/log/dns-monitor.log“
ALERT_THRESHOLD=1000  # ms

log() {
    echo “$(date ‘+%Y-%m-%d %H:%M:%S‘) $1“ >> $LOG_FILE
}

for domain in “${DOMAINS[@]}“; do
    for dns in “${DNS_SERVERS[@]}“; do
        start=$(date +%s%N)
        result=$(dig @$dns $domain +short +time=2 2>/dev/null)
        end=$(date +%s%N)

        latency=$(( (end - start) / 1000000 ))

        if [ -z “$result“ ]; then
            log “ALERT: $domain resolution failed on $dns“
            # 发送告警
            # curl -X POST https://alert-webhook/... 
        elif [ $latency -gt $ALERT_THRESHOLD ]; then
            log “WARNING: $domain on $dns latency ${latency}ms > ${ALERT_THRESHOLD}ms“
        else
            log “OK: $domain on $dns latency ${latency}ms“
        fi
    done
done
EOF

chmod +x /usr/local/bin/dns-monitor.sh

# 添加到 crontab
echo “*/5 * * * * /usr/local/bin/dns-monitor.sh“ | crontab -

# ============================================================
# 方案 3:使用 datadog/sensu 等监控平台
# ============================================================
# 配置 DNS 检查
cat > /etc/datadog-agent/conf.d/dns_check.d/conf.yaml << EOF
init_config:

instances:
  - name: example.com
    hostname: www.example.com
    nameserver: 8.8.8.8
    record_type: A
    timeout: 5
    tags:
      - env:production
      - service:dns
EOF

8.3 DNS 性能优化

# ============================================================
# 优化 1:部署本地 DNS 缓存
# ============================================================
# 减少外部 DNS 查询,降低延迟
apt install dnsmasq
cat > /etc/dnsmasq.conf << EOF
cache-size=10000
min-cache-ttl=60
max-cache-ttl=86400
server=8.8.8.8
server=8.8.4.4
EOF

# ============================================================
# 优化 2:使用 Anycast DNS
# ============================================================
# 多个地理位置的 DNS 服务器使用相同 IP
# 用户自动连接到最近的服务器

# ============================================================
# 优化 3:DNS 预取
# ============================================================
# 在 HTML 中添加 DNS 预取提示
# <link rel=“dns-prefetch“ href=“//cdn.example.com“>
# <link rel=“dns-prefetch“ href=“//api.example.com“>

# ============================================================
# 优化 4:减少 DNS 查询次数
# ============================================================
# 使用域名拼接,减少 CNAME 链
# 避免:www → cdn → cloudfront → actual-ip
# 建议:www → actual-ip

# 合并资源到同一域名
# 避免:img1.example.com, img2.example.com
# 建议:img.example.com(使用 CDN)

# ============================================================
# 优化 5:TCP 连接复用
# ============================================================
# 启用 HTTP Keep-Alive
# 减少 DNS 查询后的连接建立时间

8.4 高可用 DNS 架构

┌─────────────────────────────────────────────────────────────────┐
│                    生产环境 DNS 高可用架构                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│                         客户端                                   │
│                           │                                     │
│              ┌────────────┼────────────┐                       │
│              │            │            │                       │
│              ▼            ▼            ▼                       │
│        ┌──────────┐ ┌──────────┐ ┌──────────┐                  │
│        │  Local   │ │  Local   │ │  Local   │                  │
│        │  DNS     │ │  DNS     │ │  DNS     │                  │
│        │  Cache   │ │  Cache   │ │  Cache   │                  │
│        └────┬─────┘ └────┬─────┘ └────┬─────┘                  │
│             │            │            │                        │
│             └────────────┼────────────┘                        │
│                          │                                     │
│              ┌───────────┴───────────┐                       │
│              │                       │                       │
│              ▼                       ▼                       │
│        ┌──────────┐           ┌──────────┐                  │
│        │  Primary │           │ Secondary│                  │
│        │  DNS     │ ◀────────▶│ DNS      │                  │
│        │  Server  │  区域传输  │ Server   │                  │
│        └────┬─────┘           └────┬─────┘                  │
│             │                       │                        │
│             └───────────┬───────────┘                        │
│                         │                                     │
│                         ▼                                     │
│                   ┌──────────┐                               │
│                   │  Upstream│                               │
│                   │  DNS     │                               │
│                   │  (Public)│                               │
│                   └──────────┘                               │
│                                                                 │
│  关键配置:                                                     │
│  1. 本地缓存:dnsmasq/systemd-resolved                          │
│  2. 主从 DNS:Bind9 区域传输                                     │
│  3. 上游 DNS:多个公共 DNS(8.8.8.8, 1.1.1.1, 9.9.9.9)          │
│  4. 健康检查:监控 DNS 服务器可用性                              │
│  5. 自动故障转移:DNS 轮询 + 健康检查                           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

九、总结

9.1 核心要点回顾

  1. DNS 是基础设施:看似简单,实则关键,直接影响用户体验
  2. 理解解析流程:掌握递归查询、缓存机制、TTL 概念
  3. 合理配置:/etc/resolv.conf、nsswitch.conf、systemd-resolved
  4. 熟练使用工具:dig、nslookup、host、resolvectl
  5. 安全防护:DNSSEC、DoT/DoH、防攻击措施
  6. 监控告警:实时监控 DNS 解析延迟和成功率
  7. 高可用设计:本地缓存 + 主从 DNS + 上游多 DNS

9.2 常用命令速查

# DNS 查询
dig domain.com          # 标准查询
dig +short domain.com   # 简洁输出
dig +trace domain.com   # 追踪解析链
dig @8.8.8.8 domain.com # 指定 DNS 服务器

# 缓存管理
resolvectl flush-caches     # 刷新 systemd-resolved 缓存
nscd -i hosts               # 刷新 nscd 缓存
killall -USR2 dnsmasq       # 刷新 dnsmasq 缓存

# 状态检查
resolvectl status           # 查看 DNS 状态
cat /etc/resolv.conf        # 查看 DNS 配置
cat /etc/nsswitch.conf      # 查看解析顺序

# 服务管理
systemctl status systemd-resolved
systemctl restart dnsmasq
systemctl restart bind9

9.3 推荐工具

工具 用途
dig/nslookup DNS 查询
Wireshark DNS 流量分析
dnsperf DNS 性能测试
dnsmasq 本地 DNS 缓存
CoreDNS 云原生 DNS
Prometheus + Blackbox DNS 监控

希望这份完整的 Linux DNS 指南能帮助你在生产环境中更好地理解、配置和排查 DNS 相关问题。理论结合实战,是掌握技术的关键。如果你在实践中遇到更多有趣的问题或经验,欢迎到 云栈社区网络/系统 板块与大家一起交流讨论。




上一篇:PCIe 8.0标准进展:DesignCon 2026首秀,单通道带宽达256 GT/s
下一篇:从数据收集到智能分析:大数据工程与机器学习的基础实践
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-16 18:16 , Processed in 0.578864 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表