在 NSD 上部署 DNSSEC

本文为 DNS 完全解决方案三部曲之末 —— DNSSEC。

背景

DNS 在设计之初并未考虑保密性与完整性验证(正如 HTTP),在 HTTPS 得到广泛应用后,人们迫切地需要在 DNS 上同样部署类似的服务,于是 DNSSEC 应运而生。尽管 DNSSEC 不能加密 DNS,但可以验证 DNS 记录的完整性,保护其不受中间人篡改,因此可以避免 DNS 污染。在域名的权威服务器和用户查询所使用的递归服务器均启用 DNSSEC 的前提下,用户要么得到正确的 DNS 记录,要么得到 SERVFAIL 状态码,提示 DNS 记录可能被篡改了。

方法

以下各步骤均建立在上一篇文章所使用的 NSD 的基础上。

TL;DR

先安装依赖,以 Debian 为例。

1
apt install haveged ldnsutils

然后在任意目录下分别保存以下内容为三个文件,并授予执行权限。文件名分别取为 signre-signrevoke

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/usr/bin/bash
# This script is for signing.
# Usage: ./sign example.com
# First run this script, then add DS record in registrar.
DOMAIN=$1
cd /etc/nsd/zone
rm -rf K$DOMAIN.*
ZSK=$(ldns-keygen -a ECDSAP256SHA256 $DOMAIN)
KSK=$(ldns-keygen -a ECDSAP256SHA256 -k $DOMAIN)
rm $KSK.ds
ldns-signzone -n -s $(head -n 1000 /dev/random | sha1sum | cut -b 1-16) $DOMAIN $ZSK $KSK
sed -i "s/zonefile: $DOMAIN$/zonefile: $DOMAIN.signed/g" /etc/nsd/nsd.conf.d/ns.conf
systemctl restart nsd
ldns-key2ds -n $DOMAIN.signed
1
2
3
4
5
6
7
8
9
#!/usr/bin/bash
# This script is for re-signing.
# Usage: ./re-sign example.com
DOMAIN=$1
cd /etc/nsd/zone
KSK=$(basename $(grep -r "`grep '(ksk)' $DOMAIN.signed | cut -f3-10`" K$DOMAIN.*.key | cut -d':' -f1) .key)
ZSK=$(basename $(grep -r "`grep '(zsk)' $DOMAIN.signed | cut -f3-10`" K$DOMAIN.*.key | cut -d':' -f1) .key)
ldns-signzone -n -s $(head -n 1000 /dev/random | sha1sum | cut -b 1-16) $DOMAIN $ZSK $KSK
systemctl restart nsd
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/bash
# This script is for revoking sign.
# Usage: ./revoke example.com
# First delete DS record in registrar, then run this script.
DOMAIN=$1
cd /etc/nsd/zone
rm -rf K$DOMAIN.*
rm -rf $DOMAIN.signed
sed -i "s/zonefile: $DOMAIN.signed/zonefile: $DOMAIN/g" /etc/nsd/nsd.conf.d/ns.conf
systemctl restart nsd

详细说明

建议读者先掌握 DNSSEC 的基本理论知识,这里不作介绍,只讲述实践方法。

签名时,首先生成 ZSK 和 KSK 两对密钥,然后使用它们对域进行签名,ldns 会自动生成与原始 DNS 记录相对应的带有 DNSSEC 的 DNS 记录,文件名为 example.com.signed,因此需要重新配置 NSD。最后需要在域名提供商处添加 DS 记录(因为 DNSSEC 也采用 TLS 证书的信任链方式),将命令的输出直接(或者按各项参数分别)添加到域名提供商处即可。

修改了 DNS 记录后,由于完整性被破坏,需要重新签名,但这时无须重新生成密钥,因而也无须修改 DS 记录(否则也太麻烦了点),只须使用原有的 ZSK 和 KSK 两对密钥重新签名。

撤销签名时,首先须在域名提供商处删除相应 DS 记录,然后将 NSD 的相应 zonefile 修改为原本的 example.com。此外,还可以删除 example.com.signed 和那两对密钥等无用文件。

验证

可以使用 dig 命令验证,如下(以本站为例)。

1
dig ononoki.org +dnssec

但更推荐使用 DNSViz 验证。本站的 DNSSEC 状态如下图。 DNSSEC for ononoki.org