在 DN42 中注册域名并开启 DNSSEC

请注意:

阅读本文前,我已假设你了解、已加入 DN42 网络,并且能正常收发 BGP 表。

如果你没有听说过 DN42,不妨先去阅读一下蓝天师祖的这篇文章

不过,文章的前半部分由于不涉及到 DN42,理论上应该是通用的,但是我不对此做出保证。

0x00 起因

首先当然是在配置完成 DN42 后,在蓝天的博客看到了在 DN42 中注册自己的域名的文章,于是也想动手试试。

然后我发现,蓝天的部署方式对我来说似乎过于复杂了。

Linux 下自建 DNS 一般使用 Bind 或 PowerDNS 两款软件。Bind 以文件形式保存 DNS 记录,跨服务器同步有些麻烦,而 PowerDNS 不仅可以用文件保存,还可以用 MySQL 等数据库形式保存,同时自己也提供记录同步功能。

由于我配置 PowerDNS 自带的记录同步功能总是失败,查不出原因,我就干脆设置了 MySQL 主从复制来进行同步。

对于蓝天来说,使用 PowerDNS 并配置同步是合理的。但是,我只有一台服务器,何必为难自己呢?果断选择 Bind。其实是因为我部署了 PowerDNS,但是不知道为什么它的 53 端口一直开放不出来,被迫放弃。

0x01 准备工作

首先,当然是已经注册好 DN42。尝试 ping 172.20.0.53 ,如果能通,就说明问题不大。

其次,我是用的是 Ubuntu 22.04,我安装的 Bind9 版本为 9.18.5,因此下文也都基于此。

再次,由于测试需要,我是用 apt install ldnsutils 安装了一些额外工具。

最后,下文所有操作均在 root 用户下完成,如果你不使用 root 用户,请按需添加 sudo

特别注意

在接下来的步骤中,我将注册 potat0.dn42 域名,同时配置 0/26.246.23.172.in-addr.arpa2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa 反向 DNS。

请牢记:这些都是我的域名和 IP,请务必更改成你的!

0x02 从安装 Bind9 开始

首先,在多数 Linux 发行版中,53 端口一般都已经被系统的某些进程占用,Ubuntu 也不例外。使用下面的语句释放 53 端口:

systemctl stop systemd-resolved
systemctl disable systemd-resolved
unlink /etc/resolv.conf
echo "nameserver 8.8.8.8" > /etc/resolv.conf

可以使用 lsof -i:53 确认端口已无占用。

现在可以安装 Bind9 了:

add-apt-repository ppa:isc/bind
apt update
apt install bind9
systemctl enable named

至此,Bind9 已经顺利安装并且会在开机时自动启动。

在后续配置的过程中,如果需要重启 Bind 以使配置立即生效,可以使用以下命令:

service named reload

0x03 基础配置

Bind9 的配置文件在 /etc/bind/named.conf ,可以看到它事实上引入了 named.conf.optionsnamed.conf.localnamed.conf.default-zones 。我们也按照这个结构进行配置。

以下配置会将 Bind 同时配置成权威 DNS 服务器递归 DNS 服务器

named.conf.options

首先是 named.conf.options ,这是 Bind 的相关选项。对于我们的需求,配置如下:

点此查看 named.conf.options
options {
    // Disable the integrated handling of RFC1918 and non-assigned IPv6 space reverse dns
    empty-zones-enable no;

    // Working directory
    directory "/var/cache/bind";

    // Allow access to cache
    allow-query-cache { any; };

    // Provide recursive service
    recursion yes;
    allow-recursion { any; };
    listen-on { any; };
    listen-on-v6 { any; };

    // Config for forwarding
    forward first;
    forwarders {
        8.8.8.8;
        8.8.4.4;
    };

    // Need to disable DNSSEC validation for some dn42 related TLDs,
    // since they are not valid TLDs and not be signed by root DNS server.
    // See: https://dn42.dev/services/dns/Configuration#forwarder-setup_bind
    validate-except {
        "dn42";
        "20.172.in-addr.arpa";
        "21.172.in-addr.arpa";
        "22.172.in-addr.arpa";
        "23.172.in-addr.arpa";
        "10.in-addr.arpa";
        "d.f.ip6.arpa";
    };
};

named.conf.default-zones

然后是 named.conf.default-zones ,这里是一些转发的相关配置,用来告诉 Bind,DN42 的域名应该去那里解析。这些配置是参照 DN42 Wiki 完成的:

