构建 Linux IPv6 DNS 服务器
IPv6 是互联网工程任务组 (IETF) 设计的下一代协议,旨在取代当前版本的互联网协议 IPv4。IPv4 具有非凡的弹性。然而,其最初的设计并未考虑到当今的几个重要问题,例如大型地址空间、移动性、安全性、自动配置和服务质量。为了解决这些问题,IETF 开发了一套称为 IPv6 的协议和标准,其中包含了许多更新 IPv4 的概念和建议方法。因此,IPv6 修复了 IPv4 中的许多问题,并增加了许多迎合未来移动互联网的改进和功能。
IPv6 预计将逐步取代 IPv4,两者将在过渡期内共存数年。服务器将是双栈的,同时支持 IPv4 和 IPv6。
在本文中,我们将仔细研究 IPv6 名称解析,并提供技术教程,以帮助读者设置自己的 IPv6 Linux DNS 服务器,以便使用最新版本的 BIND 9.x 进行 IPv6 名称解析。
在本节中,我们将介绍一个包含不同 IPv6 服务器的示例网络方案(图 1)。
此架构中表示以下节点
路由服务器 (pc1) 充当 IPv6 软件路由器服务器,并为所有 IPv6 节点提供路由器通告。
DNS IPv6 服务器 (pc2) 提供 IPv6 名称解析。
两个应用服务器,一个提供视频流 (pc3),另一个是基于 Apache 的 Web 服务器 (pc4)。
客户端机器 (pc5–7) 用于测试目的。
域名是互联网地址的有意义且易于记忆的“句柄”。域名系统 (DNS) 是定位互联网域名并将其转换为互联网协议地址的方式。由于维护域名/IP 地址对应关系的中央列表是不切实际的,因此域名和 IP 地址列表分布在整个互联网中,形成一个权威层级结构。通常,DNS 服务器位于您的接入提供商的附近地理范围内;此 DNS 服务器映射 DNS 请求中的域名或将其转发到互联网上的其他服务器。对于 IPv6 DNS 请求,A6 和 AAAA 语法都用于表示 IPv6 地址。
AAAA 资源记录(称为 quad A 记录)的格式为固定长度数据。使用 AAAA,我们可以为 IPv6 名称解析定义 DNS 记录,方法与 IPv4 中的 A 记录相同
$ORIGIN X.EXAMPLE. N AAAA 2345:00C1:CA11:0001:1234:5678:9ABC:DEF0 N AAAA 2345:00D2:DA11:0001:1234:5678:9ABC:DEF0 N AAAA 2345:000E:EB22:0001:1234:5678:9ABC:DEF0
A6 资源记录的格式为可变长度数据。使用 A6,可以使用多个 DNS 记录定义 IPv6 地址。以下示例摘自 RFC 2874
$ORIGIN X.EXAMPLE. N A6 64 ::1234:5678:9ABC:DEF0 SUBNET-1.IP6 SUBNET-1.IP6 A6 48 0:0:0:1:: IP6 IP6 A6 48 0::0 SUBSCRIBER-X.IP6.A.NET. IP6 A6 48 0::0 SUBSCRIBER-X.IP6.B.NET. SUBSCRIBER-X.IP6.A.NET. A6 40 0:0:0011:: A.NET.IP6.C.NET. SUBSCRIBER-X.IP6.A.NET. A6 40 0:0:0011:: A.NET.IP6.D.NET. SUBSCRIBER-X.IP6.B.NET. A6 40 0:0:0022:: B-NET.IP6.E.NET. A.NET.IP6.C.NET. A6 28 0:0001:CA00:: C.NET.ALPHA-TLA.ORG. A.NET.IP6.D.NET. A6 28 0:0002:DA00:: D.NET.ALPHA-TLA.ORG. B-NET.IP6.E.NET. A6 32 0:0:EB00:: E.NET.ALPHA-TLA.ORG. C.NET.ALPHA-TLA.ORG. A6 0 2345:00C0:: D.NET.ALPHA-TLA.ORG. A6 0 2345:00D0:: E.NET.ALPHA-TLA.ORG. A6 0 2345:000E::
如果我们将以上代码转换为 AAAA 记录,则如下所示
$ORIGIN X.EXAMPLE. N AAAA 2345:00C1:CA11:0001:1234:5678:9ABC:DEF0 N AAAA 2345:00D2:DA11:0001:1234:5678:9ABC:DEF0 N AAAA 2345:000E:EB22:0001:1234:5678:9ABC:DEF0
配置 IPv6 名称解析后,我们可以将域名系统安全扩展 (DNSSEC) 添加到我们的 DNS 服务器。DNSSEC 提供三项不同的服务:密钥分发、数据来源身份验证以及事务和请求身份验证。DNSSEC 的完整定义在 RFC 2535 中提供。
在安装兼容 IPv6 的 BIND 版本之前的必要步骤是在内核中以及在支持 IPv6 的系统上的网络二进制文件中启用 IPv6 支持。我们在之前的文章“在 Linux 服务器节点上支持 IPv6”中介绍了这个主题,该文章发表在 2002 年 8 月的 LJ 杂志上 (/article/4763)。按照该文章中提供的教程操作后,您应该可以安装具有 IPv6 支持的最新 BIND 版本。
最新版本的 BIND 可从互联网软件联盟网站 (www.isc.org/products/BIND/BIND9.html) 获取。BIND 版本 9 是对底层 BIND 架构几乎所有方面进行重大重写的版本。版本 9 中引入了许多重要功能和增强功能;与本文最相关的是对 IPv6 的支持。BIND 9.x 允许 DNS 服务器在 IPv6 套接字上回答 DNS 查询,提供对 IPv6 资源记录(A6、DNAME 等)的支持,并支持位串标签。此外,BIND 9.x 还提供了一个实验性的 IPv6 解析器库。还有许多其他功能可用,您可以从 BIND 网站阅读有关它们的更多信息。
BIND 9.2.1 是在撰写本文时可用的最新稳定版本。我们的安装和配置过程遵循此版本。要安装 BIND,首先将最新版本的 BIND 下载到 /usr/src 中,然后使用以下命令解压缩软件包
% tar -xzf bind-9.2.1.tar.gz % cd bind-9.2.1
虽然 IPv6 支持是 BIND 的原生功能,但在编译时必须显式指定。此外,由于我们希望支持 DNSSEC,因此我们需要使用加密支持编译 BIND。应安装 OpenSSL 0.9.5a 或更高版本。使用所需选项运行配置脚本如下所示
% ./configure -enable-ipv6 -with-openssl
最后,使用以下命令以 root 用户身份编译并安装软件包
% make && make install
默认情况下,BIND 9 文件分布在文件系统中。配置文件位于 /etc/named.conf 中;二进制文件“named”位于 /usr/local/sbin 中,所有其他相关配置文件都位于 /var/named 中。
DNS 查询可以通过多种不同的方式解析。例如,DNS 服务器可以使用其缓存来回答查询,或者代表客户端联系其他 DNS 服务器以完全解析名称。当 DNS 服务器收到查询时,它首先检查是否可以根据服务器上本地配置区域中包含的资源记录信息权威地回答查询。如果查询的名称与本地区域信息中的相应资源记录匹配,则服务器会使用此信息权威地回答查询名称。对于完整的 DNS 查询过程,存在四个现有的 DNS 区域
主服务器:服务器具有区域数据的主副本,并为其提供权威答案。
辅助服务器:辅助区域是主区域的副本。每个辅助区域都有一个主服务器列表,它可以查询这些主服务器以接收对其区域副本的更新。辅助服务器可以选择将区域副本保存在磁盘上以加快启动速度。单个主服务器可以有任意数量的辅助服务器,以分配负载。
存根服务器:存根区域很像辅助区域,行为也很相似,但它仅复制主区域的 NS 记录,而不是整个区域。存根区域跟踪哪些 DNS 服务器对组织具有权威性。它们直接联系根 DNS 服务器以确定哪些服务器对哪些域具有权威性。
转发服务器:转发区域将区域中的所有查询定向到其他服务器。因此,它充当网络的缓存 DNS 服务器。或者,它可以为防火墙后面的网络提供互联网 DNS 服务,防火墙限制外部 DNS 查询,但显然转发 DNS 服务器必须具有对互联网的 DNS 访问权限。这种情况类似于全局转发设施,但允许每个区域选择转发器。
为了将其映射到我们的网络(图 1),我们需要为我们自己的域 secv6.your.domain 创建一个主服务器。列表 1 提供了示例 /etc/named.conf 配置。(密钥已截断以适合一行。)
列表 1. /etc/named.conf
options { directory "/var/named"; // a caching only nameserver config zone "." IN { type hint; file "named.ca"; }; // this defines the loopback name lookup zone "localhost" IN { type master; file "master/localhost.zone"; allow-update { none; }; }; // this defines the loopback reverse name lookup zone "0.0.127.in-addr.arpa" IN { type master; file "master/localhost.rev"; allow-update { none; }; }; // This defines the secv6 domain name lookup // Secure (signed) zone file is // secv6.your.domain.signed // Regular zone file is secv6.your.domain zone "secv6.your.domain" IN { type master; file "master/secv6.your.domain.signed"; // file "master/secv6.your.domain"; }; // this defines the secv6 domain reverse // name lookup (AAAA) zone "secv6.int" IN { type master; file "master/secv6.int"; }; // this defines the secv6 domain reverse // name lookup (A6) zone "secv6.arpa" IN { type master; file "master/secv6.rev"; }; // secret key truncated to fit key "key" { algorithm hmac-md5; secret "HxbmAnSO0quVxcxBDjmAmjrmhgDUVFcFNcfmHC"; };
下一步是定义描述我们域的配置文件。请注意,到目前为止,我们还没有接触到 IPv6 的具体细节。至于 DNSSEC,文件 /var/named/master/secv6.your.domain.signed 是由 DNS 服务器的区域密钥签名的域文件。这对于 DNSSEC 很重要,因为客户端能够验证所有后续 DNS 请求。DNS 服务器区域密钥与配置文件中的密钥不同;有关如何生成区域密钥的详细信息将在本文稍后讨论。
要编辑的下一个文件是 /var/named/master/secv6.your.domain。我们的示例(列表 2)同时使用了 AAAA 和 A6 格式。末尾的 $INCLUDE 指令包含区域密钥的公共部分。保持密钥的私有部分私有。私钥在末尾附加了private而key后缀为公钥。如果您对 DNSSEC 密钥及其权限有任何疑问,请查阅 BIND 手册。在列表 2 中,我们显示了 secv6.your.domain 的典型 IPv6 DNS 域配置。
列表 2. /var/named/master/secv6.your.domain
$TTL 86400 $ORIGIN secv6.your.domain. @ IN SOA secv6.your.domain. hostmaster.your.domain. ( 2002011442 ; Serial number (yyyymmdd-num) 3H ; Refresh 15M ; Retry 1W ; Expire 1D ) ; Minimum IN MX 10 noah.your.domain. IN NS ns.secv6.your.domain. $ORIGIN secv6.your.domain. ns 1D IN AAAA fec0::1:250:b7ff:fe14:35d0 1D IN A6 0 fec0::1:250:b7ff:fe14:35d0 secv6.your.domain. 1D IN AAAA fec0::1:250:b7ff:fe14:35d0 1D IN A6 0 fec0::1:250:b7ff:fe14:35d0 pc2 1D IN AAAA fec0::1:250:b7ff:fe14:35d0 1D IN A6 0 fec0::1:250:b7ff:fe14:35d0 pc3 1D IN A6 0 fec0::1:250:b9ff:fe00:131 1D IN AAAA fec0::1:250:b9ff:fe00:131 pc6 1D IN A6 0 fec0::1:250:b7ff:fe14:3617 1D IN AAAA fec0::1:250:b7ff:fe14:3617 pc4 1D IN A6 0 fec0::1:250:b7ff:fe14:35c4 1D IN AAAA fec0::1:250:b7ff:fe14:35c4 pc5 1D IN A6 0 fec0::1:250:b7ff:fe14:361b 1D IN AAAA fec0::1:250:b7ff:fe14:361b pc7 1D IN A6 0 fec0::1:250:b7ff:fe14:365a 1D IN AAAA fec0::1:250:b7ff:fe14:365a pc1 1D IN A6 0 fec0::1:250:b9ff:fe00:12e 1D IN AAAA fec0::1:250:b9ff:fe00:12e pc1 1D IN A6 0 fec0:0:0:1::1 1D IN AAAA fec0:0:0:1::1 $INCLUDE "/var/named/master/Ksecv6.your.domain.+003+27034.key"
对于 /var/named/master 中的配置文件,Hostmaster 实际上是管理员的电子邮件地址,其中第一个点代替了 at 符号 (@),因为语法限制。此外,列表 2 开头 IN SOA 结构的第一个数字是序列号,通常表示为 YYYYMMDDNN,其中 NN 是每次更新 DNS 区域时递增的数字。
现在,我们讨论如何生成区域密钥。此步骤的工作目录很重要,因为密钥放置在那里。我们建议将密钥放置在 /var/named/master 中。以下命令为区域生成 768 位 DSA 密钥
% dnssec-keygen -a DSA -b 768 -n ZONE \ secv6.your.domain
默认情况下,所有具有可用私钥的区域密钥都用于生成签名。密钥必须位于工作目录中或包含在区域文件中。以下命令签署 secv6.your.domain 区域,假设它位于名为 /var/named/master/secv6.your.domain 的文件中
% dnssec-signzone -o secv6.your.domain \ secv6.your.domain
生成一个输出文件:/var/named/master/secv6.your.domain.signed。此文件应由 /etc/named.conf 引用,作为区域的输入文件。
其余配置文件是 localhost.zone(列表 3)、localhost.rev(列表 4)、secv6.rev(列表 5)和 secv6.int(列表 6)。反向查找区域文件 secv6.rev 和 secv6.int 之间的区别在于,可以使用 A6 字符串(在 secv6.rev 中不需要反转)指定一个,另一个可以使用 secv6.int 中反向 AAAA 格式地址指定。例如,ping6 只能引用 secv6.int 域,因为它不支持 A6 格式。
列表 3. /var/named/master/localhost.zone
// localhost.zone Allows for local communications // using the loopback interface $TTL 86400 $ORIGIN localhost. @ 1D IN SOA @ root ( 42 ; serial (d. adams) 3H ; refresh 15M ; retry 1W ; expire 1D ) ; minimum 1D IN NS @ 1D IN A 127.0.0.1
列表 4. /var/named/master/localhost.rev
// localhost.rev Defines reverse DNS lookup on // loopback interface $TTL 86400 $ORIGIN 0.0.127.in-addr.arpa. @ IN SOA 0.0.127.in-addr.arpa. hostmaster.secv6.your.domain. ( 42 ; Serial number (d. adams) 3H ; Refresh 15M ; Retry 1W ; Expire 1D ) ; Minimum NS ns.secv6.your.domain. MX 10 noah.ip6.your.domain. PTR localhost.
列表 5. /var/named/master/secv6.rev
// secv6.rev Defines reverse lookup for secv6 // domain in A6 format $TTL 86400 $ORIGIN secv6.arpa. @ IN SOA secv6.arpa. hostmaster.secv6.your.domain. ( 2002011442 ; Serial number (yyyymmdd-num) 3H ; Refresh 15M ; Retry 1W ; Expire 1D ) ; Minimum NS ns.secv6.your.domain. MX 10 noah.your.domain. ; fec0:0:0:1::/64 $ORIGIN \[xfec0000000000001/64].secv6.arpa. \[x0250b7fffe1435d0/64] 1D IN PTR pc2.secv6.your.domain. \[x0250b9fffe000131/64] 1D IN PTR pc3.secv6.your.domain. \[x0250b7fffe143617/64] 1D IN PTR pc6.secv6.your.domain. \[x0250b7fffe1435c4/64] 1D IN PTR pc4.secv6.your.domain. \[x0250b7fffe14361b/64] 1D IN PTR pc5.secv6.your.domain. \[x0250b7fffe14365a/64] 1D IN PTR pc7.secv6.your.domain. \[x0250b9fffe00012e/64] 1D IN PTR pc1.secv6.your.domain.
列表 6. /var/named/master/secv6.int
// secv6.int Defines reverse lookup for secv6 // domain in AAA format $TTL 86400 $ORIGIN secv6.int. @ IN SOA secv6.int. hostmaster.secv6.your.domain. ( 2002011442 ; Serial number (yyyymmdd-num) 3H ; Refresh 15M ; Retry 1W ; Expire 1D ) ; Minimum NS ns.secv6.your.domain. MX 10 noah.your.domain. ; fec0:0:0:1::/64 $ORIGIN 1.0.0.0.0.0.0.0.0.0.0.0.0.c.e.f.secv6.int. 0.d.5.3.4.1.e.f.f.f.7.b.0.5.2.0 IN PTR pc2.secv6.your.domain. e.2.1.0.0.0.e.f.f.f.9.b.0.5.2.0 IN PTR pc1.secv6.your.domain. 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR pc1.secv6.your.domain. 1.3.1.0.0.0.e.f.f.f.9.b.0.5.2.0 IN PTR pc3.secv6.your.domain. 7.1.6.3.4.1.e.f.f.f.7.b.0.5.2.0 IN PTR pc6.secv6.your.domain. 4.c.5.3.4.1.e.f.f.f.7.b.0.5.2.0 IN PTR pc4.secv6.your.domain. b.1.6.3.4.1.e.f.f.f.7.b.0.5.2.0 IN PTR pc5.secv6.your.domain.
安装和配置步骤完成后,您就可以在 pc2 上启动 DNS 守护程序了。Named 默认使用 /etc/named.conf,但如果需要,您可以使用 -c 选项指定其他配置文件。根据您安装守护程序的位置,输入
pc2% /usr/local/sbin/named
IPv6 网络中的机器还需要一个额外的配置步骤:更新 /etc/resolv.conf(列表 7)以包含 DNS 服务器的 IP 地址。重要的是包含 IP 地址而不是 DNS 服务器的主机名,因为此文件是系统查找 DNS 地址的位置。换句话说,如果您在此处指定了 DNS 服务器的主机名,系统如何知道哪个 IP 地址对应于 DNS 的主机名?
列表 7. 客户端机器上的 /etc/resolv.conf
# To enable secv6 domain, start named on pc2 # and use this file as /etc/resolv.conf search secv6.your.domain nameserver fec0::1:250:b7ff:fe14:35d0
我们使用两种简单的方法测试设置。第一个方法验证 DNS 服务器中是否启用了 A6 地址,第二个方法验证 DNS 服务器是否支持 AAAA 地址。测试在 pc2 上执行。我们在此处仅展示有意义的输出;否则列表会太长。对于第一个示例,我们使用 DNS 查找实用程序 dig 以 A6 格式对 secv6 域执行查找(列表 8)。然后,我们以 AAAA 格式执行查找(列表 9)。在这两种情况下,我们都没有指定要查找的地址,因此我们使用了 0.0.0.0。
列表 8. A6 DNS 查询
pc2% dig 0.0.0.0 secv6.your.domain a6 ; <<>> DiG 9.1.0 <<>> 0.0.0.0 secv6.your.domain A6 [...] ;secv6.your.domain. IN A6 ;; ANSWER SECTION: secv6.your.domain. 86400 IN A6 0 fec0::1:250:b7ff:fe14:35d0 ;; AUTHORITY SECTION: secv6.your.domain. 86400 IN NS ns.secv6.your.domain. ;; ADDITIONAL SECTION: ns.secv6.your.domain. 86400 IN A6 0 fec0::1:250:b7ff:fe14:35d0 ns.secv6.your.domain. 86400 IN AAAA fec0::1:250:b7ff:fe14:35d0
列表 9. AAAA DNS 查询
pc2% dig 0.0.0.0 secv6.your.domain aaaa ; <<>> DiG 9.1.0 <<>> 0.0.0.0 secv6.your.domain AAAA [...] ;secv6.your.domain. IN AAAA ;; ANSWER SECTION: secv6.your.domain. 86400 IN AAAA fec0::1:250:b7ff:fe14:35d0 ;; AUTHORITY SECTION: secv6.your.domain. 86400 IN NS ns.secv6.your.domain. ;; ADDITIONAL SECTION: ns.secv6.your.domain. 86400 IN A6 0 fec0::1:250:b7ff:fe14:35d0 ns.secv6.your.domain. 86400 IN AAAA fec0::1:250:b7ff:fe14:35d0
对于我们的第二个测试,我们包括 SSH 会话连接的示例,首先使用 IPv6 地址,然后使用 IPv6 主机名。
在我们的 IPv6 网络中,我们介绍了两个应用程序服务器:作为 Web 服务器的 Apache 和用于视频流的 VideoLan。为了在流式传输视频时测试 IPv6 名称解析,客户端节点 pc5 上的用户访问 pc3 上的视频流服务器。视频服务器位于 pc3 (fec0::1:250:b7ff:fe14:5768) 上,视频客户端位于 pc5 (fec0::1:250:b7ff:fe50:7c) 上。使用 tcpdump 嗅探 pc5 上的网络通信,我们捕获了来自视频流的数据包。以下是跟踪的一部分
% tcpdump ip6 # only trace IPv6 traffic, must be run as root or setuid root [snip...] 02:09:26.716040 fec0::1:250:b7ff:fe14:5768.32769 > fec0::1:250:b7ff:fe50:7c.1234: udp 1316 02:09:26.735805 fec0::1:250:b7ff:fe14:5768.32769 > fec0::1:250:b7ff:fe50:7c.1234: udp 1316 02:09:26.735971 fec0::1:250:b7ff:fe14:5768.32769 > fec0::1:250:b7ff:fe50:7c.1234: udp 1316 02:09:26.736082 fec0::1:250:b7ff:fe14:5768.32769 > fec0::1:250:b7ff:fe50:7c.1234: udp 1316 02:09:26.755810 fec0::1:250:b7ff:fe14:5768.32769 > fec0::1:250:b7ff:fe50:7c.1234: udp 1316 02:09:26.755935 fec0::1:250:b7ff:fe14:5768.32769 > fec0::1:250:b7ff:fe50:7c.1234: udp 1316 02:09:26.775787 fec0::1:250:b7ff:fe14:5768.32769 > fec0::1:250:b7ff:fe50:7c.1234: udp 1316
使用 Linux X 服务器上的 X11 输出正确显示视频;图 2 显示了来自流的捕获。

图 2. IPv6 视频的输出流
IPv6 正在成为现实。在完全过渡到 IPv6 之前,在未来几年内,我们需要能够在我们的服务器上同时支持 IPv4 和 IPv6。我们需要不同的拼图碎片来实现完全迁移到 IPv6,而必不可少的一块是兼容 IPv6 的 BIND 实现。
资源
BIND: www.isc.org/products/BIND/BIND9.html
BIND 手册: www.crt.se/dnssec/bind9/Bv9ARM.html
AAAA 和 A6 的比较: www.ietf.org/proceedings/02mar/I-D/draft-ietf-dnsext-aaaa-a6-01.txt
DNSSEC: www.ietf.org/rfc/rfc2535.txt
DNSSEC 和 IPv6 A6: ftp.rfc-editor.org/in-notes/rfc3226.txt
DNSSEC 签名授权机构: ftp.rfc-editor.org/in-notes/rfc3008.txt
IPv6 HOWTO: www.bieringer.de/linux/IPv6/IPv6-HOWTO/IPv6-HOWTO.html
IPv6 Linux 实现: /article/5468
DNS 的 IPv6 支持: www.ietf.org/rfc/rfc2874.txt
IP 版本 6 寻址架构: www.rfc-editor.org/rfc/rfc2373.txt
Linux 内核: www.kernel.org
“在 Linux 服务器节点上支持 IPv6”,作者:Hbrahim Haddad 和 Marc Blanchet,LJ,2002 年 8 月: /article/4763
David Gordon (David.Gordon@Ericsson.ca) 是爱立信研究 - 开放系统实验室的计算机科学实习生。他正在 Sherbrooke 大学完成计算机科学专业的本科学习。他的研究兴趣包括安全、下一代 IP 网络和无线技术。
Ibrahim Haddad (Ibrahim.Haddad@Ericsson.com) 是爱立信公司蒙特利尔研究部门的研究员,参与第三代无线 IP 网络的系统架构研究。