DNS 解析故障排查实战指南

一、概述

DNS(Domain Name System)是互联网的基础设施,负责将域名解析为 IP 地址。DNS 故障会导致服务不可访问、应用连接失败等问题。本文介绍 DNS 解析故障的排查方法和解决方案。

DNS 解析流程

1
客户端 → 本地缓存 → hosts 文件 → 本地 DNS 服务器 → 根服务器 → TLD 服务器 → 权威服务器

常见故障现象

现象 可能原因
域名无法解析 DNS 服务器故障、域名过期、配置错误
解析结果错误 DNS 缓存污染、劫持、配置错误
解析速度慢 DNS 服务器响应慢、网络延迟
间歇性解析失败 DNS 服务器负载高、网络不稳定

二、排查工具

2.1 nslookup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 基本查询
nslookup www.example.com

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

# 查询特定记录类型
nslookup -type=MX example.com
nslookup -type=NS example.com
nslookup -type=TXT example.com
nslookup -type=SOA example.com

# 详细模式
nslookup -debug www.example.com

2.2 dig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 基本查询
dig www.example.com

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

# 查询特定记录
dig example.com MX
dig example.com NS
dig example.com TXT

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

# 简洁输出
dig +short www.example.com

# 显示详细统计
dig +stats www.example.com

2.3 host

1
2
3
4
5
6
7
8
9
# 基本查询
host www.example.com

# 查询特定记录
host -t MX example.com
host -t NS example.com

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

2.4 其他工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看本地 DNS 缓存(Windows)
ipconfig /displaydns

# 清除本地 DNS 缓存
# Linux (systemd-resolved)
sudo systemd-resolve --flush-caches
# Linux (nscd)
sudo service nscd restart
# macOS
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
# Windows
ipconfig /flushdns

# 测试 DNS 端口连通性
telnet 8.8.8.8 53
nc -zv 8.8.8.8 53

# 抓包分析 DNS 请求
tcpdump -i any -n port 53 -w dns.pcap

三、排查流程

3.1 快速诊断流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
开始


检查本地 hosts 文件 ──有配置──→ 检查 hosts 配置是否正确
│ 无配置 │
▼ ▼
使用 dig/nslookup 测试 修正 hosts 配置


本地 DNS 能否解析?───否───→ 检查 DNS 服务器配置
│ 是

解析结果是否正确?───否───→ 检查 DNS 缓存/劫持
│ 是

解析速度是否正常?───否───→ 更换 DNS 服务器/优化
│ 是

问题解决

3.2 第一步:检查本地配置

1
2
3
4
5
6
7
8
9
10
11
12
# 查看 DNS 服务器配置
cat /etc/resolv.conf

# 查看 hosts 文件
cat /etc/hosts

# 检查 NetworkManager 配置
nmcli dev show | grep DNS

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

3.3 第二步:测试 DNS 解析

1
2
3
4
5
6
7
8
9
10
11
12
13
# 使用系统默认 DNS
dig www.example.com

# 使用公共 DNS 对比
dig @8.8.8.8 www.example.com
dig @1.1.1.1 www.example.com
dig @223.5.5.5 www.example.com # 阿里 DNS

# 对比结果
echo "=== 本地 DNS ==="
dig +short www.example.com
echo "=== Google DNS ==="
dig @8.8.8.8 +short www.example.com

3.4 第三步:追踪解析链

1
2
3
4
5
6
7
# 完整追踪解析过程
dig +trace www.example.com

# 输出示例分析:
# . 根服务器返回 com. TLD 服务器
# com. TLD 服务器返回 example.com 权威服务器
# example.com 权威服务器返回最终 A 记录

3.5 第四步:检查 DNS 服务器健康

1
2
3
4
5
6
7
8
9
10
11
# 测试 DNS 服务器响应时间
dig @dns-server-ip www.example.com | grep "Query time"

# 批量测试多个域名
for domain in www.baidu.com www.taobao.com www.jd.com; do
echo "Testing $domain:"
dig @dns-server-ip +short $domain
done

# 检查 DNS 服务器是否递归
dig @dns-server-ip +norecursive www.example.com