点此查看 named.conf.default-zones
zone "dn42" {
    type forward;
    forwarders {
        172.23.0.53;
        172.20.0.53;
        fd42:d42:d42:54::1;
        fd42:d42:d42:53::1;
    };
};

zone "20.172.in-addr.arpa" {
    type forward;
    forwarders {
        172.23.0.53;
        172.20.0.53;
        fd42:d42:d42:54::1;
        fd42:d42:d42:53::1;
    };
    forward only;
};

zone "21.172.in-addr.arpa" {
    type forward;
    forwarders {
        172.23.0.53;
        172.20.0.53;
        fd42:d42:d42:54::1;
        fd42:d42:d42:53::1;
    };
    forward only;
};

zone "22.172.in-addr.arpa" {
    type forward;
    forwarders {
        172.23.0.53;
        172.20.0.53;
        fd42:d42:d42:54::1;
        fd42:d42:d42:53::1;
    };
    forward only;
};

zone "23.172.in-addr.arpa" {
    type forward;
    forwarders {
        172.23.0.53;
        172.20.0.53;
        fd42:d42:d42:54::1;
        fd42:d42:d42:53::1;
    };
    forward only;
};

zone "10.in-addr.arpa" {
    type forward;
    forwarders {
        172.23.0.53;
        172.20.0.53;
        fd42:d42:d42:54::1;
        fd42:d42:d42:53::1;
    };
    forward only;
};

zone "d.f.ip6.arpa" {
    type forward;
    forwarders {
        172.23.0.53;
        172.20.0.53;
        fd42:d42:d42:54::1;
        fd42:d42:d42:53::1;
    };
    forward only;
};

这里有一个小技巧。可以提前 ping 一下 DN42 DNS AnyCast 在你服务器上的延迟( 172.20.0.53172.23.0.53fd42:d42:d42:54::1fd42:d42:d42:53::1 ),找出你这边延迟更低的服务器,替换上面配置中对应的。

named.conf.local

最后是 named.conf.local ,这里填写的是 Bind 作为权威 DNS 服务器说服务的 Zone。这是到目前位置第一次需要按需填写的地方。

点此查看 named.conf.local
// An authoritative name server for potat0.dn42
zone "potat0.dn42" {
    type primary;
    file "/etc/bind/zones/potat0.dn42.zone";
    // Disable transfer to other servers. IP addresses of secondary servers allowed to transfer this domain
    allow-transfer { none; };
    // Disable ddns update
    allow-update { none; };
};

// IPv4 reverse resolution
zone "0/26.246.23.172.in-addr.arpa" {
    type primary;
    file "/etc/bind/zones/0%2F26.246.23.172.in-addr.arpa.zone";
    allow-transfer { none; };
    allow-update { none; };
};

// IPv6 reverse resolution
zone "2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa" {
    type primary;
    file "/etc/bind/zones/2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa.zone";
    allow-transfer { none; };
    allow-update { none; };
};

对于 3 个 Zone,你需要更改 zone 的名称和对应的 file 路径。具体名称将会在后面的小节讲述。

0x04 Zone 配置

整洁起见,我选择创建了 /etc/bind/zones 目录来存放 Zone 的相关配置。(因为等开启 DNSSEC 之后确实会多出来不少文件)

主域名

首先当然是从最简单的开始:配置主域名。我将文件存放在了 /etc/bind/zones/potat0.dn42.zone

点此查看主域名的Zone文件
; potat0.dn42.
$TTL  300 ; default ttl for all RRs
@ IN  SOA ns1.potat0.dn42. dn42.potat0.cc. ( ; ns1.potat0.dn42 is the domain of dns server
         2022072401     ; Serial Number, should be change any time when modify happens
               3600     ; Refresh
                180     ; Retry
              86400     ; Expire
                300 )   ; Negative Cache TTL
;
                        IN  NS    ns1.potat0.dn42.  ; announce the name server of current zone(domain) to be ns1.potat0.dn42.
ns1                     IN  A     172.23.246.1
ns1                     IN  AAAA  fd2c:1323:4042::1
@                       IN  A     172.23.246.1
@                       IN  AAAA  fd2c:1323:4042::1

以分行引导的是注释语句,无需理会。

首先我们定义了 SOA 记录。该记录指示了该 Zone 的基本信息,你可以阅读这篇文章了解更多。其中,

  • ns1.potat0.dn42. (MNAME),是我们的主 NS 服务器。

  • dn42.potat0.cc. (RNAME),是管理员邮箱,将其中的 @ 改为 . 的结果。

  • 下方的 Serial Number (即 2022072401 )是非常重要的,它表示 Zone 文件的版本号。其他 DNS 服务器在获取 SOA 后发现序列号增加了就会重新拉取新的记录。

    因此,请务必记得每次修改 Zone 文件时也修改序列号!

    序列号是一个 10 位的数字,这里依照 RFC 1912 的建议,使用日期 + 编号的方式编码,你也可以用其他的方式。

