Skip to content

16 - 运维操作手册 ​

本文是 TDNS 日常运维的操作手册,每一步都给到可直接复制的命令。按章节对号入座,照着做就行。


服务管理 ​

systemd 部署 ​

bash
# 启动 / 停止 / 重启
sudo systemctl start tdns
sudo systemctl stop tdns
sudo systemctl restart tdns

# 热重载(不中断现有查询,改配置首选)
sudo systemctl reload tdns

# 查看状态 + 最近日志
sudo systemctl status tdns

# 开机自启
sudo systemctl enable tdns
sudo systemctl disable tdns     # 关闭自启

# 查看最近 100 行日志
journalctl -u tdns -n 100 --no-pager

# 实时跟踪日志
journalctl -u tdns -f

Docker 部署 ​

bash
# 启动
docker compose up -d

# 停止 / 重启
docker compose down
docker compose restart tdns

# 查看日志
docker compose logs -f tdns

# 进入容器排查
docker compose exec tdns sh

# 热重载(容器内发 SIGHUP)
docker compose exec tdns kill -HUP 1

裸进程部署 ​

bash
# 前台运行(调试首选,日志直接输出到终端)
tdns --config /etc/tdns/tdns.toml --log-level debug

# 后台运行
nohup tdns --config /etc/tdns/tdns.toml &
echo $! > /var/run/tdns/tdns.pid

# 优雅关闭(等现有查询处理完再退出)
kill -TERM $(cat /var/run/tdns/tdns.pid)

# 热重载
kill -HUP $(cat /var/run/tdns/tdns.pid)

配置变更流程 ​

标准变更步骤(4 步) ​

bash
# 1️⃣ 备份当前配置(永远先备份)
sudo cp /etc/tdns/tdns.toml /etc/tdns/tdns.toml.bak.$(date +%Y%m%d%H%M)

# 2️⃣ 编辑配置
sudo vi /etc/tdns/tdns.toml

# 3️⃣ 验证配置(语法 + 逻辑校验,不会启动服务)
tdns --validate --config /etc/tdns/tdns.toml
# 或用 CLI 工具
tdnsctl validate /etc/tdns/tdns.toml

# 4️⃣ 热重载,立即生效
sudo systemctl reload tdns
# 或
tdnsctl reload

# 确认状态
tdnsctl status

哪些变更能热重载,哪些必须重启? ​

变更项热重载重启说明
Zone 文件内容✅—原子替换,不中断查询
新增 / 删除 [[zones]]✅—区域加载 / 卸载
ACL 地址列表✅—访问控制即时更新
转发器列表✅—上游变更即时生效
缓存配置(大小、TTL)✅—缓存参数更新
安全配置(RRL 等)✅—速率限制即时生效
server.listen-addrs / listen-port—✅监听地址变更需重新绑定
server.workers—✅线程数变更
[tls] / [doh] 启用 / 禁用—✅监听器变更
[api] / [metrics] 启用 / 禁用—✅HTTP 服务器变更
Feature flag 变更—✅需重新编译

经验法则:改"内容"的走热重载,改"监听"的重启。不确定就先 --validate,过了再 reload。


区域管理 ​

添加新区域(Zone 文件方式,4 步) ​

bash
# 1️⃣ 创建 Zone 文件
sudo vi /etc/tdns/zones/newzone.com.zone
text
; /etc/tdns/zones/newzone.com.zone
$TTL 3600
@   IN  SOA ns1.example.com. admin.example.com. (
        2026081001  ; Serial —— 每次改记录递增
        3600        ; Refresh
        1800        ; Retry
        604800      ; Expire
        86400 )     ; Minimum TTL

    IN  NS  ns1.example.com.
@   IN  A   192.0.2.10
www IN  A   192.0.2.20
bash
# 2️⃣ 在配置中声明区域
sudo vi /etc/tdns/tdns.toml
toml
[[zones]]
name = "newzone.com"
file = "/etc/tdns/zones/newzone.com.zone"
type = "master"
bash
# 3️⃣ 验证 + 热重载
tdnsctl validate /etc/tdns/tdns.toml
tdnsctl reload

# 4️⃣ 验证解析
dig @127.0.0.1 www.newzone.com A
dig @127.0.0.1 newzone.com SOA

通过 REST API 添加记录(无需改 Zone 文件) ​

bash
TOKEN="your-secret-token"
BASE="http://127.0.0.1:8080"

# 添加 A 记录(区域不存在会自动创建)
curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"api.newzone.com","type":"A","ttl":300,"data":"192.0.2.30"}' \
  "$BASE/api/v1/zones/newzone.com/records"

# 验证
dig @127.0.0.1 api.newzone.com A +short

修改 Zone 文件后递增 Serial ​

BIND 格式要求每次修改 Zone 文件后递增 SOA Serial,否则次级服务器不会同步:

