BIND DNS 服务器搭建完全教程 / 第 14 章:故障排查
本章概述
DNS 故障排查是运维工作中的常见任务。本章系统讲解常见问题的诊断方法、核心排查工具的使用技巧、日志分析方法和区域文件错误修复。
14.1 排查工具概览
14.1.1 工具对比
| 工具 | 用途 | 优势 |
|---|
dig | DNS 查询(最推荐) | 信息最全、可指定服务器和记录类型 |
nslookup | DNS 查询(简单) | 交互模式,适合快速测试 |
host | DNS 查询(简洁) | 输出简洁,适合脚本 |
named-checkconf | 配置语法检查 | 检查 named.conf 错误 |
named-checkzone | 区域文件检查 | 检查区域文件语法 |
rndc | 服务器管理 | 重载、刷新、查看状态 |
delv | DNSSEC 验证 | 专门用于 DNSSEC 诊断 |
14.2 dig 工具详解
14.2.1 基本用法
# 基本查询
dig example.com A
# 指定 DNS 服务器
dig @192.168.1.10 example.com A
# 指定记录类型
dig example.com MX
dig example.com NS
dig example.com SOA
dig example.com TXT
dig example.com AAAA
dig example.com ANY # 查询所有记录
# 反向查询
dig -x 93.184.216.34
# 简洁输出(仅答案部分)
dig +short example.com A
# 输出: 93.184.216.34
# 详细输出
dig +noall +answer example.com A
14.2.2 高级选项
# 查看完整查询过程(跟踪递归)
dig +trace example.com A
# 输出示例:
# ;; Received 529 bytes from 198.41.0.4#53(.)
# ;; Received 284 bytes from 192.5.6.30#53(A.GTLD-SERVERS.NET.)
# ;; Received 132 bytes from 93.184.216.34#53(ns1.example.com.)
# 指定源地址(测试视图)
dig -b 192.168.1.100 @192.168.1.10 example.com
# 指定端口
dig @192.168.1.10 -p 5353 example.com
# 使用 TCP(而非 UDP)
dig +tcp example.com
# 查看 DNSSEC 签名
dig +dnssec example.com A
# 不使用搜索域
dig +search example.com
dig +ndots=5 example.com
# 查看 EDNS 信息
dig +edns=0 example.com
dig +edns=1 example.com
# 超时设置
dig +time=2 +tries=1 @192.168.1.10 example.com
14.2.3 常用 dig 查询模式
# 1. 检查 SOA(验证主服务器和 Serial)
dig @192.168.1.10 example.com SOA +short
# 输出: ns1.example.com. admin.example.com. 2026051001 3600 900 1209600 86400
# 2. 比较主从 Serial
diff <(dig @master example.com SOA +short) <(dig @slave example.com SOA +short)
# 3. 检查邮件服务器
dig example.com MX +short
# 输出: 10 mail1.example.com.
# 20 mail2.example.com.
# 4. 检查 TXT 记录(SPF/DKIM/DMARC)
dig example.com TXT +short
dig _dmarc.example.com TXT +short
dig selector1._domainkey.example.com TXT +short
# 5. 检查 CNAME 链
dig www.example.com +trace
# 6. 测试 DNSSEC
dig @1.1.1.1 example.com +dnssec
# 检查是否有 ad 标志
# 7. 区域传输测试
dig @192.168.1.10 example.com AXFR
# 有权限: 返回所有记录
# 无权限: ;; ->>HEADER<<- opcode: QUERY, status: REFUSED
# 8. 检查 CAA 记录
dig example.com CAA
14.2.4 dig 输出解读
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58937
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 86390 IN A 93.184.216.34
| 字段 | 含义 |
|---|
opcode | 操作码(QUERY = 标准查询) |
status | 响应状态码 |
id | 查询 ID |
qr | 查询响应标志(QR = 这是响应) |
rd | 期望递归(RD = Recursion Desired) |
ra | 可用递归(RA = Recursion Available) |
aa | 权威答案(AA = Authoritative Answer) |
ad | 已验证(AD = Authenticated Data,DNSSEC) |
cd | 检查禁用(CD = Checking Disabled,DNSSEC) |
ANSWER | 答案记录数 |
AUTHORITY | 权威记录数 |
ADDITIONAL | 附加记录数 |
| TTL | 缓存生存时间(秒) |
14.2.5 常见响应状态码
| 状态码 | 含义 | 常见原因 |
|---|
NOERROR | 成功 | 正常响应 |
NXDOMAIN | 域名不存在 | 域名未注册或记录不存在 |
SERVFAIL | 服务器故障 | DNSSEC 验证失败、上游超时 |
REFUSED | 查询被拒绝 | ACL 不允许 |
FORMERR | 格式错误 | 查询格式不正确 |
NOTIMP | 未实现 | 不支持的操作码 |
YXDOMAIN | 域名已存在 | 动态更新前置条件失败 |
NXRRSET | 记录集不存在 | 动态更新前置条件失败 |
14.3 nslookup 基础用法
# 基本查询
nslookup example.com
# 指定 DNS 服务器
nslookup example.com 192.168.1.10
# 指定记录类型
nslookup -type=MX example.com
nslookup -type=TXT example.com
# 反向查询
nslookup 93.184.216.34
# 交互模式
nslookup
> server 192.168.1.10
> set type=MX
> example.com
> exit
💡 优先使用 dig:nslookup 的输出不如 dig 详细,且在某些情况下行为不一致。
14.4 常见问题与解决方案
14.4.1 服务无法启动
# 1. 检查配置语法
sudo named-checkconf /etc/named.conf
# 输出错误 → 修复后重试
# 2. 检查端口占用
sudo ss -ulnp | grep :53
sudo ss -tlnp | grep :53
# 如果有其他进程占用 → 停止该进程或修改 BIND 监听地址
# 3. 检查日志
journalctl -u named -n 50
sudo tail -50 /var/log/named/default.log
# 4. 检查文件权限
ls -la /etc/named.conf
ls -la /var/named/
# 确保 named 用户有权读取
# 5. 检查 SELinux
sudo ausearch -m avc -ts recent
# 如有 SELinux 拒绝 → 添加策略或暂时禁用
sudo setenforce 0 # 临时禁用
常见启动错误:
| 错误信息 | 原因 | 解决方案 |
|---|
address already in use | 端口被占用 | 停止占用进程或 systemctl restart named |
permission denied | 权限不足 | 检查文件权限和 SELinux |
config error | 配置语法错误 | named-checkconf 检查 |
zone file not found | 区域文件缺失 | 检查路径和文件名 |
could not open entropy source | 熵源不可用 | 安装 haveged 或 rng-tools |
14.4.2 查询超时
# 1. 检查网络连通性
ping 192.168.1.10
telnet 192.168.1.10 53
# 2. 检查防火墙
sudo iptables -L -n | grep 53
sudo firewall-cmd --list-all
# 3. 检查 BIND 是否监听正确地址
sudo ss -ulnp | grep named
# 输出示例:
# UNCONN 0 0 127.0.0.1:53 0.0.0.0:* users:(("named",pid=1234,fd=512))
# 确认监听地址是否正确(应为 0.0.0.0 或指定的对外 IP)
# 4. 检查 BIND 状态
sudo rndc status
# 5. 开启查询日志
sudo rndc querylog on
dig @192.168.1.10 example.com
sudo tail -f /var/log/named/query.log
14.4.3 区域解析失败
# 1. 检查区域文件语法
sudo named-checkzone example.com /var/named/primary/example.com.zone
# 2. 检查是否包含在 named.conf 中
grep "example.com" /etc/named.conf
# 3. 检查区域类型
# primary → 检查本地文件
# secondary → 检查主服务器是否可达
dig @primary-server example.com SOA
# 4. 重载区域
sudo rndc reload example.com
# 5. 查看区域状态
sudo rndc zonestatus example.com
14.4.4 从服务器数据不同步
# 1. 检查主服务器 Serial
dig @primary example.com SOA +short
# 2. 检查从服务器 Serial
dig @secondary example.com SOA +short
# 3. 如果 Serial 不同,手动触发传输
sudo rndc retransfer example.com
# 4. 检查传输日志
sudo tail -50 /var/log/named/transfer.log
# 5. 检查 TSIG 密钥
# 确保主从使用相同的密钥
diff /etc/bind/transfer.key.primary /etc/bind/transfer.key.secondary
# 6. 测试手动传输
dig @primary example.com AXFR -k /etc/bind/transfer.key
14.4.5 DNSSEC 验证失败
# 1. 检查 DNSSEC 签名状态
dig @server example.com +dnssec
# 检查是否有 RRSIG 记录
# 2. 使用 delv 详细诊断
delv @server example.com A +rtrace
# 3. 在线工具验证
# https://dnsviz.net/d/example.com/dnssec/
# https://dnssec-analyzer.verisignlabs.com/example.com
# 4. 检查 DS 记录
dig example.com DS
# 5. 检查密钥文件
sudo rndc signing -list example.com
# 6. 强制重新签名
sudo rndc loadkeys example.com
14.4.6 动态更新失败
# 1. 检查 TSIG 密钥
nsupdate -k update.key
> server 127.0.0.1
> zone example.com.
> update add test.example.com 3600 A 192.168.1.50
> send
# 查看响应
# 2. 检查 allow-update 配置
grep -A 5 "allow-update" /etc/named.conf
# 3. 检查安全日志
sudo tail -50 /var/log/named/security.log
# 4. 检查区域是否被冻结
# 如果冻结,解冻后重试
sudo rndc thaw example.com
14.5 日志分析
14.5.1 启用各类日志
logging {
channel default_log {
file "/var/log/named/default.log" versions 5 size 50m;
severity debug 3; // 调试级别 3(生产用 info)
print-time yes;
print-severity yes;
print-category yes;
};
channel query_log {
file "/var/log/named/query.log" versions 10 size 100m;
severity dynamic;
print-time yes;
};
category default { default_log; };
category queries { query_log; };
};
14.5.2 日志关键字分析
# 查找 REFUSED 响应
grep "REFUSED" /var/log/named/default.log
# 查找 SERVFAIL 响应
grep "SERVFAIL" /var/log/named/default.log
# 查找 TSIG 认证失败
grep "tsig" /var/log/named/security.log
# 查找区域传输记录
grep "transfer" /var/log/named/transfer.log
# 统计查询频率(TOP 10 域名)
awk '/query:/ {print $NF}' /var/log/named/query.log | sort | uniq -c | sort -rn | head -10
# 统计查询来源(TOP 10 IP)
awk '{print $6}' /var/log/named/query.log | cut -d'#' -f1 | sort | uniq -c | sort -rn | head -10
# 查找 NXDOMAIN 查询(可能是扫描)
grep "NXDOMAIN" /var/log/named/query.log | awk '{print $NF}' | sort | uniq -c | sort -rn | head
# 查找查询超时
grep "timed out" /var/log/named/default.log
14.5.3 安全日志分析
# 查找动态更新事件
grep "update" /var/log/named/security.log
# 查找拒绝的查询
grep "denied" /var/log/named/security.log
# 查找区域传输事件
grep "transfer" /var/log/named/security.log
# 查找 DNSSEC 验证失败
grep "dnssec" /var/log/named/security.log
14.5.4 性能日志分析
# 查看查询统计
sudo rndc stats
cat /var/cache/bind/named.stats
# 查看缓存使用情况
sudo rndc status
# 输出包含缓存大小和命中率
14.6 区域文件错误
14.6.1 常见语法错误
| 错误信息 | 原因 | 修复方法 |
|---|
missing ';' | 缺少分号 | 在语句末尾添加分号 |
CNAME and other data | CNAME 与其他记录共存 | 删除冲突记录或改用 A 记录 |
unknown RR type | 记录类型拼写错误 | 检查记录类型名称 |
not a valid name | 域名格式错误 | 检查是否遗漏 .(FQDN) |
out of zone data | 记录不属于当前区域 | 使用正确名称或修改 $ORIGIN |
has no address records | NS 记录缺少 A 记录 | 为 NS 添加 Glue Record |
SOA record not at top | SOA 不在区域顶点 | 确保 SOA 记录名称正确 |
14.6.2 修复步骤
# 1. 语法检查
sudo named-checkzone example.com /var/named/primary/example.com.zone
# 2. 根据错误信息修复文件
sudo vim /var/named/primary/example.com.zone
# 3. 重新检查
sudo named-checkzone example.com /var/named/primary/example.com.zone
# 4. 重载区域
sudo rndc reload example.com
# 5. 验证解析
dig @127.0.0.1 example.com A
14.6.3 常见记录错误
; ❌ 错误:CNAME 与 A 记录共存
www IN CNAME example.com.
www IN A 93.184.216.34
; ✅ 正确:只保留一条
www IN A 93.184.216.34
; ❌ 错误:域名末尾缺少 .
www.example.com IN A 93.184.216.34
; (会被补全为 www.example.com.example.com.)
; ✅ 正确:FQDN 以 . 结尾
www.example.com. IN A 93.184.216.34
; ❌ 错误:MX 指向 CNAME
mail.example.com. IN CNAME other-server.com.
example.com. IN MX 10 mail.example.com.
; ✅ 正确:MX 指向 A 记录
mail.example.com. IN A 93.184.216.35
example.com. IN MX 10 mail.example.com.
14.7 网络层排查
14.7.1 端口检查
# 检查 BIND 监听状态
sudo ss -ulnp | grep :53
sudo ss -tlnp | grep :53
# 从外部测试连通性
nc -zv 192.168.1.10 53
nc -zuv 192.168.1.10 53
# 检查防火墙
sudo iptables -L -n -v | grep 53
sudo firewall-cmd --list-all
14.7.2 网络追踪
# 跟踪 UDP 数据包
sudo tcpdump -i eth0 port 53 -n
# 只捕获特定主机
sudo tcpdump -i eth0 host 192.168.1.100 and port 53 -n
# 只捕获响应
sudo tcpdump -i eth0 src port 53 -n
# 解析域名(慎用,可能有 DNS 查询干扰)
sudo tcpdump -i eth0 port 53
14.8 rndc 调试命令
# 查看服务器状态
rndc status
# 查看统计信息
rndc stats
# 转储缓存数据库
rndc dumpdb -cache
cat /var/cache/bind/named_dump.db
# 转储区域数据库
rndc dumpdb -zones
# 开启查询日志(临时)
rndc querylog on
# 设置调试级别
rndc trace 3 # 设置 debug 级别 3
rndc notrace # 关闭调试
# 刷新所有缓存
rndc flush
# 刷新特定域名缓存
rndc flushname example.com
# 查看 DNSSEC 状态
rndc dnssec -status example.com
14.9 故障排查流程图
DNS 故障
│
├── 1. 检查 BIND 服务状态
│ ├── 未运行 → 启动服务
│ └── 运行中 → 继续
│
├── 2. 检查配置语法
│ ├── 有错误 → 修复配置
│ └── 正确 → 继续
│
├── 3. 检查网络连通性
│ ├── 不通 → 检查防火墙/网络
│ └── 通 → 继续
│
├── 4. 检查端口监听
│ ├── 未监听 → 检查配置中的 listen-on
│ └── 监听中 → 继续
│
├── 5. 使用 dig 测试查询
│ ├── REFUSED → 检查 ACL
│ ├── SERVFAIL → 检查上游服务器/DNSSEC
│ ├── NXDOMAIN → 检查区域文件/记录
│ └── NOERROR → 正常
│
└── 6. 检查日志
└── 根据日志内容定位问题
14.10 常见问题速查表
| 症状 | 可能原因 | 排查工具 |
|---|
| 服务无法启动 | 端口占用/配置错误 | ss -ulnp, named-checkconf |
| 查询超时 | 防火墙/网络不通 | tcpdump, telnet |
| REFUSED | ACL 限制 | dig, grep allow-query |
| SERVFAIL | 上游超时/DNSSEC 失败 | dig +trace, delv |
| NXDOMAIN | 记录不存在 | dig, named-checkzone |
| 数据不同步 | Serial 未更新 | dig SOA, rndc retransfer |
| 缓存问题 | 缓存了错误结果 | rndc flushname |
| 内存占用高 | 缓存过大 | max-cache-size, rndc status |
| 响应慢 | 缓存未命中/网络延迟 | rndc stats, dig +trace |
14.11 本章小结
| 工具 | 用途 | 推荐场景 |
|---|
dig | 详细 DNS 查询 | 排查首选 |
nslookup | 简单 DNS 查询 | 快速验证 |
named-checkconf | 配置语法检查 | 修改配置后必用 |
named-checkzone | 区域文件检查 | 修改区域文件后必用 |
rndc | 服务器管理 | 重载、刷新、查看状态 |
tcpdump | 网络抓包 | 网络层问题 |
delv | DNSSEC 验证 | DNSSEC 问题 |
💡 小技巧
dig +trace 是排查递归问题的神器。rndc querylog on 可以实时查看查询。- 修改配置后:
named-checkconf → rndc reload。 - 修改区域文件后:
named-checkzone → rndc reload <zone>。 - 缓存问题:
rndc flushname <domain> 可以清除特定域名缓存。
📖 扩展阅读