接下来的是 NS 服务器,指向服务该 Zone 的权威 DNS 服务器即可(也就是现在正在配置的这台)。

然后就是普通的记录了。没什么特别的,按照格式写就行, @ 表示顶级域名(即 potat0.dn42 本身,而不带任何二级域名)。别忘了加上 ns 域名的记录。

提醒:

在写 SOA 记录时,你可能会觉得 MNAME 和 RNAME 末尾的 . 有些奇怪,但这是必须的。缺少末尾点会导致报错。

所以请不要忘记加上他们。

写完以后记得修改之前的 named.conf.local ,之后的 2 个 Zone 也一样。

IPv4 反向 DNS

DN42 的 IPv4 反向 DNS 遵循 RFC 2317。我的 DN42 IPv4 段是 172.23.246.0/26 ,因此我的 IPv4 反向 DNS 的 Zone 应该为 0/26.246.23.172.in-addr.arpa (即,将 IPv4 段最后一节的 0/26 视作一个整体,再倒序)。

在作文件名时, / 应该使用 %2F 代替。

点此查看IPv4 反向 DNS的Zone文件
; 0/26.246.23.172.in-addr.arpa.
$TTL  300 ; default ttl for all RRs
@ IN  SOA ns1.potat0.dn42. dn42.potat0.cc. ( ; ns1.potat0.dn42 is the domain of dns server
         2022072502     ; Serial Number, should be change any time when modify happens
               3600     ; Refresh
                180     ; Retry
              86400     ; Expire
                300 )   ; Negative Cache TTL
;
                        IN  NS    ns1.potat0.dn42.  ; announce the name server of current zone(domain) to be ns1.potat0.dn42.
1                       IN  PTR   potat0.dn42.

IPv6 反向 DNS

DN42 的 IPv6 反向 DNS 遵循 RFC 3152。我的 DN42 IPv6 段是 fd2c:1323:4042::/48 ,因此我的 IPv6 反向 DNS 的 Zone 应该为 2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa

点此查看IPv6 反向 DNS的Zone文件
; 2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa.
$TTL  300 ; default ttl for all RRs
@ IN  SOA ns1.potat0.dn42. dn42.potat0.cc. ( ; ns1.potat0.dn42 is the domain of dns server
         2022072401     ; Serial Number, should be change any time when modify happens
               3600     ; Refresh
                180     ; Retry
              86400     ; Expire
                300 )   ; Negative Cache TTL
;
                                            IN  NS    ns1.potat0.dn42.  ; announce the name server of current zone(domain) to be ns1.potat0.dn42.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0     IN  PTR   potat0.dn42.

0x05 配置 DNSSEC

至此,我们以及完成了权威 DNS 的所有必须的配置。如果你不想配置 DNSSEC,则可以直接进行测试

但是,既然做了,不如一次性做好。其实是因为 DNSSEC 配置完成后需要修改 DN42 Registry,那就需要再发一个 PR 了,还是给 burble 减减负吧:P

开始前,可以先访问 Cloudflare 的这篇文章了解一下 DNSSEC 的工作过程。

生成密钥

首先,我们需要生成我们的 ZSK 和 KSK。为此,我创建了 /etc/bind/dnssec_keys 目录来存放相关的 Key。

进入 /etc/bind/dnssec_keys 目录,使用如下语句生成密钥:

dnssec-keygen -a ECDSAP256SHA256 -n ZONE <your-zone-name>
dnssec-keygen -f KSK -a ECDSAP256SHA256 -n ZONE <your-zone-name>

其中第一条将会生成 ZSK,第二条会生成 KSK。注意,所有需要配置 DNSSEC 的 Zone 都需要分别生成对应的 ZSK 和 KSK。

关联 Zone 和密钥

观察 /etc/bind/dnssec_keys 目录,会发现每个 Zone 都有 4 个文件,文件名为 K<your-zone-name>+xxx+xxxxx.keyK<your-zone-name>+xxx+xxxxx.privateK<your-zone-name>+yyy+yyyyy.keyK<your-zone-name>+yyy+yyyyy.private

现在,编辑所有需要配置 DNSSEC 的 Zone 的对应文件,在文件的最末尾,加入如下语句:

