Skip to content

17 - 故障排查指南 ​

遇到问题先看这里。按"症状 → 原因 → 命令"组织,照着敲就行。


快速诊断流程(6 步定位) ​

bash
# 1️⃣ 服务是否运行?
sudo systemctl status tdns
# Docker:
docker compose ps

# 2️⃣ 端口是否监听?
sudo ss -tlnp | grep :53     # TCP
sudo ss -ulnp | grep :53     # UDP
sudo ss -tlnp | grep :853    # DoT
sudo ss -tlnp | grep :443    # DoH
sudo ss -tlnp | grep :8080   # API

# 3️⃣ 防火墙是否放行?
sudo iptables -L -n | grep -E '53|853|443'
# 或
sudo firewall-cmd --list-all

# 4️⃣ DNS 是否应答?
dig @127.0.0.1 example.com

# 5️⃣ 查看日志
journalctl -u tdns --since "10 minutes ago" --no-pager
# Docker:
docker compose logs --tail 100 tdns

# 6️⃣ 查看指标
curl -s http://127.0.0.1:9090/metrics | head -30

启动失败 ​

端口被占用 ​

症状:

Error: Address already in use (os error 98)

排查:

bash
# 查看占用 53 端口的进程
sudo ss -tlnp | grep :53
sudo ss -ulnp | grep :53
sudo lsof -i :53

解决:

bash
# 情况 1:systemd-resolved 占用 53 端口
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved

# 情况 2:另一个 DNS 服务(如 dnsmasq)
sudo systemctl stop dnsmasq

# 情况 3:不想停占用方,改 TDNS 端口
# /etc/tdns/tdns.toml:
#   listen-port = 5353

权限不足(特权端口) ​

症状:

Error: Permission denied (os error 13)

原因:非 root 用户无法绑定 1024 以下端口。

解决(三选一):

bash
# 方法 1:systemd 授予 capability(推荐)
# /etc/systemd/system/tdns.service
[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

# 方法 2:setcap
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/tdns

# 方法 3:使用非特权端口
# /etc/tdns/tdns.toml:
#   listen-port = 5353

配置文件不存在 ​

症状:

Error: failed to load configuration: No such file or directory

排查:

bash
# 确认配置文件路径
ls -la /etc/tdns/tdns.toml

# TDNS 默认查找 etc/tdns.toml(相对路径)
# systemd 服务的 WorkingDirectory 决定基准路径
grep WorkingDirectory /etc/systemd/system/tdns.service

解决:

bash
# 指定绝对路径
tdns --config /etc/tdns/tdns.toml

# 或从示例复制
sudo cp etc/tdns.toml.example /etc/tdns/tdns.toml

配置验证失败 ​

症状:

Error: config validation failed: recursion enabled but allow-recursion is empty

原因:启用递归模式时未配置 allow-recursion,TDNS 的开放递归防护阻止启动。

解决:

toml
[recursion]
enabled = true

[access-control]
allow-recursion = ["trusted"]   # 必填,防开放递归

[acl.trusted]
addresses = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]

查询异常 ​

SERVFAIL 响应 ​

症状:

;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 12345

原因与排查:

原因排查命令解决方案
递归模式无 root.hintsls -la /etc/tdns/root.hints下载 root.hints
网络不通根服务器dig @198.41.0.4 . NS +time=5检查防火墙出站规则
上游转发器不可达dig @8.8.8.8 example.com +time=5检查上游连通性
递归超时查看 debug 日志增大 query-timeout
CNAME 循环查看 debug 日志修复区域 CNAME 配置

逐步排查:

bash
# 1. 确认运行模式
tdnsctl status | grep Mode

# 2. 递归模式:检查 root.hints 是否存在
ls -la /etc/tdns/root.hints

# 3. 递归模式:测试根服务器连通性
dig @198.41.0.4 . NS +time=5

# 4. 转发模式:测试上游可达性
dig @8.8.8.8 example.com +time=5

# 5. 查看错误日志
journalctl -u tdns --since "5 minutes ago" | grep -i error

# 6. 检查 EDE(Extended DNS Error,RFC 8914)
dig @127.0.0.1 example.com +dnssec

REFUSED 响应 ​

症状:

;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 12345

原因与排查:

原因排查方法
ACL 拒绝查询检查客户端 IP 是否在 allow-query 范围内
ACL 拒绝递归检查客户端 IP 是否在 allow-recursion 范围内
权威模式收到非权威查询确认查询域名在 [[zones]] 列表中
查询无 RD 标志确认客户端设置了 RD=1
bash
# 查看客户端 IP(从哪台机器发起的查询)
dig @127.0.0.1 example.com

# 确认 ACL 配置
grep -A5 "allow-query" /etc/tdns/tdns.toml
grep -A5 "allow-recursion" /etc/tdns/tdns.toml

# 确认 ACL 组定义
grep -A5 "acl\." /etc/tdns/tdns.toml

NXDOMAIN 异常(域名应该存在但返回 NXDOMAIN) ​

bash
# 1. 检查权威区域是否加载
tdnsctl status | grep Zones

# 2. 通过 API 检查记录
curl -s -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8080/api/v1/zones | jq

curl -s -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8080/api/v1/zones/example.com/records | jq

# 3. 检查 Zone 文件语法(如有 named-checkzone)
named-checkzone example.com /etc/tdns/zones/example.com.zone

# 4. 清空缓存重试
tdnsctl flush
dig @127.0.0.1 www.example.com

响应延迟高 ​

bash
# 1. 查看查询延迟指标
curl -s http://127.0.0.1:9090/metrics | grep query_duration

# 2. 查看缓存命中率(低命中率 = 大量回源)
tdnsctl stats

# 3. 查看上游延迟
curl -s http://127.0.0.1:9090/metrics | grep upstream

