在 Linux 上构建您自己的 DNS 服务器

了解如何使用 BIND 设置您自己的服务器来解析域名。
630 位读者喜欢这篇文章。
Pixelated globe

Geralt。CC0。

在本系列文章的前一篇《域名系统 (DNS) 简介》中,我介绍了 DNS 数据库的结构以及如何在客户端上配置名称服务。我还列出并描述了一些在构建名称服务器或尝试解释 dig 命令结果时可能遇到的更常见的 DNS 记录。

在本文中,我将向您展示如何使用 BIND(Berkeley Internet Name Domain,伯克利互联网名称域)构建您自己的名称服务器。它并不像您想象的那么困难,特别是您可以分两个阶段完成它。

在本文中,您将首先学习如何创建缓存名称服务器,然后您将继续学习如何将其升级为完整的网络主域名服务器,包括正向和反向区域文件。

使用 BIND 设置 DNS 服务器

使用 BIND 设置名称服务器非常简单,因此我将向您展示如何在您可能拥有的任何计算机上进行操作以进行实验。这个小型实验室项目将向您展示如何在您的计算机上安装和配置 BIND 作为缓存名称服务器、对其进行测试,然后将其设置为具有区域文件的主名称服务器,您可以将其用作网络的名称解析器,或者仅用于测试。

从技术上讲,在您拥有的任何 GNU/Linux 计算机上设置名称服务器都是可行的,因为它不会干扰网络上的其他主机或其运行。但是,您可能不应该在您不拥有或无权修改的计算机上执行此操作,除非您获得明确的许可。

我的设置

您只需要一台计算机即可执行此实验室项目中的所有任务,但一项任务除外。我在功能更强大的 ThinkPad 上使用此设置,因为当我使用有线或无线连接连接到非家庭网络时,DHCP(动态主机配置协议)提供的名称服务器有时可能不可靠。为了表明几乎任何主机都可以很好地充当名称服务器,我已经在旧的 ASUS EeePC 900 上测试了这个项目上网本。

我将在此项目中使用我的 ASUS 的私有 IP 地址,但您应该使用您正在使用的主机的 IP 地址。

hosts 文件

首先,让我们看一下 /etc/hosts 文件。在其默认状态下,hosts 文件中应该只有两行,即下面列表 1 中看到的前两行。

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

# Lab hosts
192.168.25.1        server
192.168.25.21      host1
192.168.25.22      host2
192.168.25.23      host3
192.168.25.24      host4

列表 1:您可以维护一个简单的 hosts 文件,以在小型网络中执行解析器的功能。

虽然您可以像列表 1 中所示那样添加主机名及其各自的 IP 地址,但这并不是名称服务的最佳解决方案,尤其是在旅行时。如果您的 hosts 文件中有其他条目,如果它们干扰命名或 IP 地址,您可能需要将它们注释掉,以用于此项目期间。你们大多数人除了两个默认行之外,不会有任何其他条目。

准备工作

缓存名称服务器无法取代您使用 /etc/hosts 来解析内部网络上的主机名;但是,与使用 ISP 或其他公共名称服务器相比,缓存名称服务器可以提高解析常用外部名称(例如 www.cnn.com)时的性能。最好的部分是,设置缓存名称服务器非常容易。

在开始之前,您应该通过执行以下步骤进行准备。

首先,制作文件 /etc/hosts/etc/named.confresolv.conf/etc/sysconfig/iptables 的备份副本。

如果尚未安装,请使用您的发行版的软件包管理器安装以下 BIND RPM:bindbind-chrootbind-utils。要使您的实验室主机能够使用缓存名称服务器,您必须在 /etc/resolv.conf 中添加一个名称服务器行,以指向您自己的主机。例如,如果您的实验室主机 IP 地址是 192.168.0.203,就像我的 epc 一样,请将以下行添加到 /etc/resolv.conf 中的名称服务器列表的顶部

name server         192.168.0.203

请务必使用您正在进行此项目的主机的 IP 地址。

您可以使用本地主机的 IP 地址 127.0.0.1 而不是外部 IP 地址。您还应该注释掉指向其他主机作为名称服务器的任何行。请务必保存修改后的 resolv.conf 文件。

这些更改将立即生效,无需重启或服务重启。现在尝试 ping 一个不阻止 ICMP(Internet 控制消息协议)数据包的常见公共主机;随意使用我的防火墙,它是一个 Raspberry Pi

ping wally2.both.org