$INCLUDE "/etc/bind/dnssec_keys/K<your-zone-name>+xxx+xxxxx.key"
$INCLUDE "/etc/bind/dnssec_keys/K<your-zone-name>+yyy+yyyyy.key"

也就是将 ZSK 与 KSK 引入到 Zone 文件末尾。引入的顺序无关。

签名 Zone

现在是时候对 Zone 签名了。

进入 /etc/bind/zones 目录,对所有需要配置 DNSSEC 的 Zone 分别执行下述命令进行签名:

提醒:

与 SOA 记录类似,下面的 <your-zone-name> 末尾也都是带有 . 的。有些奇怪,但这是必须的。缺少末尾点会导致报错。

所以请不要忘记加上他们。

dnssec-signzone -K ../dnssec_keys -o <your-zone-name> ./<your-zone-file>

如果一切顺利,你会在当前目录见到多出的 2 个文件: <your-zone-file>.signeddsset-<your-zone-name> 。记住他们的名字!

修改 named.conf.local

现在,我们需要让 Bind 读取签名后的 Zone 文件。

方法很简单,只需要修改 named.conf.local 文件,将已经完成签名的 Zone 的 file 属性改为以 .signed 结尾的文件(也就是刚才签名时多出来的其中一个文件)。

修改 named.conf.options

最后,我们需要修改 named.conf.options ,让 Bird 启用 DNSSEC。只需在 named.conf.options 中加入下面的选项即可:

dnssec-validation auto;

如果你去网上搜索,你会看到很多教你在 named.conf.options 中添加下述配置的教程:

dnssec-enable yes;
dnssec-lookaside auto;

他们或许曾经是对的,但是现在请千万不要这么做!

从 Bind 9.16 起, dnssec-enablednssec-lookaside 已经被废弃了

加上这些只会弄巧成拙。

0x06 测试

为了减少给别人添麻烦,这里提供了一些基本的测试,可以简单判断一下你的 Bind 是否部署正常。测试前记得使用 service named reload 重启 Bind 服务!

由于你的域名还没有真正在 DN42 中被注册,因此需要指定 DNS 服务器。

你可以修改并运行下面的语句,对照自己的结果是否与直接运行(也就是我的结果)相似。如果不太一样,就说明有一些问题。

下面的测试很多,嫌麻烦的话随机挑几个测一下吧。

基本测试

如果你没有配置 DNSSEC,则在测试过程中请去除 -D 选项,同时忽略参考结果中的 RRSIG 记录。

drill -D @172.23.246.1 SOA potat0.dn42
drill -D @172.23.246.1 SOA 0/26.246.23.172.in-addr.arpa
drill -D @172.23.246.1 SOA 2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa
drill -D @172.23.246.1 DNSKEY potat0.dn42
drill -D @172.23.246.1 DNSKEY 0/26.246.23.172.in-addr.arpa
drill -D @172.23.246.1 DNSKEY 2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa
drill -D @172.23.246.1 A potat0.dn42
drill -D @172.23.246.1 AAAA potat0.dn42
drill -D @172.23.246.1 PTR 1.0/26.246.23.172.in-addr.arpa
drill -D @172.23.246.1 PTR 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa

DNSSEC 验证

如果你没有配置 DNSSEC,请跳过改部分测试。

首先,准备 trust-anchors 文件,内容如下:

trust-anchors {
  "potat0.dn42." static-key 257 3 13 "bhrgZCEAUuLRChkVmZb1N2lkuNhqX2rcItPlVtmoSMzmCKm1X9extkQGIgerr7KNlkQdViI/lWbSguB8u5zQYQ==";
  "0/26.246.23.172.in-addr.arpa." static-key 257 3 13 "6rlQRG+vJA8gVjWShOiCH0/6QZ9NanlgFVigMMKXSUuUyj82pUhAMjaSlLuGsnF7MY00qQ5nC40HGXUWA5pH0g==";
  "2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa." static-key 257 3 13 "5r6vR7XdVjTk7DovODDwaGjBPySRYIUuqT9CZH0neQcY9R1QuBLBCTFNmZeGWYJsct1On8ZIw6yWm27Om1ArOg==";
};

其中,一行一个 Zone, static-key 后面的内容,是 drill -D @172.23.246.1 DNSKEY <zone-name> 返回的 KSK 的 DNSKEY 记录的值。可以对照上面的测试项定位一下。

然后进行如下测试:

$ delv @172.23.246.1 -a ./trust-anchors +root=potat0.dn42. potat0.dn42. SOA
; fully validated
potat0.dn42.            300     IN      SOA     ns1.potat0.dn42. dn42.potat0.cc. 2022072201 3600 180 86400 300
potat0.dn42.            300     IN      RRSIG   SOA 13 2 300 20220822062531 20220723062531 58169 potat0.dn42. B7ipJymfKCmmF955LVnT1sKLW1d3Lb0x41qKPIurC1zeXE5VkunLdocS Q9KMAi7JQDsUsb92jaQwd+Zq73PSmQ==

$ delv @172.23.246.1 -a ./trust-anchors +root=0/26.246.23.172.in-addr.arpa. 0/26.246.23.172.in-addr.arpa. SOA
; fully validated
0/26.246.23.172.in-addr.arpa. 300 IN    SOA     ns1.potat0.dn42. dn42.potat0.cc. 2022072502 3600 180 86400 300
0/26.246.23.172.in-addr.arpa. 300 IN    RRSIG   SOA 13 6 300 20220824045403 20220725045403 27415 0/26.246.23.172.in-addr.arpa. 4wGpuUpew0cQvwsyWTRBTJg2gEQsLIrvrqWXepaaDUPJfIpp/dpotEOz o88/JEX8UEnn1v1Atj7eWC2CpTdTAw==

$ delv @172.23.246.1 -a ./trust-anchors +root=2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa. 2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa. SOA
; fully validated
2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa. 300 IN SOA    ns1.potat0.dn42. me.potat0.top. 2022072201 3600 180 86400 300
2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa. 300 IN RRSIG  SOA 13 14 300 20220822063302 20220723063302 49981 2.4.0.4.3.2.3.1.c.2.d.f.ip6.arpa. MXM42j8X4PA3CqRyMaLAdBhyuU1v9W4xtNZdq6KeHp9X2CL8bieFIBp4 IYMzxaTnk3ApCg8WU0S5jheSkvkNcg==

0x07 在 DN42 中注册域名

终于!我们已经完成了所有部署工作,现在是时候向 DN42 Registry 注册域名了。

与注册 DN42 相似,你也需要 Fork dn42/registry,再修改文件后 git addgit commitgit push ,发起 PR,并附上签名文本,这些在此不再赘述。如有疑问请阅读蓝天的 DN42 注册教程

注册域名

对于我们的需求(注册域名),最主要的是在 data/dns/ 中创建对应的文件。以我为例,我创建了 potat0.dn42 ,内容如下:

domain:             potat0.dn42
admin-c:            POTAT0-DN42
tech-c:             POTAT0-DN42
mnt-by:             POTAT0-MNT
nserver:            ns1.potat0.dn42 172.23.246.1
nserver:            ns1.potat0.dn42 fd2c:1323:4042::1
ds-rdata:           29004 13 2 28AFACEA2ACDA38340C7BFF8240FF971EC4803B0B766A1F33B1B4ACF 0EF56AED
source:             DN42

其中,你的所有 ns 服务器地址都可以填入 nserver 字段。

对于 DNSSEC,最重要的是 ds-rdata 字段。

还记得刚才的 dsset-<your-zone-name> 文件吗,它的格式如下:

potat0.dn42.            IN DS 29004 13 2 28AFACEA2ACDA38340C7BFF8240FF971EC4803B0B766A1F33B1B4ACF 0EF56AED

IN DS 之后的内容就是 ds-rdata 字段所需要的内容。

在这里,因为是在注册域名,因此应该填入主域名的 dsset 记录。

注册反向 DNS 解析

由于我们也部署了 IPv4 和 IPv6 的反向 DNS 解析,因此我们也要在仓库中注册他们。

修改 data/inetnumdata/inet6num 中的对应文件,添加追加如下 2 行:

nserver:            ns1.potat0.dn42
ds-rdata:           <your-dsset>

其他 nserver 是你的反向 DNS 解析服务器的域名,下面的 ds-rdata 字段是对应的 dsset 记录。

0x08 接下来做什么

  • 域名已经注册好了,当然是部署网站了。

    DN42 中有自己的 SSL Certificate Authority,同时也有人提供了 ACME 服务

    你可以先在自己的设备上信任 DN42 的根证书,同时试试也给你自己的域名签发一张 SSL 证书。

  • 不如考虑和我 Peer 一下?欢迎访问 https://dn42.potat0.cc/ 来获取相关信息!

0xFF 参考 | 致谢


在 DN42 中注册域名并开启 DNSSEC
https://potat0.cc/posts/20220726/Register_DN42_Domain/
作者
Potat0
发布于
2022年7月26日
许可协议