四、常见故障场景

4.1 场景一:域名完全无法解析

现象:

1
2
3
4
5
$ nslookup www.example.com
Server: 192.168.1.1
Address: 192.168.1.1#53

** server can't find www.example.com: NXDOMAIN

排查步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 确认域名是否有效
whois example.com

# 2. 检查域名是否过期
dig example.com SOA

# 3. 测试其他 DNS 服务器
dig @8.8.8.8 www.example.com

# 4. 检查本地 DNS 配置
cat /etc/resolv.conf

# 5. 检查防火墙是否阻断 DNS
iptables -L -n | grep 53

解决方案:

1
2
3
4
5
6
7
8
9
# 方案 1:更换 DNS 服务器
echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 1.1.1.1" >> /etc/resolv.conf

# 方案 2:检查并修复 DNS 服务
systemctl restart systemd-resolved

# 方案 3:检查网络连通性
ping -c 4 8.8.8.8

4.2 场景二:解析结果错误

现象:

1
2
3
# 预期解析到 1.2.3.4,实际解析到 5.6.7.8
$ dig www.example.com +short
5.6.7.8

排查步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 清除本地缓存
sudo systemd-resolve --flush-caches

# 2. 查询权威 DNS
dig @ns1.example.com www.example.com

# 3. 检查是否有 CDN 或负载均衡
dig www.example.com | grep -A 5 "ANSWER SECTION"

# 4. 检查 DNS 劫持
dig @8.8.8.8 www.example.com +short
dig @1.1.1.1 www.example.com +short

# 5. 抓包分析
tcpdump -i eth0 -n port 53 -w dns_debug.pcap

解决方案:

1
2
3
4
5
6
7
# 方案 1:使用 HTTPS over DNS (DoH)
# 配置 Firefox/Chrome 使用 DoH

# 方案 2:使用 DNSSEC 验证
# 在 resolv.conf 中添加 options edns0

# 方案 3:联系域名管理员修正 DNS 记录

4.3 场景三:解析速度慢

现象:

1
2
3
$ time dig www.example.com
...
;; Query time: 2500 msec

排查步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 测试不同 DNS 服务器响应时间
for dns in 8.8.8.8 1.1.1.1 223.5.5.5 114.114.114.114; do
echo "Testing $dns:"
dig @$dns www.example.com | grep "Query time"
done

# 2. 检查 DNS 服务器负载
# 联系 DNS 管理员或更换服务器

# 3. 检查网络延迟
mtr 8.8.8.8

# 4. 检查本地 DNS 缓存命中率
resolvectl statistics

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 方案 1:使用更快的公共 DNS
cat > /etc/resolv.conf << EOF
nameserver 223.5.5.5
nameserver 114.114.114.114
EOF

# 方案 2:部署本地 DNS 缓存(dnsmasq)
apt install dnsmasq
systemctl enable dnsmasq
systemctl start dnsmasq

# 方案 3:配置 DNS 预取(浏览器)
# network.dns.disableIPv6 = false (Firefox)

4.4 场景四:间歇性解析失败

现象:

1
2
3
4
5
# 有时成功,有时失败
$ dig www.example.com +short
1.2.3.4
$ dig www.example.com +short
;; connection timed out; no servers could be reached

排查步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 检查 DNS 服务器可用性
for i in {1..10}; do
dig @dns-server www.example.com +short
sleep 1
done

# 2. 检查网络连接稳定性
ping -c 100 dns-server | tail -5

# 3. 检查防火墙规则
iptables -L -n -v | grep 53

# 4. 检查 DNS 服务器日志
journalctl -u systemd-resolved -f

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
# 方案 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 attempts:3
EOF

# 方案 2:使用 DNS 负载均衡
# 部署多个 DNS 服务器并配置健康检查

# 方案 3:增加重试机制(应用层)

4.5 场景五:内网域名无法解析

现象:

1
2
3
# 外网域名正常,内网域名失败
$ dig www.google.com +short # 成功
$ dig internal.corp.com +short # 失败

排查步骤:

1
2
3
4
5
6
7
8
9
10
11
# 1. 检查内网 DNS 服务器配置
cat /etc/resolv.conf

# 2. 确认内网 DNS 服务器可达
ping -c 4 192.168.1.10

# 3. 查询内网 DNS 服务器
dig @192.168.1.10 internal.corp.com

# 4. 检查 DNS 转发配置
# 查看 named.conf 或 CoreDNS 配置

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 方案 1:配置 DNS 搜索域
cat > /etc/resolv.conf << EOF
search corp.com
nameserver 192.168.1.10
nameserver 8.8.8.8
EOF

# 方案 2:配置条件转发(BIND)
# zone "corp.com" {
# type forward;
# forward only;
# forwarders { 192.168.1.10; };
# };

# 方案 3:使用 split-horizon DNS

五、Kubernetes 环境 DNS 排查

5.1 CoreDNS 故障排查

1
2
3
4
5
6
7
8
9
10
11
# 检查 CoreDNS Pod 状态
kubectl get pods -n kube-system -l k8s-app=kube-dns

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

# 测试集群内 DNS 解析
kubectl run -it --rm dns-test --image=busybox:1.28 --restart=Never -- nslookup kubernetes.default

# 检查 CoreDNS 配置
kubectl get cm -n kube-system coredns -o yaml

5.2 常见问题

1
2
3
4
5
6
7
8
9
# 问题 1:Pod 无法解析服务名
# 检查:/etc/resolv.conf 中的 nameserver 是否指向 CoreDNS

# 问题 2:跨 Namespace 解析失败
# 解决:使用完整服务名 service.namespace.svc.cluster.local

# 问题 3:CoreDNS 响应慢
# 解决:调整 CoreDNS 副本数或资源限制
kubectl scale deployment coredns -n kube-system --replicas=3

六、DNS 安全

6.1 DNS 劫持防护

1
2
3
4
5
6
7
8
# 1. 使用 DNSSEC
# 在域名注册商处启用 DNSSEC

# 2. 使用 DoH/DoT
# 配置支持加密 DNS 的解析器

# 3. 监控 DNS 变更
# 设置 DNS 记录变更告警

6.2 DDoS 防护

1
2
3
# 1. 使用 Anycast DNS
# 2. 配置速率限制
# 3. 使用云 DNS 服务(阿里云 DNS、Cloudflare)

七、最佳实践

7.1 客户端配置

1
2
3
4
5
6
7
# /etc/resolv.conf 推荐配置
nameserver 223.5.5.5 # 阿里 DNS
nameserver 114.114.114.114 # 114 DNS
nameserver 8.8.8.8 # Google DNS(备用)
options timeout:2 # 超时 2 秒
options attempts:3 # 重试 3 次
options rotate # 轮询使用 DNS 服务器

7.2 服务器端配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# BIND 性能优化
options {
recursion yes;
allow-recursion { trusted-nets; };

# 缓存配置
max-cache-size 2g;
max-cache-ttl 86400;

# 性能优化
listen-on port 53 { any; };
clients-per-query 100;
max-clients-per-query 500;

# 安全配置
version "not disclosed";
hostname "not disclosed";
};

7.3 监控告警

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Prometheus DNS 监控指标
# 查询成功率
rate(dns_responses_total{rcode="NOERROR"}[5m])
/
rate(dns_responses_total[5m])

# 查询延迟
histogram_quantile(0.95, rate(dns_request_duration_seconds_bucket[5m]))

# 告警规则
- alert: DNSHighFailureRate
expr: dns_failure_rate > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "DNS 失败率过高"

八、总结

DNS 故障排查的关键步骤:

  1. 确认范围:单个域名还是全部域名?内网还是外网?
  2. 分层排查:本地配置 → DNS 服务器 → 权威服务器
  3. 对比验证:使用多个 DNS 服务器对比结果
  4. 工具辅助:dig、nslookup、tcpdump 配合使用
  5. 监控预防:建立 DNS 监控告警机制

记住:DNS 是基础设施,稳定的 DNS 服务对业务连续性至关重要。