text
@   IN  SOA ns1.example.com. admin.example.com. (
        2026081001  ; Serial — 改记录后改成 2026081002

Serial 推荐格式:YYYYMMDDNN(年月日 + 当日序号),如 2026081001 → 2026081002。

删除区域(3 步) ​

bash
# 1️⃣ 从配置中移除 [[zones]] 段
sudo vi /etc/tdns/tdns.toml

# 2️⃣ 可选:删除 Zone 文件
sudo rm /etc/tdns/zones/oldzone.com.zone

# 3️⃣ 验证 + 热重载
tdnsctl validate /etc/tdns/tdns.toml
tdnsctl reload

缓存管理 ​

查看缓存统计 ​

bash
tdnsctl stats

输出包含缓存条目数、命中率、正 / 负缓存数量等。

清空全部缓存 ​

配置变更或区域更新后,清空缓存让变更立即生效:

bash
# CLI
tdnsctl flush

# API
curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8080/api/v1/cache/flush

清空指定域名缓存 ​

bash
# CLI
tdnsctl flush-name www.example.com

# API
curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8080/api/v1/cache/flush/www.example.com

缓存调优建议 ​

场景推荐配置
高 QPS 公网 DNSmax-size = "4GB", prefetch-enabled = true
内网 DNSmax-size = "512MB"
权威 DNS(无递归)cache.enabled = false 或小缓存
低延迟要求min-ttl = 30, prefetch-threshold = 0.9
防缓存投毒negative-ttl = 60, max-negative-entries = 10000

日志管理 ​

日志轮转 ​

systemd 自动管理 journald 日志。对于文件日志,配置 logrotate:

# /etc/logrotate.d/tdns
/var/log/tdns/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}

临时启用调试日志 ​

bash
# 停止后台服务
sudo systemctl stop tdns

# 前台调试运行(日志直接输出到终端)
tdns --config /etc/tdns/tdns.toml --log-level debug

# 或 trace 级别(更详细)
tdns --config /etc/tdns/tdns.toml --log-level trace

关键日志过滤 ​

bash
# 递归解析失败
journalctl -u tdns | grep "recursive.*failed\|SERVFAIL"

# 上游超时
journalctl -u tdns | grep "upstream.*timeout"

# ACL 拒绝
journalctl -u tdns | grep "REFUSED\|ACL"

# Zone 加载失败
journalctl -u tdns | grep "zone.*error\|zone.*failed"

# TLS 握手失败
journalctl -u tdns | grep "handshake.*failed"

备份与恢复 ​

配置备份(定期 cron) ​

bash
# 手动备份配置 + Zone 文件
sudo tar -czf tdns-backup-$(date +%Y%m%d).tar.gz \
  /etc/tdns/tdns.toml \
  /etc/tdns/zones/ \
  /etc/tdns/root.hints

# 每日凌晨 2 点自动备份
echo "0 2 * * * tar -czf /backup/tdns-$(date +\%Y\%m\%d).tar.gz /etc/tdns/" | sudo crontab -

区域数据导出(通过 API) ​

bash
# 导出所有区域的记录为 JSON
curl -s -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8080/api/v1/zones | jq -r '.zones[].origin' | \
  while read zone; do
    curl -s -H "Authorization: Bearer $TOKEN" \
      "http://127.0.0.1:8080/api/v1/zones/$zone/records" > "/backup/${zone}.json"
  done

恢复流程(5 步) ​

bash
# 1️⃣ 停止服务
sudo systemctl stop tdns

# 2️⃣ 恢复配置
sudo tar -xzf tdns-backup-20260810.tar.gz -C /

# 3️⃣ 验证配置
tdns --validate --config /etc/tdns/tdns.toml

# 4️⃣ 启动
sudo systemctl start tdns

# 5️⃣ 确认状态
tdnsctl status

证书管理(DoT / DoH) ​

查看证书有效期 ​

bash
openssl x509 -in /etc/tdns/tls/fullchain.pem -noout -dates

证书续期(Let's Encrypt) ​

bash
# 续期
sudo certbot renew --quiet

# 续期后热重载 TDNS(重新加载证书)
sudo systemctl reload tdns

证书过期告警(cron) ​

bash
# 每天检查,过期前 30 天告警
echo "0 9 * * * openssl x509 -in /etc/tdns/tls/fullchain.pem -checkend 2592000 -noout || echo 'TDNS certificate expiring soon!'" | crontab -

root.hints 更新(递归模式) ​

递归模式需要定期更新 root.hints 文件:

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

建议每 3-6 个月更新一次。根服务器 IP 很少变更,但保持更新是好习惯。


性能调优 ​

内核参数 ​

bash
# /etc/sysctl.d/tdns.conf

# UDP 缓冲区(高 QPS 场景必调)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 4194304
net.core.wmem_default = 4194304

# 连接队列
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# 端口范围(转发 / 递归模式)
net.ipv4.ip_local_port_range = 10240 65535

# 应用
sudo sysctl --system

文件描述符限制 ​

bash
# /etc/security/limits.d/tdns.conf
tdns  soft  nofile  65535
tdns  hard  nofile  65535

systemd 服务文件中也设置:

ini
[Service]
LimitNOFILE=65535

Worker 线程 ​

toml
[server]
workers = 0    # 0 = 自动检测 CPU 核心数(推荐)

手动设置:

toml
[server]
workers = 4    # 建议等于或小于物理核心数

安全运维 ​

API Token 轮换 ​

bash
# 1️⃣ 生成新 Token
NEW_TOKEN=$(openssl rand -hex 32)

# 2️⃣ 更新配置(注意字段名是 auth-token)
sudo sed -i "s/^auth-token = .*/auth-token = \"$NEW_TOKEN\"/" /etc/tdns/tdns.toml

# 3️⃣ 热重载
tdnsctl reload

# 4️⃣ 更新客户端环境变量
export TDNS_API_TOKEN="$NEW_TOKEN"

定期检查清单 ​

检查项频率命令
证书有效期每周openssl x509 -checkend 2592000 -noout
root.hints 更新每 3-6 月对比 IANA 版本
缓存命中率每日tdnsctl stats
RRL 丢弃率每日curl -s http://localhost:9090/metrics | grep rrl
上游可用性每日curl -s http://localhost:9090/metrics | grep upstream
配置备份每周tar 备份
日志清理每月logrotate
Rust 安全公告随时关注 Rust 安全公告

下一步 ​