DNSSEC 是一组 DNS 安全扩展,用于验证 DNS 数据的真实性和完整性。本指南介绍如何在已有的 BIND9 DNS 服务器部署中,为现有区域启用 DNSSEC:通过为已签名区域提供 DS、DNSKEY、RRSIG 等附加记录来实现。
起点
本指南以已经部署了权威区域的 BIND9 DNS 服务器为基础。部署方法见 DNS 操作指南。不过有一个关键区别:区域文件必须位于服务器能够写入的目录,例如 /var/lib/bind,而不是 /etc/bind。
以下简要步骤使用示例域名 example.internal,将服务器配置到这一状态。首先安装 bind9:
sudo apt install bind9 -y
编辑 /etc/bind/named.conf.local,添加以下区域定义:
zone "example.internal" {
type master;
file "/var/lib/bind/db.example.internal";
};
创建 /var/lib/bind/db.example.internal,内容如下:
$TTL 86400 ; 1 day
example.internal. IN SOA example.internal. root.example.internal. (
1 ; serial
43200 ; refresh (12 hours)
900 ; retry (15 minutes)
1814400 ; expire (3 weeks)
7200 ; minimum (2 hours)
)
example.internal. IN NS ns.example.internal.
ns IN A 192.168.1.10
noble IN A 192.168.1.11
重新启动服务:
sudo systemctl restart named
检查服务能否解析 noble.example.internal:
dig @127.0.0.1 +short noble.example.internal
192.168.1.11
启用 DNSSEC
为区域启用 DNSSEC 涉及多个步骤。BIND9 默认会自动处理这些工作,需要手工完成的很少。转换区域至少需要生成新密钥,并为该区域的全部资源记录签名。但这只是第一天的工作:之后还必须正确维护区域,包括轮换密钥、设置过期时间等。当前版本的 BIND9 使用 DNSSEC 策略处理这些事务,并提供可以直接使用的默认策略。
要将 example.internal 迁移到 DNSSEC,只需在 /etc/bind/named.conf.local 中为区域定义添加两行:
zone "example.internal" {
type master;
file "/var/lib/bind/db.example.internal";
dnssec-policy default;
inline-signing yes;
};
新增设置的含义:
dnssec-policy default:使用默认 DNSSEC 策略。策略包含密钥轮换、默认 TTL 等多项设置。inline-signing yes:为已签名区域保留单独的文件。
修改后不需要重启服务,但需要通知服务重新加载配置,可以使用 rndc:
sudo rndc reconfig
服务器会立即发现新配置,开始为 example.internal 区域签名。日志会显示进度,可以这样查看:
sudo journalctl -u named.service -f
日志类似:
named[3246]: zone example.internal/IN (unsigned): loaded serial 1 named[3246]: zone example.internal/IN (signed): loaded serial 1 named[3246]: zone example.internal/IN (signed): receive_secure_serial: unchanged named[3246]: zone example.internal/IN (signed): sending notifies (serial 1) named[3246]: zone example.internal/IN (signed): reconfiguring zone keys named[3246]: keymgr: DNSKEY example.internal/ECDSAP256SHA256/44911 (CSK) created for policy default named[3246]: Fetching example.internal/ECDSAP256SHA256/44911 (CSK) from key repository. named[3246]: DNSKEY example.internal/ECDSAP256SHA256/44911 (CSK) is now published named[3246]: DNSKEY example.internal/ECDSAP256SHA256/44911 (CSK) is now active named[3246]: zone example.internal/IN (signed): next key event: 23-Oct-2024 22:47:12.544 named[3246]: any newly configured zones are now loaded named[3246]: running named[3246]: resolver priming query complete: success named[3246]: managed-keys-zone: Key 20326 for zone . is now trusted (acceptance timer complete) named[3246]: zone example.internal/IN (signed): sending notifies (serial 3)
区域越大,为所有记录签名所需的时间可能越长。
上述日志包含几项值得注意的事件:
- 为
example.internal生成密钥。 - 该区域已签名。
- 安排了下一次密钥事件,说明 BIND9 同时负责已签名区域及密钥的维护。
- 因为区域发生变化,序列号递增:从 1 变为 3。
DNSSEC 密钥保存在 /var/cache/bind:
-rw-r--r-- 1 bind bind 413 Oct 23 20:50 Kexample.internal.+013+48112.key -rw------- 1 bind bind 215 Oct 23 20:50 Kexample.internal.+013+48112.private -rw-r--r-- 1 bind bind 647 Oct 23 20:50 Kexample.internal.+013+48112.state
主要工作已经完成。该区域现已签名,BIND9 会按 default DNSSEC 策略自动维护它。
验证
刚签名的区域已经基本具备提供 DNSSEC 的条件,接下来进行验证。
当前 example.internal 与父区域尚未建立关联。虽然域名是指南虚构的,但即便它是真实域名,也仍然缺少到父区域的连接。DNSSEC 依靠信任链,父区域必须能够为子区域背书。
建立这条连接之前,先验证其他部分是否正常,尤其是执行 DNSSEC 查询并验证结果。delv 很适合这项工作:它类似 dig,但会使用与 BIND9 服务器相同的内部解析器和验证器逻辑验证查询结果。
由于区域尚未连接到父区域,需要告诉 delv 将该区域生成的公钥作为信任锚,并且不要尝试访问互联网根服务器。
首先把区域公钥复制到其他位置,以便编辑:
cp /var/cache/bind/Kexample.internal.+013+48112.key /tmp/example.key
文件顶部有注释,随后是一行以区域名开头的记录。下面为简洁起见截断了密钥:
example.internal. 3600 IN DNSKEY 257 3 13 jkmS5hfyY3nSww....
需要作以下修改:
- 删除顶部注释行。
- 把
3600 IN DNSKEY替换为static-key。 - 将数字
13后的密钥内容放入双引号中。 - 以分号结束这一行。
- 将这一行包在
trust-anchors块中。
最终 /tmp/example.key 应类似:
trust-anchors {
example.internal. static-key 257 3 13 "jkmS5hfyY3nSww....";
};
现在可以使用 delv 查询该区域并执行 DNSSEC 验证:
delv @127.0.0.1 -a /tmp/example.key +root=example.internal noble.example.internal +multiline
; fully validated
noble.example.internal. 86400 IN A 192.168.1.11
noble.example.internal. 86400 IN RRSIG A 13 3 86400 (
20241106131533 20241023195023 48112 example.internal.
5fL4apIwCD9kt4XbzzlLxMXY3mj8Li1WZu3qzlcBpERp
lXPgLODbRrWyp7L81xEFnfhecKtEYv+6Y0Xa5iVRug== )
输出体现了两项重要信息:
; fully validated:DNSSEC 验证已成功完成,返回的数据经过认证。RRSIG:随结果中的 A 记录一同返回的签名资源记录。
连接信任链:父区域
要完成信任链,父区域必须能够为刚签名的子区域背书。具体操作因父区域管理员而异,可能只需将 DS 或 DNSKEY 记录粘贴到表单中。
通常需要 DS 或 DNSKEY 记录中的一种。下面说明如何生成并提交这些记录。
DS 记录格式
可以使用 dnssec-dsfromkey 从区域公钥生成 DS 记录:
dnssec-dsfromkey /var/cache/bind/Kexample.internal.+013+48112.key
example.internal. IN DS 48112 13 2 1212DE7DA534556F1E11898F2C7A66736D5107962A19A0BFE1C2A67D6841962A
DNSKEY 记录格式
DNSKEY 不需要额外工具。它就在区域公钥文件中,位于以分号开头的注释行之后:
cat /var/cache/bind/Kexample.internal.+013+48112.key
; This is a key-signing key, keyid 48112, for example.internal. ; Created: 20241023205023 (Wed Oct 23 20:50:23 2024) ; Publish: 20241023205023 (Wed Oct 23 20:50:23 2024) ; Activate: 20241023205023 (Wed Oct 23 20:50:23 2024) ; SyncPublish: 20241024215523 (Thu Oct 24 21:55:23 2024) example.internal. 3600 IN DNSKEY 257 3 13 jkmS5hfyY3nSww4tD9Fy5d+GGc3A/zR1CFUxmN8T2TKTkgGWp8dusllM 7TrIZTEg6wZxmMs754/ftoTA6jmM1g==
取出这一行,略作格式调整,实际提交给父区域的记录应类似:
example.internal. 3600 IN DNSKEY 257 3 13 (jkmS5hfyY3nSww4tD9Fy5d+GGc3A/zR1CFUxmN8T2TKTkgGWp8dusllM 7TrIZTEg6wZxmMs754/ftoTA6jmM1g==);
延伸阅读
- BIND9 的 DNSSEC 指南。
- 权威区域签名快速入门指南。
- 创建自定义 DNSSEC 策略。
- BIND9 文档的详细 DNSSEC 章节。
delv(1)手册。- 与父区域协作。











暂无评论内容