Technitium DNS Server 日常运维与监控告警手册

Technitium DNS Server 15.6.2 日常运维与监控告警手册:容器健康、53 端口 dig 探活、Web 可用性、查询日志与磁盘水位的巡检闭环,备份恢复、升级回滚,以及解析失败、端口占用、拦截误杀等故障排查手册,全部附实测原始回显。

Technitium DNSDNS 服务2026/10/19

Technitium DNS Server 日常运维与监控告警手册

目标:为 Technitium DNS Server 15.6.2 建立日常巡检闭环(服务健康、DNS 探活、Web 可用性、查询日志、磁盘水位)、备份恢复与升级回滚流程,并沉淀解析失败、端口占用等故障的排查手册。全部命令在 Ubuntu 22.04.4 + Docker 29.8.1 部署的 v15.6.2 实例实测,回显原文照抄(部署见《Technitium DNS Server Docker Compose 部署指南》,配置项含义见《Technitium DNS Server 15.6.2 配置详解》)。

一、环境信息

  • 操作系统:Ubuntu 22.04.4 LTS(x86_64);Docker 29.8.1;Docker Compose v5.5.1
  • 软件:Technitium DNS Server v15.6.2(容器 technitium-dns-15.6.2-server,compose 项目目录 /opt/data/quzuo/technitium-dns/)
  • 访问入口:DNS 5300/udp+tcp(宿主 53 被 systemd-resolved 占用,取舍见部署篇)、Web 管理台 8118、DoT 8530、DoH 9543
  • 管理凭据:admin / q1w2e3r4(API 基址 http://127.0.0.1:8118/api/)
  • 数据目录:config/(配置+zone+黑名单缓存)、logs/(按天日志)
  • 健康检查端点:GET /api/dnsClient/healthCheck(官方 healthcheck 同源)

二、日常巡检

每天 5 项巡检构成闭环:容器健康 → DNS 探活 → Web 可用 → 日志异常 → 磁盘水位。每项给出命令、实测回显与判定标准。

2.1 容器健康状态

cd /opt/data/quzuo/technitium-dns && docker compose ps

实测回显:

NAME                           IMAGE                          COMMAND                   SERVICE      CREATED         STATUS                    PORTS
technitium-dns-15.6.2-server   technitium/dns-server:15.6.2   "/usr/bin/dotnet /op…"   dns-server   5 seconds ago   Up 5 seconds (health: starting)   67/udp, 80/tcp, 8053/tcp, 853/udp, 53443/tcp, 0.0.0.0:5300->53/tcp, 0.0.0.0:5300->53/udp, ...

启动约 40 秒后 STATUS 变为 Up (healthy)(healthcheck:30s 间隔调 /api/dnsClient/healthCheck 校验 "status":"ok")。判定:STATUS 必须含 (healthy);出现 (unhealthy) 或 Restarting 立即转 7.1 节排查。

2.2 DNS 服务探活(53 端口 dig)

权威与递归各探一条(权威探本地 zone 最快最准):

dig @127.0.0.1 -p 5300 lab.internal A +noall +answer        # 权威探针(部署时创建的 zone)
dig @127.0.0.1 -p 5300 www.baidu.com A +noall +answer       # 递归探针

实测回显:

lab.internal.           3600    IN      A       10.89.46.10
www.baidu.com.          1200    IN      CNAME   www.a.shifen.com.
www.a.shifen.com.       120     IN      A       110.242.69.21

判定:权威探针必有答案;递归探针超时/无答案说明上游或递归链路故障(转 7.2 节)。服务挂掉时 dig 的失败形态(实测):

dig @127.0.0.1 -p 5399 www.baidu.com A +time=2 +tries=1
;; communications error to 127.0.0.1#5399: connection refused

; <<>> DiG 9.18.39-0ubuntu0.22.04.6-Ubuntu <<>> @127.0.0.1 -p 5399 www.baidu.com A +time=2 +tries=1
; (1 server found)
;; global options: +cmd

2.3 Web 管理台可用性

curl -s http://127.0.0.1:8118/api/dnsClient/healthCheck
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:8118/

实测回显:

{"status":"ok"}
HTTP 200

判定:健康端点必须返回 {"status":"ok"},页面 200。

2.4 查询日志与服务日志异常扫描

日志在 logs/<日期>.log,含服务事件与查询记录两种行。先确认查询日志已开启(配置见《Technitium DNS Server 15.6.2 配置详解》5.6 节,实测开启后行格式):

tail -2 /opt/data/quzuo/technitium-dns/logs/2026-10-19.log

实测回显:

[2026-10-19 05:28:52 UTC] [10.89.46.1:39855] [UDP] QNAME: doubleclick.net; QTYPE: A; QCLASS: IN; RCODE: NxDomain; ANSWER: []
[2026-10-19 05:28:52 UTC] [10.89.46.1:49152] [UDP] QNAME: www.baidu.com; QTYPE: A; QCLASS: IN; RCODE: NoError; ANSWER: [www.a.shifen.com., 110.242.69.21, 110.242.70.57]

异常扫描三连(错误/拒绝/慢查询):

grep -c "ERROR\|error" /opt/data/quzuo/technitium-dns/logs/$(date +%F).log   # 错误计数
grep "QTYPE" /opt/data/quzuo/technitium-dns/logs/$(date +%F).log | grep -c "RCODE: ServerFailure\|RCODE: ServFail"   # 解析失败计数
grep "QTYPE" /opt/data/quzuo/technitium-dns/logs/$(date +%F).log | grep -c "RCODE: Refused"   # 拒绝响应(客户端违规递归)

实测回显(正常日):

0
1
0

判定:错误行应为 0;ServerFailure/Refused 持续增长需查上游与 ACL。当日服务事件中的正常启动序列(实测样例,作为对照基线):

[2026-10-19 05:26:22 UTC] DNS Server (v15.6.2.0) was started successfully.
[2026-10-19 05:26:27 UTC] DNS Server is downloading block list: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
[2026-10-19 05:28:52 UTC] [10.89.46.1:39855] [UDP] QNAME: doubleclick.net; QTYPE: A; QCLASS: IN; RCODE: NxDomain; ANSWER: []

黑名单加载行是启动后必查项(域名计数与拦截统计对账):

[2026-10-19 05:19:27 UTC] DNS Server read block list file (71492 domain(s) blocked) from: https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts

2.5 磁盘水位

DNS 服务的磁盘消耗点:日志目录(默认保留 90 天)与统计文件。巡检命令:

df -h /opt/data | tail -1
du -sh /opt/data/quzuo/technitium-dns/config /opt/data/quzuo/technitium-dns/logs

实测回显:

/dev/sda3       786G  262G  490G  35% /
291M    /opt/data/quzuo/technitium-dns/config
160K    /opt/data/quzuo/technitium-dns/logs

判定:使用率超过 80% 告警;config/ 占用大头是黑名单缓存与统计(本文 291 MB,含 2.1 MB 黑名单与多日 stat 文件,属正常量级)。日志膨胀治理:DNS_SERVER_LOG_MAX_LOG_FILE_DAYS=90(可调小);统计保留由 Settings → Statistics 的保留天数控制(默认 365 天)。

2.6 巡检一键脚本

把 5 项巡检串成一个可入 cron 的脚本(输出全部实测可跑):

#!/usr/bin/env bash
# /opt/data/quzuo/technitium-dns/inspect.sh — Technitium DNS 日常巡检
cd /opt/data/quzuo/technitium-dns
echo "== 1.容器健康 ==";  docker compose ps --format 'table {{.Name}}\t{{.Status}}'
echo "== 2.DNS探活 ==";   dig @127.0.0.1 -p 5300 lab.internal A +noall +answer && dig @127.0.0.1 -p 5300 www.baidu.com A +noall +answer | head -1
echo "== 3.Web可用 ==";   curl -s http://127.0.0.1:8118/api/dnsClient/healthCheck
echo "== 4.日志异常 ==";  echo "error=$(grep -ci 'error' logs/$(date +%F).log) servfail=$(grep 'QTYPE' logs/$(date +%F).log | grep -c 'ServerFailure') refused=$(grep 'QTYPE' logs/$(date +%F).log | grep -c 'Refused')"
echo "== 5.磁盘水位 ==";  df -h /opt/data | tail -1 | awk '{print "used="$3" avail="$4" pct="$5}'

实测回显:

== 1.容器健康 ==
technitium-dns-15.6.2-server   Up 34 minutes (healthy)
== 2.DNS探活 ==
lab.internal.           3600    IN      A       10.89.46.10
www.baidu.com.          1200    IN      CNAME   www.a.shifen.com.
== 3.Web可用 ==
{"status":"ok"}
== 4.日志异常 ==
error=0 servfail=1 refused=0
== 5.磁盘水位 ==
used=262G avail=490G pct=35%

三、备份与恢复

做什么:配置+zone+黑名单缓存+统计的一键备份与还原。两条通道:管理台 Backup/Restore 页,或 API(本文实测 API)。

备份(zip 含 11 个对象,554 KB 量级):

TOKEN=<token>
curl -s -o /opt/data/quzuo/technitium-dns/backup-$(date +%F).zip \
  "http://127.0.0.1:8118/api/settings/backup?token=$TOKEN&blockLists=true&logs=false&scopes=true&stats=true&zones=true&allowedZones=true&blockedZones=true&dnsSettings=true&logSettings=true&authConfig=true"
python3 -c "import zipfile;print('\n'.join(zipfile.ZipFile('/opt/data/quzuo/technitium-dns/backup-2026-10-19.zip').namelist()))"

实测回显(备份对象清单):

auth.config
dns.config
tls/dns-lab.pfx
log.config
zones/lab.internal.zone
allowed.config
blocked.config
blocklist.config
blocklists/603e776c4f62b98ab5930dbb790e02bc215a3a571e56cc472e020ca36c8d44dd
scopes/Default.scope
stats/2026101905.stat

恢复:管理台 Backup/Restore 页上传 zip(或 POST /api/settings/restore?...&deleteExistingFiles=true),还原后重启容器生效。目录级兜底:直接 tar 两个数据目录(全量含日志,适合整机迁移):

tar czf /opt/data/quzuo/technitium-dns/full-backup-$(date +%F).tar.gz -C /opt/data/quzuo/technitium-dns config logs

💡 建议:API 备份入 cron(每日一次),目录级 tar 每周一次;zip 备份体积小恢复快,tar 兜底防 API 层问题。

四、监控告警

4.1 指标与阈值(实测口径)

Dashboard 统计 API(/api/dashboard/stats/get)返回结构化指标,LastHour 窗口实测:

curl -s "http://127.0.0.1:8118/api/dashboard/stats/get?token=$TOKEN&type=LastHour&utc=true" | python3 -c "
import json,sys
s=json.load(sys.stdin)['response']['stats']
for k in ['totalQueries','totalNoError','totalNxDomain','totalServerFailure','totalBlocked','totalCached','totalAuthoritative','totalRecursive','totalClients','cachedEntries','blockListZones']:
    print(k,'=',s.get(k))"

实测回显:

totalQueries = 14
totalNoError = 9
totalNxDomain = 4
totalServerFailure = 1
totalBlocked = 5
totalCached = 2
totalAuthoritative = 4
totalRecursive = 3
totalClients = 1
cachedEntries = 37
blockListZones = 71492

建议告警阈值(基于上述实测口径):

指标含义建议阈值/动作
totalServerFailureSERVFAIL 数每小时 >10 告警(上游/递归故障)
totalQueries查询总量环比突增 >5x 告警(内网中招/扫描)
totalBlocked拦截量突增告警(恶意软件活动信号)
totalNoError/totalQueries成功率<95% 告警
blockListZones黑名单域名数与黑名单源对账(本文 71492),掉 0 告警(源下载失败)
healthCheck服务健康非 {"status":"ok"} 即告警
dig 权威探针DNS 面可用失败 2 次连续告警

4.2 接入外部监控(探针形态)

任何支持 HTTP/dig 探针的监控器都能直接接入,无需 Agent:

  • HTTP 探针:GET http://<IP>:8118/api/dnsClient/healthCheck,断言响应含 "status":"ok"(可用《Gatus 介绍与选型指南》endpoint + conditions: ["[BODY].status == ok"] 或《Uptime Kuma 介绍与选型指南》HTTP-Keyword 类型);
  • DNS 探针:dig/mDNS 探测 @<IP> -p 5300 lab.internal(Gatus dns 查询类型、Zabbix DNS check 等);
  • 端口探针:TCP 8118/5300 拨测兜底。

4.3 拦截临时关闭(应急处置)

误杀爆发时先止血再排查(5 分钟窗口自动恢复):

curl -s -X POST "http://127.0.0.1:8118/api/settings/temporaryDisableBlocking?token=$TOKEN&minutes=5"

五、扩容缩容

  • 纵向:单实例为无状态内存型服务,内存消耗随 cachedEntries 缓存量增长,默认配置足够千级终端;升配直接改 compose 资源限制后 up -d。
  • 横向:官方 Clustering 功能把多实例组成集群统一管理(README 特性;管理台 Settings → Clustering 初始化,主节点生成邀请,从节点加入后配置自动同步)。第二节点照部署篇流程再起一套(独立数据目录、独立子网槽位,如 10.89.47.0/24),客户端 DNS 轮询指向两台即可。
  • 缩容:先在 Clustering 页摘除节点,再 docker compose down;删除数据目录前务必完成第三节备份。

六、升级与回滚

升级(当前 v15.6.2 为最新,升级到未来版本的通用流程):

cd /opt/data/quzuo/technitium-dns
# 1. 备份(第三节任一方式)
# 2. 改 compose 内 image tag:15.6.2 → <新版本>
docker compose pull && docker compose up -d
docker compose ps --format 'table {{.Name}}\t{{.Status}}'
docker logs technitium-dns-15.6.2-server 2>&1 | head -1

启动日志确认新版本号(实测格式):

Technitium DNS Server v15.6.2 was started successfully.

回滚:compose 的 image tag 改回旧版本 → docker compose up -d。数据目录向后兼容风险低,但大版本降级前先用第三节 zip 备份;若新版做了配置迁移,用备份 zip + 删除 config 目录的方式回到旧版数据基线。

七、故障排查手册

7.1 容器 unhealthy / 反复重启

docker compose logs --tail 50
docker exec technitium-dns-15.6.2-server curl -s http://127.0.0.1:5380/api/dnsClient/healthCheck

常见原因:宿主内存不足(OOM,dmesg | grep -i oom)、配置目录权限(root 属主即可)、healthcheck 的 curl 不通(网络命名空间异常,重启容器)。

7.2 解析失败(无答案/超时)

按链路分段定位(每步实测过):

  1. 服务挂:connection refused(2.2 节失败形态回显)→ docker compose ps 看状态,重启;
  2. 上游/递归故障:dig @127.0.0.1 -p 5300 example.org A +comments 无应答或 SERVFAIL。实测案例:转发器 1.1.1.1:853(DoT)在该网络出口不可达,dig 无任何输出;换 223.5.5.5 + forwarderProtocol=Tls 后立即恢复 NOERROR(回显见《Technitium DNS Server 15.6.2 配置详解》5.1)。定位口诀:换协议(Tls→Udp)换上游(8.8.8.8/223.5.5.5)二分;
  3. 被拦截:RCODE: NxDomain 且 TXT 查询返回拦截报告(见 7.3);
  4. 递归 ACL:非私网客户端递归被拒(默认 AllowOnlyForPrivateNetworks),日志出现 RCODE: Refused。

7.3 域名"打不开"怀疑误杀

TXT 拦截报告直接给出命中的黑名单源(实测原文):

dig @127.0.0.1 -p 5300 doubleclick.net TXT +noall +answer
doubleclick.net.        30      IN      TXT     "source=block-list-zone; blockListUrl=https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts; domain=doubleclick.net"

处置:域名加 Allowed Zone(Zones → Allowed),或应急 temporaryDisableBlocking(4.3),或移除该黑名单源后 POST /api/settings/forceUpdateBlockLists。

7.4 端口占用(53 / 8443 类)

映射宿主端口被占的两种原始报错(实测原文):

53 被 systemd-resolved stub 占用(部署篇 4.4 节完整案例):

docker: Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint technitium-port-test (ee88da96deed7e7574eabf187c307d7ba438da2ec17dfed3a6245645e4c40b04): failed to bind host port 0.0.0.0:53/tcp: address already in use

8443 被其他服务占用:

Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint technitium-dns-15.6.2-server (10c65577b35e51faee4c319dfda2139afb7add912813106984ecce7732c57000): Bind for 0.0.0.0:8443 failed: port is already allocated

处置:ss -ltnp | grep <端口> 找占用者 → 换高位映射(本文 5300/9543)或停掉占用服务。专属 DNS 主机想用标准 53:/etc/systemd/resolved.conf 设 DNSStubListener=no 后 systemctl restart systemd-resolved。

7.5 DoT/DoH 端口通但握手失败

特征:宿主 ss -ltn 有 8530/9543 监听(docker-proxy),但 TLS 握手被重置。实测根因与修法见《Technitium DNS Server 15.6.2 配置详解》5.3:enableDnsOverTls/证书设置保存 ok 不等于监听生效,必须重启;重启后容器内 :0355(853)监听出现,dig +tls 与 openssl s_client 验证通过(Verify return code: 18 (self-signed certificate) 为自签预期告警)。

7.6 查询日志开关"看似生效却不落盘"

实测现象:settings/set logQueries=true 返回 ok、立即 get 回显 True,但 dig 后日志文件无 QNAME 行;且过早重启容器会丢失该设置(重启后回退 false——设置异步落盘被重启截断,实测踩坑)。正确操作序列:set → 等待数秒(确认 dns.config was saved 事件入日志)→ dig 验证 QNAME: 行出现。实测成功后的查询行格式:

[2026-10-19 05:28:52 UTC] [10.89.46.1:49152] [UDP] QNAME: www.baidu.com; QTYPE: A; QCLASS: IN; RCODE: NoError; ANSWER: [www.a.shifen.com., 110.242.69.21, 110.242.70.57]

7.7 黑名单下载失败

特征:blockListZones 计数为 0 或日志反复出现下载失败。源为 GitHub raw(国内不稳),处置:换国内可达镜像源 URL,或给服务器出网配代理(Settings → Proxy 或容器级代理),改完 forceUpdateBlockLists 强制刷新并核对日志计数行(7.4 节基线行 71492 domain(s) blocked)。

八、常见问题(FAQ)

Q1:Dashboard 统计和日志对不上? 统计窗口按小时文件滚动(LastHour/LastDay),重启瞬时丢当窗部分数据属正常;日志行是逐条落地的事实流,以日志为准做安全审计。

Q2:升级后 Dashboard 清零? 统计文件在 config/stats/ 按天留存,升级不清数据;LastHour 窗口跨重启会重置,看 LastDay 即可。

Q3:怎么确认拦截在"工作"? 三个实测信号任一:TXT 报告(7.3)、统计 totalBlocked 增长、日志 RCODE: NxDomain 行的 QNAME 命中黑名单域名。

Q4:第二节点怎么加? Settings → Clustering 初始化主节点 → 新机按部署篇部署(不导入备份)→ 加入集群;配置自动同步,zone 自动下发(Catalog Zones 机制)。

Q5:备份 zip 多久做一次? 配置变化后手动一次 + cron 每日自动;重大变更(加 zone、换证书)前后各一次。zip 仅 554 KB(实测),成本可忽略。

九、参考链接

  1. 官方在线帮助(Dashboard/Logs/Backup 章节):https://go.technitium.com/?id=25(查询日期 2026-10-19)
  2. HTTP API 文档(stats/backup/restore/logs 端点):https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md(查询日期 2026-10-19)
  3. 官方 docker-compose.yml(healthcheck 定义依据):https://github.com/TechnitiumSoftware/DnsServer/blob/master/docker-compose.yml(查询日期 2026-10-19)
  4. Clustering 功能说明(仓库 README):https://github.com/TechnitiumSoftware/DnsServer(查询日期 2026-10-19)
  5. 系列文档:《Technitium DNS Server 15.6.2 介绍与选型指南》《Technitium DNS Server Docker Compose 部署指南》《Technitium DNS Server 15.6.2 配置详解》