外观
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.hints | ls -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 +dnssecREFUSED 响应
症状:
;; ->>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.tomlNXDOMAIN 异常(域名应该存在但返回 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 tdnsAPI 不可达
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_TOKENAPI 连接被拒
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.hints | ls /etc/tdns/root.hints |
| 所有查询 SERVFAIL | 转发器不可达 | dig @8.8.8.8 test.com |
| 查询 REFUSED | ACL 限制 | 检查 allow-query |
| 权威查询 REFUSED | 模式不匹配 | 确认 mode = "hybrid" 或 "authoritative" |
| 记录不更新 | 缓存未清 | tdnsctl flush |
| Zone 不加载 | 文件路径错误 | 确认 file 路径 + 权限 |
| DoT 连接失败 | 证书问题 | openssl x509 检查 |
| DoH 返回 400 | 请求格式错误 | 确认 Content-Type: application/dns-message |
| API 401 | Token 错误 | 确认 auth-token 和 Authorization: Bearer |
| API 连接拒 | listen 地址限制 | listen = "0.0.0.0:8080" |
| 内存增长 | 缓存过大 | 调小 max-size |
| 热重载不生效 | 改了监听地址 | 需重启而非热重载 |
下一步
- 16 - 运维操作手册 — 日常运维操作全流程
- 15 - 监控与可观测性 — 指标 + 日志 + 告警
- 04 - 配置参考手册 — 配置项速查