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 DNSKnotDNS2026/10/20

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
keystoreDNSSEC 密钥库id、backend(pem/pkcs11)
keyTSIG 密钥id、algorithm、secret
remote / remotes远端对端address、via、tsig
acl访问控制id、action、address、key、deny
submissionKSK 提交检查parent(s)、check-interval
dnskey-syncDNSKEY 同步parent(s)
policyDNSSEC 签名策略id、algorithm、rrsig-lifetime、nsec3 等
templatezone 模板id、storage、file、acl、notify、dnssec-signing 等
zonezone 定义domain、继承 template 全部键
xdpXDP 高性能面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-tlsDoT 监听地址无8853 端口开监听,kdig +tls 查询成功(见下)
listen-quicDoQ 监听地址无conf-check 通过但本环境未绑定(见 FAQ-4)
user降权目标 user:groupknot:knot配置固定 user: knot:knot
rundir运行目录(pid/控制套接字/统计文件)/run/knotls 实见 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
identityCHAOS 类 id.server./hostname.bind. 查询的 TXT 应答(RFC 4892)FQDN 主机名(实测本机回 "ops");设空值关闭实测设置后返回设置值(3.3 节)
versionCHAOS 类 version.server./version.bind. 查询的 TXT 应答真实版本号实测返回 "Knot DNS 3.6.1"
key-file / cert-fileDoT/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-dbjournal/密钥/定时器库路径storage 下同名purge 后删库即丢 DDNS 历史与密钥(部署篇 9.2 节降级实测佐证)
confdb配置库storage/confdbFAQ-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 节

参数说明默认值实测
filezone 文件名,%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-loadzone 文件加载语义difference-no-serial文件旧 serial + journal 差异回放(部署篇 FAQ-5 佐证)
journal-contentjournal 持久化范围allDDNS 后 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-syncjournal 回写 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) 完整错误链)。

八、参考链接