# 4. 查看活跃连接数
curl -s http://127.0.0.1:9090/metrics | grep active_connections

调优:

问题解决方案
缓存命中率低增大 cache.max-size,启用 prefetch-enabled
上游延迟高增加上游数量,配置优先级
Worker 不足增大 server.workers
连接数高检查是否有异常高 QPS 攻击

加密传输问题 ​

DoT 连接失败 ​

bash
# 测试 DoT 连接(需 kdig 或 dig +tls)
kdig @dns.example.com example.com +tls

# 常见错误排查:

# 1. 证书无效 → 检查证书内容
openssl x509 -in /etc/tdns/tls/fullchain.pem -noout -text | head -20

# 2. 证书路径错误 → 确认配置字段名是 cert 和 key
grep -E "^cert|^key" /etc/tdns/tdns.toml

# 3. 端口未放行 → 检查防火墙
sudo iptables -L -n | grep 853

# 4. TLS 握手失败 → 查看日志
journalctl -u tdns | grep "DoT\|tls\|handshake"

DoH 连接失败 ​

bash
# 测试 DoH
curl -v -H "Content-Type: application/dns-message" \
  --data-binary @query.bin \
  https://dns.example.com/dns-query

# 常见错误排查:

# 1. 证书问题 → 同 DoT
openssl x509 -in /etc/tdns/tls/fullchain.pem -noout -text

# 2. HTTP/2 未协商 → 确认 ALPN 包含 h2
openssl s_client -connect dns.example.com:443 -alpn h2

# 3. 路径错误 → 确认配置的 path
grep "^path" /etc/tdns/tdns.toml

区域加载问题 ​

Zone 文件解析失败 ​

bash
# 查看加载日志
journalctl -u tdns | grep "zone"

# 常见语法错误:
# 1. 缺少 $TTL 指令
# 2. SOA 记录括号不匹配
# 3. 记录格式错误(列数不对)
# 4. 域名未以 . 结尾(FQDN 必须带点)
# 5. SOA Serial 不是数字

热重载不生效 ​

bash
# 1. 确认热重载执行成功
tdnsctl reload
# 检查返回的 zones_reloaded 数量

# 2. 查看日志有无错误
journalctl -u tdns --since "1 minute ago"

# 3. 确认配置验证通过
tdnsctl validate /etc/tdns/tdns.toml

# 4. 确认 Zone 文件路径正确
grep "file =" /etc/tdns/tdns.toml
ls -la /etc/tdns/zones/

# 5. 如果是 listen-addrs / listen-port 变更,热重载不生效,需要重启
sudo systemctl restart tdns

API 不可达 ​

API 401 Unauthorized ​

bash
# 确认 Token 配置(字段名是 auth-token)
grep "auth-token" /etc/tdns/tdns.toml

# 确认请求头格式正确
curl -v -H "Authorization: Bearer your-token" \
  http://127.0.0.1:8080/api/v1/health

# 确认环境变量
echo $TDNS_API_TOKEN

API 连接被拒 ​

bash
# 1. 确认 API 已启用
grep -A5 "\[api\]" /etc/tdns/tdns.toml

# 2. 确认端口监听(listen 是 "IP:Port" 格式,不是分开的 addr+port)
ss -tlnp | grep 8080

# 3. 确认绑定地址
# 如果 listen = "127.0.0.1:8080",仅本机可访问
# 远程访问需改为 "0.0.0.0:8080" 或管理 IP
grep "^listen" /etc/tdns/tdns.toml

资源问题 ​

内存使用高 ​

bash
# 查看缓存条目数
tdnsctl stats

# 检查 RRL 桶数量
curl -s http://127.0.0.1:9090/metrics | grep rrl

# 调整:
# 1. 减小 cache.max-size
# 2. 减小 max-negative-entries
# 3. 检查是否有异常大量查询导致缓存膨胀

CPU 使用高 ​

bash
# 查看 QPS
curl -s http://127.0.0.1:9090/metrics | grep queries_total

# 查看查询延迟分布
curl -s http://127.0.0.1:9090/metrics | grep query_duration

# 调整:
# 1. 增大 server.workers(或设为 0 自动检测)
# 2. 增大缓存,减少递归 / 转发回源
# 3. 检查是否有异常高 QPS(DDoS 或 RRL 触发)

文件描述符耗尽 ​

bash
# 查看当前打开的 FD
ls /proc/$(pidof tdns)/fd | wc -l

# 查看限制
cat /proc/$(pidof tdns)/limits | grep "Max open files"

# 解决:
# 1. 增大 systemd LimitNOFILE
# 2. 检查是否有连接泄漏(DoT/DoH 长连接未释放)

常见问题速查表 ​

症状最可能原因快速验证命令
服务启动失败端口被占用ss -tlnp | grep :53
启动失败权限不足setcap 或 systemd capabilities
启动失败配置错误tdns --validate --config /etc/tdns/tdns.toml
所有查询 SERVFAIL递归无 root.hintsls /etc/tdns/root.hints
所有查询 SERVFAIL转发器不可达dig @8.8.8.8 test.com
查询 REFUSEDACL 限制检查 allow-query
权威查询 REFUSED模式不匹配确认 mode = "hybrid" 或 "authoritative"
记录不更新缓存未清tdnsctl flush
Zone 不加载文件路径错误确认 file 路径 + 权限
DoT 连接失败证书问题openssl x509 检查
DoH 返回 400请求格式错误确认 Content-Type: application/dns-message
API 401Token 错误确认 auth-token 和 Authorization: Bearer
API 连接拒listen 地址限制listen = "0.0.0.0:8080"
内存增长缓存过大调小 max-size
热重载不生效改了监听地址需重启而非热重载

下一步 ​