您应该会收到“未知主机”或“名称或服务未知”错误,因为您当前在 resolv.conf 文件中没有定义任何可用的 DNS 服务或解析器。现在使用 dig 命令查看名称服务是否正常工作。

dig wally2.both.com

您应该收到错误“连接超时;无法到达任何服务器。”

设置缓存名称服务器

缓存名称服务器不是任何域的权威来源。它只是缓存来自其服务的网络的所有名称解析器请求的结果,以加快对将来对同一远程主机的请求的响应。

注意:named.conf 文件对语法,尤其是标点符号非常挑剔。分号用于分隔条目的结尾和节的结尾以及行的结尾。请务必按照示例所示正确添加它们。

对于缓存名称服务器的初始设置,需要对默认的 /etc/named.conf 文件进行一些修改,因此请使用您喜欢的编辑器编辑该文件。首先,将您的本地测试主机的 IP 地址添加到“listen-on port 53”行,如下面的列表 2 所示。这使 named 能够监听您主机的外部 IP 地址,以便其他计算机也可以将其用作名称服务器。

默认情况下,BIND 参考 Internet 的根名称服务器来查找域的权威名称服务器。可以指定其他称为“转发器”的服务器,本地 BIND 实例会将请求发送到这些服务器,而不是根服务器。这确实增加了 DNS 劫持的可能性。

添加一个“forwarders”行,如下所示。这告诉您的缓存 DNS 服务器在本地尚未缓存 IP 地址时从哪里获取 IP 地址。下面列表中的 IP 地址是 Google 公共 DNS 服务器 的 IP 地址。您可以将本地 ISP 或 OpenDNS 或其他一些公共名称服务器用作您的转发器。没有必要定义任何转发器,在这种情况下,BIND 将使用文件 /var/named/named.ca 中定义的 Internet 根服务器来查找域的权威名称服务器(如果没有定义转发器)。但是对于本练习,请像我在列表 2 中那样定义转发器。

注释掉 IPV6 行,因为我们在实验室环境中未使用 IPV6。请注意,“//”两个正斜杠表示 named.conf 文件中的注释。

//
// named.conf
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only name server (as a localhost DNS resolver only).
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//
//

