Skip to content

05 - 部署指南 ​

TDNS 支持三种部署方式:systemd 裸机部署、Docker 单容器部署、Docker Compose 编排部署。


方式一:systemd 裸机部署 ​

1. 安装二进制 ​

bash
tar xzf tdns-0.1.1-linux-x86_64.tar.gz
cd tdns-0.1.1-linux-x86_64
sudo cp bin/tdns bin/tdnsctl /usr/local/bin/
sudo chmod +x /usr/local/bin/tdns /usr/local/bin/tdnsctl

2. 创建系统用户 ​

bash
sudo groupadd -r tdns
sudo useradd -r -g tdns -d /var/lib/tdns -s /sbin/nologin -c "TDNS DNS Server" tdns

3. 创建目录结构 ​

bash
sudo mkdir -p /etc/tdns/zones /var/lib/tdns /var/log/tdns /var/run/tdns
sudo chown -R tdns:tdns /etc/tdns /var/lib/tdns /var/log/tdns /var/run/tdns

4. 部署配置文件 ​

bash
sudo cp etc/tdns.toml.example /etc/tdns/tdns.toml
sudo cp etc/root.hints /etc/tdns/root.hints
sudo vim /etc/tdns/tdns.toml

生产环境必须调整的配置项:

toml
[server]
listen-port = 53              # systemd 通过 AmbientCapabilities 自动授权
log-format = "json"           # 结构化日志便于采集

[access-control]
allow-recursion = ["trusted"] # 必填,仅允许受信任客户端

[api]
enabled = true
auth-token = "<随机密钥>"      # 必填,生成方式:openssl rand -hex 32

[tls]                          # 启用时必须配 cert 和 key
enabled = true
cert = "/etc/tdns/cert.pem"
key = "/etc/tdns/key.pem"

5. 安装 systemd 服务 ​

bash
sudo cp deploy/tdns.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable tdns
sudo systemctl start tdns
sudo systemctl status tdns

服务文件特性(deploy/tdns.service):

特性说明
非 root 用户运行User=tdns Group=tdns
特权端口授权AmbientCapabilities=CAP_NET_BIND_SERVICE
安全加固NoNewPrivileges=true
文件系统隔离ProtectSystem=strict + ProtectHome=true
读写限制ReadWritePaths 仅限数据/日志/PID 目录
文件描述符LimitNOFILE=65536

6. 防火墙配置 ​

bash
# firewalld
sudo firewall-cmd --permanent --add-service=dns          # 53/udp+tcp
sudo firewall-cmd --permanent --add-port=853/tcp          # DoT(如启用)
sudo firewall-cmd --permanent --add-port=443/tcp          # DoH(如启用)
sudo firewall-cmd --permanent --add-port=8080/tcp         # API(限内网)
sudo firewall-cmd --reload

# 或用 iptables
sudo iptables -A INPUT -p udp --dport 53 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 853 -j ACCEPT       # DoT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT      # DoH

7. 验证 ​

bash
# DNS 解析验证
dig @127.0.0.1 example.com A +short

# 健康检查(需启用 API)
curl http://127.0.0.1:8080/api/v1/health

# 服务状态
sudo systemctl status tdns

方式二:Docker 部署 ​

构建镜像 ​

bash
docker build -t tdns:0.1.1 .
docker tag tdns:0.1.1 tdns:latest

Dockerfile 特性:

特性说明
多阶段构建rust:1.75-slim-bookworm → debian:bookworm-slim
非 root 用户tdns 用户运行
特权端口授权setcap 'cap_net_bind_service=+ep'
内置健康检查API 优先,PID 回退
镜像大小约 80 MB

运行容器 ​

bash
docker run -d \
    --name tdns \
    --restart unless-stopped \
    --cap-add=NET_BIND_SERVICE \
    -p 53:53/udp \
    -p 53:53/tcp \
    -p 853:853/tcp \
    -p 443:443/tcp \
    -p 8080:8080/tcp \
    -v /etc/tdns:/etc/tdns:ro \
    -v /var/lib/tdns:/var/lib/tdns \
    -e TDNS_API_TOKEN=your-secret \
    tdns:latest

853/443 端口仅在 [tls] / [doh] enabled = true 时需要映射。

验证 ​

bash
# 查看容器状态
docker ps | grep tdns

# 查看日志
docker logs -f tdns

# DNS 解析验证
dig @127.0.0.1 example.com

# 健康检查
curl http://127.0.0.1:8080/api/v1/health

方式三:Docker Compose 部署 ​

编写配置 ​

yaml
# deploy/docker-compose.yml
version: "3.8"

services:
  tdns:
    build:
      context: ..
      dockerfile: Dockerfile
    container_name: tdns
    restart: unless-stopped
    ports:
      - "53:53/udp"
      - "53:53/tcp"
      - "853:853/tcp"
      - "443:443/tcp"
      - "8080:8080/tcp"
    volumes:
      - ./tdns.toml:/etc/tdns/tdns.toml:ro
      - ../etc/root.hints:/etc/tdns/root.hints:ro
      - tdns-data:/var/lib/tdns
    healthcheck:
      test: ["CMD-SHELL", "tdnsctl --api http://127.0.0.1:8080 status 2>/dev/null || kill -0 \"$$(cat /var/run/tdns/tdns.pid 2>/dev/null)\" 2>/dev/null || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

volumes:
  tdns-data:

操作命令 ​

bash
cd deploy/

# 准备配置
cp ../etc/tdns.toml.example tdns.toml
vim tdns.toml

# 构建并启动
docker compose up -d --build

# 查看状态
docker compose ps

# 查看日志
docker compose logs -f tdns

# 停止
docker compose down

# 更新(重新构建)
docker compose down
docker compose up -d --build

特权端口授权说明 ​

DNS 标准端口 53 是特权端口(< 1024),而 TDNS 以非 root 用户运行。授权方式取决于部署方式:

部署方式授权机制说明
Dockersetcap 'cap_net_bind_service=+ep'Dockerfile 中自动设置
systemdAmbientCapabilities=CAP_NET_BIND_SERVICEservice 文件中自动设置
手动部署sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/tdns需手动执行
开发测试listen-port = 5353用非特权端口规避

当 NoNewPrivileges=true 生效时(如 systemd 服务),setcap 文件能力会被内核忽略,必须使用 AmbientCapabilities 代替。


目录结构参考 ​

/etc/tdns/                    # 配置目录
├── tdns.toml                 # 主配置文件
├── root.hints                # 根服务器提示文件
├── cert.pem                  # TLS 证书(如启用 DoT/DoH)
├── key.pem                   # TLS 私钥(如启用 DoT/DoH)
└── zones/                    # 区域数据文件
    └── example.com.zone

/var/lib/tdns/                # 数据目录(SQLite 等)
/var/log/tdns/                # 日志目录
/var/run/tdns/                # PID 文件
/usr/local/bin/tdns           # 服务器二进制
/usr/local/bin/tdnsctl        # 管理工具二进制
/etc/systemd/system/tdns.service  # systemd 服务文件

下一步 ​