外观
07 - 权威 DNS 服务
概述
权威模式(authoritative)下,TDNS 作为区域数据的权威来源,应答自身管理区域的 DNS 查询。对非自身管理区域的查询返回 REFUSED。
适用场景:公网权威 DNS、CDN/GSLB 分发、内网域名解析、自有域名管理。
快速上手:三步跑通权威服务
1. 配置区域
toml
# /etc/tdns/tdns.toml
[server]
mode = "authoritative"
listen-addrs = ["0.0.0.0", "::"]
listen-port = 53
[[zones]]
name = "example.com"
file = "/etc/tdns/zones/example.com.zone"
type = "master"
[access-control]
allow-query = ["any"] # 公网可查
allow-recursion = ["none"] # 不提供递归2. 编写 Zone 文件
text
; /etc/tdns/zones/example.com.zone
$TTL 3600
@ IN SOA ns1.example.com. admin.example.com. (
2026081001 ; Serial —— 每次改记录递增,辅 DNS 据此拉取
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
; 名称服务器
IN NS ns1.example.com.
IN NS ns2.example.com.
ns1 IN A 192.0.2.1
ns2 IN A 192.0.2.2
; 主域名记录
@ IN A 192.0.2.10
@ IN AAAA 2001:db8::10
@ IN MX 10 mail.example.com.
; 子域名
www IN CNAME @
api IN A 192.0.2.11
mail IN A 192.0.2.12
; 通配符(未明确的一级子域名都走这里)
* IN A 192.0.2.10
; 文本与 CA 授权
@ IN TXT "v=spf1 include:_spf.example.com ~all"
@ IN CAA 0 issue "letsencrypt.org"3. 热重载 + 验证
bash
# 验证配置
tdns --validate --config /etc/tdns/tdns.toml
# 启动或热重载
sudo systemctl reload tdns
# 或直接发信号
sudo kill -HUP $(cat /var/run/tdns/tdns.pid)
# 验证解析
dig @127.0.0.1 example.com SOA
dig @127.0.0.1 www.example.com
dig @127.0.0.1 example.com MXSOA 的 Serial 每次改记录记得递增,方便辅 DNS 同步。推荐格式
YYYYMMDDNN(年月日+当日序号)。
多区域配置
支持正向解析区域和反向解析区域(in-addr.arpa):
toml
[[zones]]
name = "example.com"
file = "/etc/tdns/zones/example.com.zone"
type = "master"
[[zones]]
name = "0.168.192.in-addr.arpa"
file = "/etc/tdns/zones/rev-192.168.0.zone"
type = "master"Zone 文件格式详解
支持的指令
| 指令 | 说明 | 示例 |
|---|---|---|
$TTL | 默认 TTL(秒) | $TTL 3600 |
$ORIGIN | 区域起始域(影响相对名称解析) | $ORIGIN example.com. |
支持的记录类型
| 类型 | 说明 | Zone 文件示例 |
|---|---|---|
| A | IPv4 地址 | www IN A 192.0.2.10 |
| AAAA | IPv6 地址 | www IN AAAA 2001:db8::10 |
| NS | 名称服务器 | @ IN NS ns1.example.com. |
| CNAME | 别名 | www IN CNAME @ |
| SOA | 起始授权 | @ IN SOA ns1... admin... ( ... ) |
| PTR | 反向指针 | 10 IN PTR host.example.com. |
| MX | 邮件交换 | @ IN MX 10 mail.example.com. |
| TXT | 文本 | @ IN TXT "v=spf1 ..." |
| SRV | 服务定位 | _sip._tcp IN SRV 10 60 5060 sip.example.com. |
| CAA | CA 授权 | @ IN CAA 0 issue "letsencrypt.org" |
| SVCB / HTTPS | 服务绑定(RFC 9460) | _https IN HTTPS 1 . alpn="h2,h3" |
记录类型与添加方式
| 类型 | Zone 文件 | REST API | 说明 |
|---|---|---|---|
| A / AAAA | ✅ | ✅ | IPv4 / IPv6 地址 |
| CNAME / NS / PTR | ✅ | ✅ | 别名 / 名称服务器 / 反向指针 |
| TXT | ✅ | ✅ | 文本(SPF、验证等) |
| SVCB / HTTPS | ✅ | ✅ | 服务绑定(RFC 9460) |
| MX / SOA / SRV | ✅ | ❌ | 需通过 Zone 文件添加 |
| CAA | ✅ | ❌ | CA 授权,需通过 Zone 文件添加 |
通过 REST API 管理记录
先在配置中开启 API:
toml
[api]
enabled = true
listen = "127.0.0.1:8080"
auth-token = "your-secret-token" # 启用 API 时必填启动后用 curl 管理记录:
bash
TOKEN="your-secret-token"
BASE="http://127.0.0.1:8080"
# 列出已有区域
curl -s -H "Authorization: Bearer $TOKEN" $BASE/api/v1/zones | jq
# 添加 A 记录(区域不存在会自动创建 example.com.)
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name":"www.example.com","type":"A","ttl":300,"data":"192.0.2.10"}' \
$BASE/api/v1/zones/example.com/records | jq
# 添加 AAAA
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name":"www.example.com","type":"AAAA","ttl":300,"data":"2001:db8::10"}' \
$BASE/api/v1/zones/example.com/records | jq
# 添加 TXT
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name":"example.com","type":"TXT","ttl":3600,"data":"v=spf1 -all"}' \
$BASE/api/v1/zones/example.com/records | jq
# 列出区域所有记录
curl -s -H "Authorization: Bearer $TOKEN" \
$BASE/api/v1/zones/example.com/records | jq
# 删除记录
curl -s -X DELETE -H "Authorization: Bearer $TOKEN" \
$BASE/api/v1/zones/example.com/records/www.example.com/A | jq
# 验证
dig @127.0.0.1 www.example.com AAPI 适合自动化和 GSLB 动态调度:健康检查通过就 POST 加节点,失败就 DELETE 删节点。完整 API 参考见 13-REST-API参考。
通过 TSIG 认证的 DDNS 动态更新
1. 配置 TSIG 密钥
toml
# /etc/tdns/tdns.toml
[[keys]]
name = "update-key."
algorithm = "hmac-sha256"
secret = "<base64-encoded-secret>"
[[zones]]
name = "example.com"
file = "/etc/tdns/zones/example.com.zone"
allow-update = ["update-key."] # 允许此密钥执行 DDNS生成密钥:
bash
# 使用 tsig-keygen(BIND 工具)
tsig-keygen -a HMAC-SHA256 update-key
# 或手动生成
echo -n "your-secret" | base642. 使用 nsupdate 发送动态更新
bash
nsupdate -k Kupdate-key.+157+12345.key << EOF
server 127.0.0.1 53
zone example.com
update add www.example.com 300 A 192.0.2.100
show
send
EOF3. 验证
bash
dig @127.0.0.1 www.example.com A +short
# 应返回 192.0.2.100详细 TSIG 配置见 12-安全与访问控制。
查询匹配规则
精确匹配
查询 www.example.com 的 A 记录,直接在区域中查找 (www, A) 条目。
通配符匹配
通配符 *.example.com 匹配所有未明确定义的一级子域名。更具体的记录优先于通配符(掩蔽规则,RFC 4592)。
CNAME 链追踪
查询目标存在 CNAME 记录时,自动追踪 CNAME 链获取最终 A/AAAA 记录。最大追踪深度由 recursion.max-depth 控制(默认 16),超过深度或检测到循环则返回错误。
胶水记录
在权威响应的 Additional Section 中附加相关 NS 记录对应的 A/AAAA 记录。
委托处理
区域中存在子域 NS 记录时,返回 Referral 响应(Authority Section 包含子域 NS 记录,Additional Section 包含胶水记录)。
修改后何时生效
- Zone 文件改完 → 发
SIGHUP或POST /api/v1/reload热重载,原子替换区域 - REST API 增删 → 立即生效,无需重载
- 配置文件结构变(加新区域、改端口等) → 热重载
bash
# 热重载
sudo systemctl reload tdns
# 或
sudo kill -HUP $(cat /var/run/tdns/tdns.pid)
# 或
tdnsctl reload
# 或
curl -s -X POST -H "Authorization: Bearer $TOKEN" $BASE/api/v1/reload | jq热重载会重新读取配置文件和 Zone 文件,原子替换区域目录。缓存和 ACL 等其他配置保持不变。