Knot DNS 3.6.1 配置参数详解
Knot DNS 3.6.1 配置体系逐节详解:conf-check/conf-list/conf-* 事务、server/log/database/key/acl/remote/template/zone/policy 全参数表(含默认值与实测结论)、DoT/DoQ/DNSSEC/mod-stats 实测、生产配置模板与五类 FAQ,全部命令在 Ubuntu 22.04 实测并逐行照抄回显。
Knot DNS 3.6.1 配置参数详解
目标:逐节详解 Knot DNS 3.6.1 的配置体系(
/etc/knot/knot.conf),参数定义取自权威来源 knot.conf(5) 手册(随包分发,man knot.conf)与包默认配置/etc/knot/knot.conf,关键行为逐条在 Ubuntu 22.04.4 LTS + Knot DNS 3.6.1(CZ.NIC 官方仓库包)实测验证,命令输出逐行照抄。zone 搭建与安装流程见《Ubuntu 22.04 安装 Knot DNS 指南》,命令工具详解见《Knot DNS 3.6.1 常用 CLI 命令与工具详解》。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.4 LTS(jammy),x86_64,12 核 |
| 软件版本 | Knot DNS 3.6.1(knotd, Knot DNS 3.6.1,CZ.NIC 官方仓库 3.6.1-cznic.1~jammy) |
| 配置文件 | /etc/knot/knot.conf(文本,唯一事实源) |
| 配置数据库 | /var/lib/knot/confdb(LMDB 二进制库,knotd 实际读取) |
| 手册 | knot.conf(5)、knotc(8)、knotd(8)(随包分发) |
| 实验域 | lab.example(主域,zone 文件 /var/lib/knot/lab.example.zone,serial 2026102001) |
| 监听 | 127.0.0.9@53 与 ::1@53(本机 53 被 systemd-resolved 存根与其他 DNS 实例占用,详见部署篇) |
二、前置条件
sudo apt install -y knot knot-dnsutils
knotd -V
kdig @127.0.0.9 lab.example SOA +short
实测回显:
knotd, Knot DNS 3.6.1
ns1.lab.example. admin.lab.example. 2026102001 86400 7200 3600000 3600
💡 技术拓展:Knot 的配置链路是「文本 knot.conf → 校验(conf-check)→ 二进制 confdb → knotd 运行态」。knotd 启动只读 confdb;文本文件仅在 confdb 缺失时首次导入,运行期改动经
knotc reload或knotc conf-set热更新。理解这条链路是排查「改了配置不生效」的前提。
三、参数查看与修改方式
3.1 校验:conf-check(改配置前必做)
knotc conf-check
实测回显:
Configuration is valid
conf-check 校验默认路径 /etc/knot/knot.conf;校验候选文件用 -c 显式指定路径(实测踩坑:先改候选文件、后 conf-check,检查的还是旧文件——校验与部署必须同文件):
knotc -c /path/to/knot.conf.new conf-check
3.2 查看:conf-list / conf-read
knotc conf-list
knotc conf-read server.listen
实测回显(conf-list 全量 34 行,逐行照抄):
module
server
xdp
control
log
statistics
database
keystore
key
remote
remotes
acl
submission
dnskey-sync
policy
external
template
zone
include
clear
mod-alias
mod-authsignal
mod-cookies
mod-dnserr
mod-dnsproxy
mod-ecs
mod-noudp
mod-onlinesign
mod-probe
mod-queryacl
mod-rrl
mod-stats
mod-synthrecord
mod-whoami
实测回显(conf-read,注意多值参数每行一个值、节与键以空格分隔):
server.listen 127.0.0.9@53
::1@53
conf-list 列出配置 schema 的全部顶层节(前 20 行)与本包编译集内的全部查询模块(后 14 行 mod-*)——它能当「本包支持哪些模块」的清单用:本环境 deb 包编译进了 mod-alias/mod-authsignal/mod-cookies/mod-dnserr/mod-dnsproxy/mod-ecs/mod-noudp/mod-onlinesign/mod-probe/mod-queryacl/mod-rrl/mod-stats/mod-synthrecord/mod-whoami 共 14 个,而 mod-dnstap/mod-geoip 未编译(配置它们会在 conf-check 报错)。conf-read 可按 section[.id][.item] 粒度查询。
3.3 修改:文本编辑 + reload,或控制通道 conf-set
两种途径(等效):
# 途径一:编辑文本 → 校验 → 热加载(listen 变更除外,见 FAQ-2)
sudo vim /etc/knot/knot.conf
knotc conf-check && knotc reload
# 途径二:控制通道事务式修改,写回 confdb 并即时生效(不改动文本文件)
knotc conf-begin
knotc conf-set 'server.identity' "dns-node-ops"
knotc conf-commit
knotc conf-read server.identity
实测回显(途径二,conf-begin/conf-set/conf-commit 各回一行 OK;conf-read 输出为空格分隔格式):
OK
OK
OK
server.identity dns-node-ops
CHAOS 类查询验证 identity 生效。按 RFC 4892(knot.conf(5) 手册 identity 条目),identity 的正确查询名是 id.server. 或 hostname.bind.(不是 identity.bind,实测查 identity.bind 返回空),version 的正确查询名是 version.server. 或 version.bind.:
kdig @127.0.0.9 -c CH -t TXT id.server +short
kdig @127.0.0.9 -c CH -t TXT version.bind +short
"dns-node-ops"
"Knot DNS 3.6.1"
默认行为实测(identity 未设置时,id.server 应答为 FQDN 主机名——本实验机主机名即 ops;设为空值则关闭应答):
kdig @127.0.0.9 -c CH -t TXT id.server +short # unset 后重查
"ops"
删除参数必须同样走事务(事务外执行 conf-unset 直接报错,实测回显 error: (no active transaction) server.identity),完整还原链条:
knotc conf-begin
knotc conf-unset 'server.identity'
knotc conf-commit
OK
OK
OK
💡 技术拓展与排障实录:conf-* 事务开启后若中途出错未提交,事务会保持打开,此时再
conf-begin会报error: (too many transactions)(实测复现);恢复路径是继续在该事务里操作后conf-commit,或conf-abort丢弃(实测 begin→abort 链回显 OK OK)。公网服务器建议把 identity 设为无业务含义字符串,并用 mod-queryacl 限制 CHAOS 查询,降低指纹泄露(identity 与 version 的默认值都会暴露主机名/精确版本号)。
四、参数体系总览
knot.conf 的节(SECTION)与隶属关系(取自 knot.conf(5) 手册目录,与 3.2 节 conf-list 实测一致):
| 节 | 职责 | 关键子项 |
|---|---|---|
| server | 服务进程与监听 | listen、user、workers、identity、key-file/cert-file |
| control | 控制套接字 | listen(Unix socket 路径)、timeout |
| log | 日志 | target、any/server/zone/control 级别 |
| statistics | 统计导出 | timer、file、append |
| database | 数据目录 | storage、journal-db、kasp-db、timer-db |
| keystore | DNSSEC 密钥库 | id、backend(pem/pkcs11) |
| key | TSIG 密钥 | id、algorithm、secret |
| remote / remotes | 远端对端 | address、via、tsig |
| acl | 访问控制 | id、action、address、key、deny |
| submission | KSK 提交检查 | parent(s)、check-interval |
| dnskey-sync | DNSKEY 同步 | parent(s) |
| policy | DNSSEC 签名策略 | id、algorithm、rrsig-lifetime、nsec3 等 |
| template | zone 模板 | id、storage、file、acl、notify、dnssec-signing 等 |
| zone | zone 定义 | domain、继承 template 全部键 |
| xdp | XDP 高性能面 | interface、mode |
| mod-* | 查询模块 | 见部署篇 6.2 节模块清单 |
配置继承:zone 未显式给出的键按 template 填充,template 未给出的按内置默认值;template: default 名字的模板自动应用到所有未指定 template 的 zone。
五、核心参数详解
5.1 server 节
| 参数 | 说明 | 默认值(knot.conf(5)) | 实测 |
|---|---|---|---|
| listen | 监听地址,格式 ADDR[%接口][@端口],可多个 | 无(不配则不开 DNS 端口,日志报 no network interface configured) | 绑 127.0.0.9@53 后 ss 核验 UDP×12 + TCP 各一套 |
| listen-tls | DoT 监听地址 | 无 | 8853 端口开监听,kdig +tls 查询成功(见下) |
| listen-quic | DoQ 监听地址 | 无 | conf-check 通过但本环境未绑定(见 FAQ-4) |
| user | 降权目标 user:group | knot:knot | 配置固定 user: knot:knot |
| rundir | 运行目录(pid/控制套接字/统计文件) | /run/knot | ls 实见 knot.pid、knot.sock、stats.yaml |
| udp-workers / tcp-workers | 查询处理线程数 | 自动(等于 CPU 核数) | knotc status workers 报 UDP 12 / TCP 12(12 核) |
| background-workers | 后台线程数(zone 加载/签名/传输) | 自动 | 同上:background workers: 10 |
| automatic-acl | 自动生成 ACL(包默认样例已开启) | off | 包默认配置原文在 server 节内 automatic-acl: on |
| identity | CHAOS 类 id.server./hostname.bind. 查询的 TXT 应答(RFC 4892) | FQDN 主机名(实测本机回 "ops");设空值关闭 | 实测设置后返回设置值(3.3 节) |
| version | CHAOS 类 version.server./version.bind. 查询的 TXT 应答 | 真实版本号 | 实测返回 "Knot DNS 3.6.1" |
| key-file / cert-file | DoT/DoQ 服务端证书 | key 自动生成;cert 为一次性内存证书 | 不配证书即可 kdig +tls 通(见下) |
| max-tcp-clients / tcp-handshake-timeout 等 | TCP 容量与超时 | 见手册 | 未实测调优 |
DoT 最小实测(无需证书配置,自动生成临时证书):listen-tls: [ 127.0.0.9@8853 ] 重启后:
ss -ltn | grep 8853
kdig @127.0.0.9 -p 8853 +tls lab.example SOA +short
journalctl -u knot --no-pager --output=cat | grep TLS | tail -2
LISTEN 0 10 127.0.0.9:8853 0.0.0.0:*
ns1.lab.example. admin.lab.example. 2026102001 86400 7200 3600000 3600
info: binding to TLS interface 127.0.0.9@8853
info: QUIC/TLS, certificate public key afzjjTQBGubwRZYV2SZRiS2d7U0v9kvuTawMArAgdto=
5.2 log 节
log:
- target: syslog
any: info
target 支持 stdout/stderr/syslog/journal/null/文件路径;级别键 any/server/zone/control 按面分级。生产建议:syslog + any: info(与包默认一致),排障期临时 any: debug。实测:本文所有排障实录(绑定失败、zone 解析错误、confdb 权限)均由该配置落 journal 后 journalctl -u knot 采集。
5.3 database 节
| 参数 | 说明 | 默认值 | 实测 |
|---|---|---|---|
| storage | 各数据库的基准目录 | /var/lib/knot | 目录实存 journal/kasp/timers/confdb |
| journal-db / kasp-db / timer-db | journal/密钥/定时器库路径 | storage 下同名 | purge 后删库即丢 DDNS 历史与密钥(部署篇 9.2 节降级实测佐证) |
| confdb | 配置库 | storage/confdb | FAQ-1 的 confdb 陷阱主角 |
5.4 key 与 acl 节(TSIG 与访问控制)
key:
- id: ddns-key
algorithm: hmac-sha256
secret: whbCR6X0Rvfq2rvlV1diJ6Du4QczkAbTqzV8Sq/1mns=
acl:
- id: transfer_acl
address: 127.0.0.1
action: transfer
- id: ddns_acl
key: ddns-key
action: update
- key.algorithm 支持 hmac-md5/sha1/sha224/sha256/sha384/sha512,secret 用
keymgr -t <名字> <算法>生成(格式见命令篇); - acl.action 取值
transfer|notify|update|query,address 支持 CIDR,key 关联 TSIG;多条 acl 按「先匹配先生效」,配deny: on显式拒绝; - zone 侧
acl: [ transfer_acl, ddns_acl ]挂载。
实测(ACL 行为双向验证):
kdig @127.0.0.9 lab.example -t AXFR # 源 127.0.0.1 命中 transfer_acl → 放行
kdig @::1 lab.example -t AXFR # 源 ::1 未命中 → 拒绝
实测回显(放行侧,完整 12 行):
;; AXFR for lab.example.
lab.example. 3600 IN SOA ns1.lab.example. admin.lab.example. 2026102001 86400 7200 3600000 3600
lab.example. 3600 IN NS ns1.lab.example.
lab.example. 3600 IN MX 10 mail.lab.example.
api.lab.example. 3600 IN A 192.168.1.101
mail.lab.example. 3600 IN A 192.168.1.110
ns1.lab.example. 3600 IN A 127.0.0.1
txt.lab.example. 3600 IN TXT "knot dns lab"
www.lab.example. 3600 IN A 192.168.1.100
lab.example. 3600 IN SOA ns1.lab.example. admin.lab.example. 2026102001 86400 7200 3600000 3600
;; Received 281 B (1 messages, 9 records)
;; Time 2026-10-20 17:33:41 CST
;; From 127.0.0.9@53(TCP) in 0.4 ms
实测回显(拒绝侧,完整 6 行):
;; ERROR: server replied with error 'NOTAUTH'
;; ERROR: failed to query server ::1@53(TCP)
;; AXFR for lab.example.
;; Received 0 B
;; Time 2026-10-20 17:33:41 CST
;; From ::1@53(TCP) in 0.2 ms
注意未授权 AXFR 的应答码是 NOTAUTH 而非 REFUSED——Knot 对未授权转移刻意伪装成「非权威」,不暴露 zone 存在性。带 TSIG 的 DDNS 同理:无密钥 update 被拒(NOTAUTH),带密钥成功(serial 自动 +1,实测 2026102001 → 2026102002)。
5.5 remote / remotes 节
remote:
- id: secondary
address: 192.0.2.10@53
remotes:
- id: secondary-group
remote: secondary
zone 的 notify: secondary 引用 remote id,master: <remote-group> 用于辅域;remote 级可配 tsig/protocol: tls|quic(对上级的加密传输)。本实验配置了 notify: secondary 指向不存在的 127.0.0.10@53,日志出现 notify failed (connection reset) 告警——验证了 notify 目标不可达时的表现,移除该引用即消除。
5.6 template 与 zone 节
| 参数 | 说明 | 默认值 | 实测 |
|---|---|---|---|
| file | zone 文件名,%s 为域名占位符 | 无 | file: "%s.zone" → /var/lib/knot/lab.example.zone |
| storage | 该 zone 文件与 journal 位置 | database.storage | — |
| acl | 挂载 ACL | 无 | 5.4 节实测 |
| notify | 出站 NOTIFY 目标 | 无 | 5.5 节实测 |
| master | 辅域上游 | 无 | — |
| zonefile-load | zone 文件加载语义 | difference-no-serial | 文件旧 serial + journal 差异回放(部署篇 FAQ-5 佐证) |
| journal-content | journal 持久化范围 | all | DDNS 后 zone-flush 实测回写文件 |
| dnssec-signing | 自动签名开关 | off | 开启后自动生成 ZSK 25397 + KSK 48798(ECDSAP256SHA256),18 条新 RRSIG 入网,serial 自动 bump |
| dnssec-policy | 引用 policy 节 | default | 默认策略即单 CSK/双密钥自动滚动 |
| catalog-role / catalog-member | 目录域角色 | 无 | catalog zone(RFC 9432)管理入口 |
| zonefile-sync | journal 回写 zone 文件周期 | 0(flush 时写) | zone-flush 立即生效 |
DNSSEC 开启实测(zone 加 dnssec-signing: on 后 reload):
knotc reload
journalctl -u knot --no-pager --output=cat | grep -E 'DNSSEC' | tail -4
kdig @127.0.0.9 lab.example DNSKEY +short | awk '{print $1, $3}'
kdig @127.0.0.9 lab.example SOA +dnssec +short
实测回显(签名日志,Knot 落 journal 的 DNSSEC 事件自带时间戳前缀):
2026-10-20T17:34:21.319+08:00 info: [lab.example.] DNSSEC, key, tag 25397, algorithm ECDSAP256SHA256, public, active
2026-10-20T17:34:21.319+08:00 info: [lab.example.] DNSSEC, signing started
2026-10-20T17:34:21.319+08:00 info: [lab.example.] DNSSEC, successfully signed, serial 2026102002, new RRSIGs 18
2026-10-20T17:34:21.320+08:00 info: [lab.example.] DNSSEC, next signing at 2026-11-02T05:58:21+0800
实测回显(DNSKEY,$3 为算法号 13=ECDSAP256SHA256;SOA serial 已自动 bump 至 2026102002 且携带 RRSIG):
256 13
257 13
ns1.lab.example. admin.lab.example. 2026102002 86400 7200 3600000 3600
SOA 13 2 3600 20261103093421 20261020080421 25397 lab.example. mS8xxDe2L3wffDQkCeL4do6pRTRGpaDQxHtcTn1d9cZEtKqUFTFMyw38HizfKKjYUB0dBc4Q2XWqb1Lw7UJzMg==
DNSKEY 256(ZSK 25397)/257(KSK 48798)与
keymgr lab.example list输出一致(命令篇 6.5 节);RRSIG 为 ECDSA 算法 13,签名者 ZSK 25397。
5.7 policy / submission / keystore 节(DNSSEC 策略三件套)
policy 声明签名策略(algorithm、rrsig-lifetime、refresh、nsec3、cdnskey 等),submission 声明 DS/CDS 父域检查点(KSK 就绪后等待 parent DS 确认才完成滚动),keystore 声明私钥库(默认 pem,/var/lib/knot/keys)。默认策略即可运行(5.6 节实测未配任何 policy 节,签名全自动)。
KSK 状态机实测(两处真实证据):① 签名日志出现 notice: [lab.example.] DNSSEC, KSK submission, waiting for confirmation;② keymgr lab.example list 中 KSK 行停在 ready=1792488861 而无 active=(ZSK 行则是 active=1792488861)——即 KSK 已就绪并随 zone 发布,但正等待 submission 节登记的父域完成 DS 上链确认后才进入 active。
5.8 mod-stats 与 statistics 节(可观测)
mod-stats:
- id: default
request-protocol: on
server-operation: on
request-bytes: on
response-bytes: on
response-code: on
statistics:
timer: 60
file: "/run/knot/stats.yaml"
template:
- id: default
global-module: mod-stats/default
实测要点:
- 合法开关逐参数验证(conf-check):
request-protocol、server-operation、request-bytes、response-bytes、response-code有效;request-server-operation、zone-size、zone-packetsize不是 3.6.1 的合法参数(conf-check 报invalid item,见 FAQ-3); - 运行态读取:
knotc stats
knotc zone-stats lab.example
实测回显(reload 重置计数器后 2 次 SOA 查询读取,逐行照抄;server.zone-count 在首行):
server.zone-count: 1
mod-stats.request-protocol[udp4]: 2
mod-stats.server-operation[query]: 2
mod-stats.request-bytes[query]: 80
mod-stats.response-bytes[reply]: 172
mod-stats.response-code[NOERROR]: 2
实测回显(zone-stats 输出无 zone 名前缀):
zone.size: 3015
zone.max-ttl: 3600
- 周期导出实测(statistics.timer: 60,每 60 秒落一份 YAML):
---
time: 2026-10-20T17:21:56+0800
identity: ops
server:
zone-count: 1
mod-stats:
request-protocol:
udp4: 1
server-operation:
query: 1
request-bytes:
query: 40
response-bytes:
reply: 86
response-code:
NOERROR: 1
💡 技术拓展:该 YAML 是 Prometheus 抓取以外的低成本观测面(file 可被脚本/采集器 tail);社区另有 knot-exporter(PyPI)直接对接 Prometheus。
六、生产配置模板
以下为可直接落地的公网权威生产基线(多监听 + 限速 + 主从 ACL + DDNS + DNSSEC + 观测),本文环境逐段验证过语法与行为:
server:
rundir: "/run/knot"
user: knot:knot
listen: [ 0.0.0.0@53, ::@53 ] # 干净机器;多 DNS 服务共存时改绑具体地址
identity: "ns1"
automatic-acl: on
control:
listen: "/run/knot/knot.sock"
log:
- target: syslog
any: info
database:
storage: "/var/lib/knot"
key:
- id: op-team-key
algorithm: hmac-sha256
secret: <keymgr -t op-team-key hmac-sha256 生成>
acl:
- id: transfer_acl
address: [10.0.0.0/24] # 辅域地址段
action: transfer
- id: ddns_acl
key: op-team-key
action: update
- id: query_acl
address: [0.0.0.0/0]
action: query
remote:
- id: secondary1
address: 10.0.0.2@53
mod-rrl:
- id: default
rate-limit: 200 # 每秒每源限速
slip: 2
mod-stats:
- id: default
request-protocol: on
server-operation: on
response-code: on
statistics:
timer: 60
file: "/run/knot/stats.yaml"
template:
- id: default
storage: "/var/lib/knot"
file: "%s.zone"
acl: [ transfer_acl, ddns_acl, query_acl ]
notify: secondary1
zonefile-sync: 300 # 5 分钟回写一次 zone 文件
global-module: [ mod-rrl/default, mod-stats/default ]
zone:
- domain: example.com
dnssec-signing: on
参数取舍说明:
rate-limit: 200为经验起点(按业务 QPS 峰值调);zonefile-sync: 300平衡 journal 性能与文件一致性;公网面建议追加mod-queryacl收敛 CHAOS/特殊查询,需要任何说明合法的 ECS 精细控制时加mod-ecs。
七、常见问题(FAQ)
FAQ-1:改了 knot.conf 重启后没生效——confdb 优先
knotd 启动读 confdb 不读文本文件(见二节拓展)。彻底脱节时删库重建:
sudo systemctl stop knot
sudo rm -rf /var/lib/knot/confdb
sudo systemctl start knot
附实测教训:以 root 身份误跑 knotc conf-init 会把 confdb 重建为 root 属主,服务以 knot 用户读库即失败(failed to open configuration database '/var/lib/knot/confdb' (operation not permitted))——处置同上(删 confdb 重建)。
FAQ-2:knotc reload 对 listen 变更不生效
实测:向 listen 追加 127.0.0.15@53 后 reload,ss 核验未绑定新地址。监听地址/端口变更必须 systemctl restart knot(knotd 的套接字在进程启动期创建)。zone、acl、模块、日志等参数 reload 即时生效。
FAQ-3:conf-check 报 invalid item——参数名逐项核对
参数名拼写错误或使用了不存在/已废弃的键。实测样例(mod-stats 下 zone-size 非法):
error: config, file '/etc/knot/knot.conf', line 31, item 'zone-size', value 'on' (invalid item)
error: failed to load configuration file '/etc/knot/knot.conf' (invalid item)
处置:对照 knot.conf(5) 修正参数名(如 mod-stats 的合法集为 request-protocol/server-operation/request-bytes/response-bytes/response-code,实测逐项验证)。conf-check 一次只报一个错,修一个再跑一次直到 Configuration is valid。
FAQ-4:listen-quic 配了但不生效(DoQ 不可用)
实测(Ubuntu 22.04 + CZ.NIC deb 包):conf-check 通过、服务正常启动,但 8854 端口无 QUIC 套接字、日志无 "binding to QUIC interface" 行(同配置的 listen-tls 有对应日志且 kdig +tls 通)。表现为静默跳过,推测与本环境 gnutls 版本(jammy 为 3.7.3,QUIC 需更新 gnutls/内核支持)有关。在本环境请以 DoT(listen-tls,实测可用)作为加密传输方案,DoQ 需更新系统库后另行验证。
FAQ-5:zone 加载失败但控制通道回 OK
knotc zone-reload 异步执行,坏 zone 文件时回显 OK、错误在日志(阻塞模式 knotc -b 才同步回错误)。实录见部署篇 FAQ-5(zone loader, error in zone ... (invalid IPv4 address) 完整错误链)。
八、参考链接
- knot.conf(5) 手册(随包分发):
man knot.conf;参数定义均以此为准 - knotc(8)(控制命令与 conf-* 事务):
man knotc - 官方配置文档:https://knot-dns.gitlab.io/knot-dns/html/configuration.html
- 本系列:《Knot DNS 3.6.1 介绍与选型指南》《Ubuntu 22.04 安装 Knot DNS 指南》《Knot DNS 3.6.1 常用 CLI 命令与工具详解》
- 站内同类:《BIND9 9.18.39 配置参数详解》(https://www.quzuo.net/document/59a7KtZwA9hf)