Skip to content

08 - 递归解析服务 ​

概述 ​

递归模式(recursive)下,TDNS 从 DNS 根服务器开始逐级迭代解析,不依赖上游递归服务器。客户端发送递归查询(RD=1)后,TDNS 承担完整的解析链路,直到获得最终答案返回给客户端。

适用场景:企业出口 DNS、家庭网络网关、需要完整解析链路控制的环境。


快速上手:四步跑通递归服务 ​

1. 配置 ​

toml
# /etc/tdns/tdns.toml
[server]
mode = "recursive"

[recursion]
enabled = true
max-concurrent-queries = 10000
query-timeout = "5s"
max-depth = 16

[cache]
enabled = true
max-size = "1GB"
min-ttl = 60
max-ttl = 86400
negative-ttl = 300
stale-ttl = 3600
max-negative-entries = 50000

[access-control]
allow-query = ["trusted"]
allow-recursion = ["trusted"]   # 必填!

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

2. 确保 root.hints 就绪 ​

bash
# 检查文件
ls -la /etc/tdns/root.hints

# 如果不存在,从 IANA 下载
curl -o /etc/tdns/root.hints https://www.internic.net/domain/named.root

# 或用 dig 获取
dig @a.root-servers.net . NS > /etc/tdns/root.hints

3. 验证配置 + 启动 ​

bash
# 验证配置
tdns --validate --config /etc/tdns/tdns.toml

# 启动
sudo systemctl start tdns

4. 测试递归解析 ​

bash
# 测试常见域名
dig @127.0.0.1 www.google.com
dig @127.0.0.1 www.baidu.com

# 测试根服务器连通性
dig @198.41.0.4 . NS +time=5

# 查看缓存命中率
tdnsctl stats

工作原理 ​

客户端查询 www.example.com A (RD=1)
    │
    ▼
1. 检查本地缓存 → 未命中
    │
    ▼
2. 查询根服务器 (.) → 获取 .com TLD 的 NS 记录
    │
    ▼
3. 查询 .com TLD 权威 → 获取 example.com 的 NS 记录
    │
    ▼
4. 查询 example.com 权威 → 获取 www.example.com 的 A 记录
    │
    ▼
5. 缓存结果(按 TTL),返回给客户端

每级查询独立超时控制,支持重试。根服务器从 root.hints 文件获取,随机选择以分散负载。


root.hints 文件 ​

文件查找顺序 ​

  1. --root-hints <path> CLI 参数(最高优先级)
  2. <working-directory>/root.hints(默认 /var/lib/tdns/root.hints)
  3. etc/root.hints(相对于当前工作目录)
bash
# 通过 CLI 参数指定
tdns --config /etc/tdns/tdns.toml --root-hints /etc/tdns/root.hints

格式说明 ​

root.hints 使用 BIND 缓存文件格式(4 列,不含 IN 类字段):

.           3600000  NS   a.root-servers.net.
a.root-servers.net. 3600000 A    198.41.0.4
a.root-servers.net. 3600000 AAAA 2001:503:ba3e::2:30

定期更新 ​

根提示文件会随时间过期(根服务器 IP 偶尔变更),建议每 3-6 个月更新一次:

bash
# 从 IANA 下载最新版本
curl -o /etc/tdns/root.hints https://www.internic.net/domain/named.root

# 或用 dig
dig @a.root-servers.net . NS > /etc/tdns/root.hints

# 热重载生效
sudo systemctl reload tdns

缓存系统 ​

正向缓存 ​

成功解析的响应按 TTL 缓存。TTL 受 min-ttl 和 max-ttl 约束:

toml
[cache]
min-ttl = 60        # 响应 TTL < 60 → 使用 60(防短 TTL 放大攻击)
max-ttl = 86400     # 响应 TTL > 86400 → 使用 86400(保证数据新鲜度)

负缓存 ​

NXDOMAIN 和 NODATA 响应也缓存,TTL 由 negative-ttl 控制(默认 300 秒)。负缓存响应携带 SOA 权威记录(RFC 2308)。

toml
[cache]
negative-ttl = 300              # 负缓存 5 分钟
max-negative-entries = 50000    # 负缓存上限,防 OOM

Serving Stale(RFC 8767) ​

上游服务器全部不可用时,返回过期缓存数据(标记为 stale),而非 SERVFAIL。

toml
[cache]
stale-ttl = 3600   # 过期缓存最长保留 1 小时

缓存预热 ​

启用后,热门记录在 TTL 到期前自动刷新:

toml
[cache]
prefetch-enabled = true
prefetch-threshold = 0.8   # TTL 剩余 < 20% 时触发预热

安全特性 ​

防护项机制如何调整
开放递归防护递归启用时强制要求 allow-recursion,否则拒绝启动配 [access-control] allow-recursion
缓存投毒防护验证上游响应 TXID、源 IP 和源端口自动生效,无需配置
CNAME 循环检测HashSet 跟踪已访问名称recursion.max-depth 调整深度
负缓存容量限制最大 50,000 条目cache.max-negative-entries
正缓存容量保护插入时二次容量检查cache.max-size
查询深度限制CNAME 链最大追踪深度 16recursion.max-depth
并发查询限制Semaphore 限制最大并发递归查询数recursion.max-concurrent-queries

网络环境要求 ​

递归模式需要服务器能直接访问公网 DNS 根服务器(端口 53/UDP+TCP)。

要求说明验证方法
公网出站访问需访问根服务器(如 198.41.0.4 等 13 组 IP)dig @198.41.0.4 . NS
UDP 出站 53向根/TLD/权威发送 UDP 查询nc -u -w3 198.41.0.4 53
TCP 出站 53响应过大时降级 TCPnc -z 198.41.0.4 53
无 NAT 限制UDP 不被 NAT 截断实际递归测试

如果网络环境无法直连根服务器(如内网隔离环境),请使用转发模式代替递归模式。


性能调优 ​

toml
# 高 QPS 递归场景推荐配置
[server]
workers = 0                     # 自动检测 CPU 核心数

[cache]
max-size = "2GB"               # 或 "4GB",高 QPS 场景加大缓存
prefetch-enabled = true        # 启用预热减少延迟
prefetch-threshold = 0.9       # TTL 剩余 < 10% 触发

[recursion]
max-concurrent-queries = 20000 # 高并发递归
query-timeout = "5s"
参数建议值说明
cache.max-size"2GB" ~ "4GB"高 QPS 场景加大缓存
cache.prefetch-enabledtrue启用预热减少延迟
recursion.max-concurrent-queries20000高并发递归
server.workersCPU 核心数0 = 自动检测

内核参数调优 ​

高 QPS 场景建议调整内核参数:

bash
# /etc/sysctl.d/tdns.conf
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 4194304
net.core.wmem_default = 4194304
net.core.somaxconn = 65535

# 应用
sudo sysctl --system