options {
        listen-on port 53 { 127.0.0.1; 192.168.0.203; };
//      listen-on-v6 port 53 { ::1; };
        forwarders { 8.8.8.8; 8.8.4.4; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        allow-query     { localhost; 192.168.0.0/24; };
        recursion yes;


        dnssec-enable yes;
        dnssec-validation yes;
        dnssec-lookaside auto;


        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";


        managed-keys-directory "/var/named/dynamic";
};
logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};
zone "." IN {
        type hint;
        file "named.ca";
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

列表 2:/etc/named.conf 文件提供了设置缓存名称服务器所需的简单配置。需要添加或更改的行以粗体突出显示。

将本地网络地址 192.168.0.0/24 添加到 allow-query 行。此行指定此 DNS 服务器将接受 DNS 查询的网络。

启动名称服务

现在启动 named 服务,并将 named 服务配置为每次启动时都启动。我在我的 Fedora 主机上使用 systemctl 命令,但该命令在您的主机上可能有所不同,具体取决于您使用的发行版。请注意,BIND 解析器服务的名称是 named。

systemctl enable named
systemctl start named

您可以执行的第一个测试以确保您的缓存名称服务器正常工作是使用 dig 查找 wally2.both.org 的 DNS 数据库信息。为了进一步测试您的缓存名称服务器,请使用 dig 命令获取一些常见 Internet 网站的 IP 地址,例如 www.opensource.com、CNN、Wired 以及您喜欢的任何其他网站。结果现在应该显示您的主机作为响应服务器。

此时,您的缓存名称服务器将正确解析 Internet 上的主机,这是因为对公共主机的 DNS 请求已转发到 Google 公共名称服务器 - 请参阅 named.conf 中的“forwarders”行。但是,您仍然依赖 /etc/hosts 文件进行内部名称服务。创建主名称服务器可以解决该问题。

创建主名称服务器

创建缓存名称服务器后,将其转换为功能齐全的主名称服务器并不太困难。主名称服务器是它所代表的域的权威来源。

您需要再次更改 named.conf 并创建几个新文件。您将创建一个名为 Example.com 的域,这是一个为本文档等示例目的保留的域名。Example.com 域在 Internet 上确实有一个 IP 地址和一个非常稀疏的网站,但您可以在实验室项目的其余部分中使用该名称,而不会给任何人造成问题。在本练习的其余部分中,您将使用 Example.com 域作为内部域名。

您将创建的两个新文件是正向和反向区域文件,您将把它们放在 /var/named 目录中。此位置由 named.conf 配置文件中的“directory”指令指定。

创建正向区域文件

正向区域文件包含“A”记录,这些记录将区域(也称为域)中的主机名称与其各自的 IP 地址配对。它还可以包含 CNAME 记录(它是 A 记录中真实主机名的别名)和用于邮件服务器的 MX 记录。

创建一个基本的正向区域文件 /var/named/example.com.zone,并将以下行添加到其中。完成时,您的区域文件应如下面的列表 3 中的示例区域文件所示。

; Authoritative data for example.com zone
;
$TTL 1D
@   IN SOA  epc.example.com   root.epc.example.com. (
                                       2017031301      ; serial
                                       1D              ; refresh
                                       1H              ; retry
                                       1W              ; expire
                                       3H )            ; minimum

$ORIGIN         example.com.
example.com.            IN      NS      epc.example.com.
epc                     IN      A       127.0.0.1
server                  IN      A       192.168.25.1
www                     IN      CNAME   server
mail                    IN      CNAME   server
test1                   IN      A       192.168.25.21
t1                      IN      CNAME   test1
test2                   IN      A       192.168.25.22
test3                   IN      A       192.168.25.23
test4                   IN      A       192.168.25.24

; Mail server MX record
example.com.            IN      MX      10      mail.example.com.

列表 3:Example.com 域的正向区域文件包含此域的主机名及其 IP 地址。

列表 3 中的第一个非注释行是生存时间 (Time to Live) 说明符,在本例中,对于所有未另行指定的记录,生存时间为一天。D 代表天。SOA(起始授权记录)行中的说明符同样显而易见。SOA 记录中参数的详细信息在此处 详细描述

NS 记录必须具有您正在执行此实验室项目的主机的主机名全称 (FQDN)。文件中还必须有一个带有主机有效 IP 地址的 A 记录。在这种情况下,您应该使用本地主机 IP 地址 127.0.0.1。

上面显示的条目将为您提供一些主机名以供实验。

请务必使用今天的日期,并将从 01 开始的计数器附加到序列号。上面的序列号是 2017 年 3 月 4 日的第一次更改。每次更改区域文件时,序列号都会递增。如果存在使用此主服务器的辅助名称服务器,则除非序列号递增,否则它们不会更新。

将正向区域文件添加到 named.conf

但是,在您的 DNS 服务器工作之前,您需要在 /etc/named.conf 中创建一个条目,该条目将指向您的新区域文件。在顶级提示区域的条目下方但在“include”行之前添加以下行。

zone "example.com" IN {
        type master;
        file "example.com.zone";
};

列表 4:将这些行添加到 named.conf 文件,以将 Example.com 区域文件添加到解析器配置。

现在重启 named 以使这些更改生效。通过使用 dignsloookup 命令获取您在正向区域文件中配置的主机的 IP 地址来测试您的名称服务器。请注意,主机不必存在于网络上,dignslookup 命令也会返回 IP 地址。

dig test1.example.com
dig t1.example.com
dig mx example.com
dig mail.example.com
nslookup test3.example.com
dig www.amazon.com

请注意,除非在 /etc/resolv.conf 文件中提供了 Example.com 的域和搜索条目,否则除了 nslookup 命令外,对这些命令使用 FQDN 是必要的。在这种情况下,它们可能不存在,因此在本项目中的所有测试中都只使用 FQDN。

使用根名称服务器

请注意,根名称服务器被指定为 Amazon.com 查找的权威服务器。但请记住,您正在使用 Google 公共名称服务器作为转发器。现在注释掉 named.conf 中的转发器行,然后重启 named。再次运行上述命令以比较返回的结果。结果应类似于列表 5 中下面的结果。

# dig www.amazon.com     

; <<>> DiG 9.10.4-P6-RedHat-9.10.4-4.P6.fc25 <<>> www.amazon.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65004
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.amazon.com.                        IN      A

;; ANSWER SECTION:
www.amazon.com.         1800    IN      CNAME   www.cdn.amazon.com.
www.cdn.amazon.com.     300     IN      CNAME   d3ag4hukkh62yn.cloudfront.net.
d3ag4hukkh62yn.cloudfront.net. 60 IN    A       52.85.147.120
d3ag4hukkh62yn.cloudfront.net. 60 IN    A       52.85.147.50
d3ag4hukkh62yn.cloudfront.net. 60 IN    A       52.85.147.92
d3ag4hukkh62yn.cloudfront.net. 60 IN    A       52.85.147.109

;; AUTHORITY SECTION:
d3ag4hukkh62yn.cloudfront.net. 1831 IN  NS      ns-1144.awsdns-15.org.
d3ag4hukkh62yn.cloudfront.net. 1831 IN  NS      ns-130.awsdns-16.com.
d3ag4hukkh62yn.cloudfront.net. 1831 IN  NS      ns-2021.awsdns-60.co.uk.
d3ag4hukkh62yn.cloudfront.net. 1831 IN  NS      ns-824.awsdns-39.net.

;; Query time: 3857 msec
;; SERVER: 192.168.0.203#53(192.168.0.203)
;; WHEN: Mon Mar 13 09:18:30 EDT 2017
;; MSG SIZE  rcvd: 306

列表 5:对 www.amazon.com 的查找结果包含一些有趣的信息,包括各种记录类型的生存时间。

当我这样做时,第一次调用以解析 Amazon 的外部地址花费了 3857 毫秒,同时数据被定位并返回。后续执行相同查询的结果为 1 毫秒,这显示了在本地缓存解析器结果的优势。请注意答案部分行中的数字 1800、300 和 60 以及授权部分行中的 1831 - 这些是以秒为单位的 TTL(生存时间)。如果您多次执行查找,这些数字将会更改,显示记录在本地缓存中剩余的生存时间。

创建反向区域文件

域的反向区域将提供执行反向查找的能力。许多组织内部不执行这些操作,但反向查找对于确定问题可能很有用。许多反垃圾邮件配置(例如 SpamAssassin)会查找反向查找以验证有效的电子邮件服务器。

创建反向区域文件 /var/named/example.com.rev 并添加以下内容。请务必使用适当的序列号。

; Authoritative data for example.com  reverse zone
;
$TTL 1D
@   IN SOA  test1.example.com   root.test1.example.com. (
                                        2017031501      ; serial
                                        1D              ; refresh
                                        1H              ; retry
                                        1W              ; expire
                                        3H )            ; minimum

@       IN      NS      epc.example.com.
example.com.    IN      NS      epc.example.com.
1               IN      PTR     mail.example.com.
1               IN      PTR     server.example.com.
21              IN      PTR     test1.example.com.
22              IN      PTR     test2.example.com.
23              IN      PTR     test3.example.com.
24              IN      PTR     test4.example.com.

列表 6:将此反向区域文件 example.com.rev 用于您的名称服务器。

您也可以将反向区域文件命名为 /var/named/25.168.192.in-addr.arpa,这遵循了较旧的约定。您实际上可以将其命名为任何您想要的名称,因为您将在 named.conf 文件中显式指向它,但使用这两个约定之一将使其他人更容易遵循您的工作。

将反向区域添加到 named.conf

zone    "25.168.192.in-addr.arpa" IN {
       type master;
       file "example.com.rev";
};

列表 7:将此节添加到 named.conf 文件将启用反向查找。

将列表 7 中的节添加到 /etc/named.conf 文件以指向新的反向区域。现在重新加载 named 并使用列表 8 中的命令测试您的反向区域。您的结果应类似于下面的结果。

​systemctl reload named

# dig -x 192.168.25.23

; <<>> DiG 9.10.4-P6-RedHat-9.10.4-4.P6.fc25 <<>> -x 192.168.25.23
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48607
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;23.25.168.192.in-addr.arpa.    IN      PTR

;; ANSWER SECTION:
23.25.168.192.in-addr.arpa. 86400 IN    PTR     test3.example.com.

;; AUTHORITY SECTION:
25.168.192.in-addr.arpa. 86400  IN      NS      epc.example.com.

;; Query time: 21 msec
;; SERVER: 192.168.0.203#53(192.168.0.203)
;; WHEN: Wed Mar 15 16:18:59 EDT 2017
;; MSG SIZE  rcvd: 112

列表 8:重新启动 named 后,当您对反向区域中的 IP 地址执行反向查找时,您应该看到类似于这些的结果。

请务必测试网络中的其他一些反向条目,并尝试以下操作以及您想要实验的其他反向查找。-x 选项表示反向查找。

dig -x 192.168.25.23
dig -x 192.168.25.1

请注意,并非正向区域中具有条目的所有主机都需要在反向区域中具有条目,但如果它们这样做,结果会更一致。

至此,您已经有了一个使用 BIND 的工作名称服务器。但是,外部主机尚无法使用此名称服务器,因为防火墙尚不应配置为允许 DNS 请求。

为 DNS 配置 IPTables

如果您希望本地网络上的其他主机将您的主机用作其名称服务器,则可以执行此步骤。

测试主机上的防火墙可能会阻止访问您的主机以进行名称服务。必须配置 IPTables 以允许 UDP(用户数据报协议)数据包在您的名称服务器上入站,以便其他主机可以使用它进行名称解析。使用以下命令添加所需的条目并保存它们。

使用 firewalld 或 IPTables 向您的防火墙添加规则,该规则允许端口 53(域)上用于 UDP 的传入数据包,并保存新的规则集。请务必在 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 行之后插入新规则,因此您必须计算过滤器表中 INPUT 行的数量才能执行此操作。以下命令中的数字 7 表示此规则将插入到现有 INPUT 规则中的位置编号 7。

iptables -t filter -I INPUT 7 -p udp -m conntrack --ctstate NEW -m udp --dport 53 -j ACCEPT

如果您愿意,可以保存新的防火墙规则,如果这是一个永久安装而不是实验室项目,您会这样做。然后使用下面列表 9 中的命令从您的其他主机之一进行测试。@epc 参数告诉 dig 命令使用主机名 epc 指定的名称服务器。您应该替换为您刚刚创建的 DNS 服务器的 IP 地址,或者网络上指向您的新名称服务器的可解析主机名。当然,您始终可以将该主机名及其 IP 地址添加到用于远程测试的主机的 /etc/hosts 文件中。

# dig @epc test1.example.com

; <<>> DiG 9.10.4-P6-RedHat-9.10.4-4.P6.fc25 <<>> @epc test1.example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27957
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;test1.example.com.             IN      A

;; ANSWER SECTION:
test1.example.com.      86400   IN      A       192.168.25.21

;; AUTHORITY SECTION:
example.com.            86400   IN      NS      epc.both.org.

;; Query time: 0 msec
;; SERVER: 192.168.0.203#53(192.168.0.203)
;; WHEN: Mon Mar 13 08:45:34 EDT 2017
;; MSG SIZE  rcvd: 92

列表 9:从同一网络上的不同主机测试您创建的名称解析器。

清理

对于清理,您应该使用适合您的发行版的工具执行以下任务。如果您还没有名称服务器,您可能只想为您的网络保留此名称服务器。

  1. 恢复原始的 /etc/hosts 文件。
  2. 在用于此实验室项目的解析器主机上停止 named。
  3. 禁用 named 服务。
  4. 删除区域文件。
  5. 恢复原始的 named.conf 文件。
  6. 恢复原始的 resolv.conf 文件。

最终想法

在我实际使用 BIND 为我的网络创建名称服务器之前,名称服务的功能对我来说似乎非常晦涩难懂。它非常简单,可以提高 DNS 查找性能。拥有您自己的名称服务器还可以防止许多由维护不善的 ISP 名称服务器引起的相对较小但令人讨厌的名称服务中断。

请注意,即使我的小型 EeePC 以 100% 的 CPU 使用率运行 Seti@Home,它对解析器请求的响应速度也非常快。您应该能够在您拥有的任何 Linux 主机上尝试此项目,影响微乎其微。我希望你们中的许多人会尝试设置自己的名称服务器并进行实验。您的名称服务器安装的具体细节将取决于您的主机和网络的详细信息。

资源

David Both
David Both 是一位开源软件和 GNU/Linux 倡导者、培训师、作家和演讲者。自 1996 年以来,他一直从事 Linux 和开源软件工作,自 1969 年以来一直从事计算机工作。他是“系统管理员 Linux 哲学”的坚定支持者和传播者。

5 条评论

很棒的文章。这应该是初出茅庐的系统管理员的必读之物。

对于简单的部署,dnsmasq 是一个更方便的解决方案。

为什么您不也为 TCP 打开端口 53(域)?这是必需的。

UDP 是 DNS 的主要协议。但是来自维基百科
======
协议传输
DNS 主要在端口号 53 上使用用户数据报协议 (UDP) 来服务请求。[3] DNS 查询由来自客户端的单个 UDP 请求和来自服务器的单个 UDP 答复组成。当响应数据大小超过 512 字节时,或者对于区域传输等任务,将使用传输控制协议 (TCP)。某些解析器实现对所有查询都使用 TCP。
======
显然,一些名称解析器和 ISP 使用 TCP 但不使用 UDP。所以,是的,我可以打开端口 53 上的 TCP,但我选择不为这个相对简单的例子这样做。

感谢您指出这一点。

回复 作者 CertDepot (未验证)

© . All rights reserved.