强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

BIND DNS 服务器搭建完全教程 / 第 14 章:故障排查

本章概述

DNS 故障排查是运维工作中的常见任务。本章系统讲解常见问题的诊断方法、核心排查工具的使用技巧、日志分析方法和区域文件错误修复。


14.1 排查工具概览

14.1.1 工具对比

工具用途优势
digDNS 查询(最推荐)信息最全、可指定服务器和记录类型
nslookupDNS 查询(简单)交互模式,适合快速测试
hostDNS 查询(简洁)输出简洁,适合脚本
named-checkconf配置语法检查检查 named.conf 错误
named-checkzone区域文件检查检查区域文件语法
rndc服务器管理重载、刷新、查看状态
delvDNSSEC 验证专门用于 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

💡 优先使用 dignslookup 的输出不如 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熵源不可用安装 havegedrng-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 dataCNAME 与其他记录共存删除冲突记录或改用 A 记录
unknown RR type记录类型拼写错误检查记录类型名称
not a valid name域名格式错误检查是否遗漏 .(FQDN)
out of zone data记录不属于当前区域使用正确名称或修改 $ORIGIN
has no address recordsNS 记录缺少 A 记录为 NS 添加 Glue Record
SOA record not at topSOA 不在区域顶点确保 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
REFUSEDACL 限制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网络抓包网络层问题
delvDNSSEC 验证DNSSEC 问题

💡 小技巧

  1. dig +trace 是排查递归问题的神器。
  2. rndc querylog on 可以实时查看查询。
  3. 修改配置后named-checkconfrndc reload
  4. 修改区域文件后named-checkzonerndc reload <zone>
  5. 缓存问题rndc flushname <domain> 可以清除特定域名缓存。

📖 扩展阅读