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

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

💡 优先使用 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 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 问题

💡 小技巧

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

📖 扩展阅读