# 如何在Ubuntu 16.04上配置绑定为缓存或转发DNS服务器 ###

2018-09-25 10:23:37 浏览数 (1)

介绍

在学习如何配置网站和服务器时,DNS或域名系统通常是一个难以实现的组件。虽然大多数人可能会选择使用其托管公司或其域名注册商提供的DNS服务器,但创建自己的DNS服务器有一些优势。

在本指南中,我们将讨论如何在Ubuntu 16.04计算机上安装和配置Bind9 DNS服务器作为缓存或转发DNS服务器。这两种配置在服务机器网络时都具有优势。

要完成本教程,你需要具备一台已经设置好可以使用sudo命令的非root账号的Ubuntu服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。

准备和目标

要完成本指南,您首先需要熟悉一些常见的DNS术语。

我们将演示两个实现类似目标的独立配置:缓存和转发DNS服务器。

要继续,您需要访问两台计算机(其中至少一台应该是Ubuntu 16.04服务器)。一个将作为客户端,另一个将配置为DNS服务器。使服务器进入良好的初步状态。

我们的示例配置的详细信息如下:

角色

IP地址

DNS服务器

192.0.2.2

客户

192.0.2.100

我们将向您展示如何配置客户端计算机以使用DNS服务器进行查询。我们将根据您的需要向您展示如何以两种不同的配置配置DNS服务器。

缓存DNS服务器

第一个配置是用于缓存 DNS服务器。这种类型的服务器也称为解析器,因为它处理递归查询,并且通常可以处理从其他服务器跟踪DNS数据的繁重工作。

当缓存DNS服务器跟踪客户端查询的答案时,它会将答案返回给客户端。但是它也在记录的TTL值允许的时间内将答案存储在它的缓存中。然后可以将高速缓存用作后续请求的源,以便加速总往返时间。

您在网络配置中可能拥有的几乎所有DNS服务器都将缓存DNS服务器。这些弥补了大多数客户端计算机上缺少足够的DNS解析器库的缺陷。对于许多情况,缓存DNS服务器是一个不错的选择。如果您不希望依赖您的ISP DNS或其他公共可用的DNS服务器,那么制作您自己的缓存服务器是一个不错的选择。如果它与客户端计算机的物理距离很近,则很可能会改善DNS查询时间。

转发DNS服务器

我们将演示的第二个配置是转发 DNS服务器。从客户端的角度来看,转发DNS服务器看起来与缓存服务器几乎完全相同,但机制和工作负载却截然不同。

转发DNS服务器提供相同的优势,即维护缓存以改善客户端的DNS解析时间。但是,它实际上没有执行任何递归查询。相反,它将所有请求转发到外部解析服务器,然后缓存结果以用于以后的查询。

这使转发服务器可以从其缓存中进行响应,同时不要求它执行递归查询的所有工作。这允许服务器仅发出单个请求(转发的客户端请求),而不必经历整个递归例程。在外部带宽传输成本高昂,可能需要经常更改缓存服务器,或者希望将本地查询转发到一台服务器以及将外部查询转发到另一台服务器的环境中,这可能是一个优势。

在DNS服务器上安装绑定

无论您希望使用哪种配置选项,实现绑定DNS服务器的第一步是安装实际的软件。

Bind软件在Ubuntu的默认存储库中可用,因此我们只需更新本地软件包索引并使用apt安装软件。我们还将包括文档和一些常用实用程序:

代码语言:javascript复制
sudo apt-get update
sudo apt-get install bind9 bind9utils bind9-doc

现在已经安装了Bind组件,我们可以开始配置服务器了。转发服务器将使用缓存服务器配置作为跳转点,因此无论您的最终目标如何,首先将服务器配置为缓存服务器。

配置为缓存DNS服务器

首先,我们将介绍如何配置Bind以充当缓存DNS服务器。当客户端发出查询时,此配置将强制服务器以递归方式从其他DNS服务器寻求答案。这意味着它正在进行查询每个相关DNS服务器的工作,直到它找到整个响应。

Bind配置文件默认保存在/etc/bind目录中。立即进入该目录:

代码语言:javascript复制
cd /etc/bind

我们不会关心此目录中的大多数文件。主配置文件名为named.confnamedbind是同一应用程序的两个名称)。此文件只是简单的提供named.conf.options文件,named.conf.local文件和named.conf.default-zones文件。

对于缓存DNS服务器,我们只会修改named.conf.options文件。使用sudo权限在文本编辑器中打开它:

代码语言:javascript复制
sudo nano named.conf.options

删除评论以便于阅读,文件如下所示:

代码语言:javascript复制
options {
        directory "/var/cache/bind";
​
        dnssec-validation auto;
​
        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { any; };
};

要配置缓存,第一步是设置访问控制列表或ACL。

作为将用于解决递归查询的DNS服务器,我们不希望恶意用户滥用DNS服务器。称为DNS放大攻击的攻击尤其麻烦,因为它可能导致您的服务器参与分布式拒绝服务攻击。

DNS放大攻击是恶意用户试图关闭互联网上的服务器或站点的一种方式。为此,他们尝试查找将解析递归查询的公共DNS服务器。他们欺骗受害者的IP地址并发送一个查询,该查询将向DNS服务器返回大量响应。在这样做时,DNS服务器响应具有针对受害者服务器的大有效负载的小请求,有效地放大攻击者的可用带宽。

托管公共递归DNS服务器需要大量特殊配置和管理。为避免将服务器用于恶意目的,我们将配置一个我们信任的IP地址或网络范围列表。

options块上方,我们将创建一个名为的新块acl。为要配置的ACL组创建标签。在本指南中,我们将致电该集团的客户

代码语言:javascript复制
acl goodclients {
};
​
options {
    . . .

在此块中,列出应允许使用此DNS服务器的IP地址或网络。由于我们的服务器和客户端都在我们示例中的同一/ 24子网内运行,因此我们将示例限制在此网络中。您应该调整此选项以包括您自己的客户,而不包括外部各方。我们还将添加localhostlocalnets,他们将尝试自动执行此操作:

代码语言:javascript复制
acl goodclients {
    192.0.2.0/24;
    localhost;
    localnets;
};
​
options {
    . . .

现在我们有一个我们想要解析请求的客户端ACL,我们可以在options块中配置这些功能。在此块中,添加以下行:

代码语言:javascript复制
. . .
​
options {
    directory "/var/cache/bind";
​
    recursion yes;
    allow-query { goodclients; };
    . . .

我们明确地启用了递归,然后配置allow-query参数以使用我们的ACL规范。我们可以使用不同的参数,比如allow-recursion来引用我们的ACL组。如果存在并且递归,allow-recursion则将指示可以使用递归服务的客户端列表。

但是,如果allow-recursion未设置,则Bind将返回allow-query-cache列表,然后是allow-query列表,最后只会回到默认值localnetslocalhost。由于我们正在配置仅缓存服务器(它没有自己的权威区域并且不转发请求),因此allow-query列表将始终仅适用于递归。我们正在使用它,因为它是指定ACL的最常用方法。

完成这些更改后,保存并关闭该文件。

这实际上是缓存DNS服务器所需的全部内容。如果您确定这是您希望使用的服务器类型,请随时跳过以了解如何检查配置文件,重新启动服务以及实现客户端配置。

否则,请继续阅读以了解如何设置转发DNS服务器。

配置为转发DNS服务器

如果转发DNS服务器更适合您的基础架构,我们可以轻松地设置它。

我们将从缓存服务器配置中的配置开始。named.conf.options文件应如下所示:

代码语言:javascript复制
acl goodclients {
        192.0.2.0/24;
        localhost;
        localnets;
};
​
options {
        directory "/var/cache/bind";
​
        recursion yes;
        allow-query { goodclients; };
​
        dnssec-validation auto;
​
        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { any; };
};

我们将使用相同的ACL列表将DNS服务器限制为特定的客户端列表。但是,我们需要更改配置,以便服务器不再尝试自己执行递归查询。

要做到这一点,我们就不会改变recursion到没有。转发服务器仍然通过回答对其不具有权威性的区域的查询来提供递归服务。相反,我们需要设置一个缓存服务器列表来转发我们的请求。

这将在options {}块内完成。首先,我们在被调用的内部创建一个块forwarders,其中包含我们要转发请求的递归名称服务器的IP地址。在我们的指南中,我们将使用Google的公共DNS服务器(8.8.8.88.8.4.4):

代码语言:javascript复制
. . .
​
options {
        directory "/var/cache/bind";
​
        recursion yes;
        allow-query { goodclients; };
​
        forwarders {
                8.8.8.8;
                8.8.4.4;
        };
        . . .

之后,我们应该将forward指令设置为“only”,因为此服务器将转发所有请求,并且不应尝试自行解析请求。

完成后,配置文件将如下所示:

代码语言:javascript复制
. . .
​
options {
        directory "/var/cache/bind";
​
        recursion yes;
        allow-query { goodclients; };
​
        forwarders {
                8.8.8.8;
                8.8.4.4;
        };
        forward only;
​
        dnssec-validation auto;
​
        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { any; };
};

我们应该做的最后一个改变是dnssec参数。使用当前配置,根据转发的DNS服务器的配置,您可能会在日志中看到一些如下所示的错误:

代码语言:javascript复制
Jun 25 15:03:29 cache named[2512]: error (chase DS servers) resolving 'in-addr.arpa/DS/IN': 8.8.8.8#53
Jun 25 15:03:29 cache named[2512]: error (no valid DS) resolving '111.111.111.111.in-addr.arpa/PTR/IN': 8.8.4.4#53

要避免这种情况,请将dnssec-validation设置更改为“yes”并显式启用dnssec:

代码语言:javascript复制
. . .
​
forward only;
​
dnssec-enable yes;
dnssec-validation yes;
​
auth-nxdomain no;    # conform to RFC1035
. . .

完成后保存并关闭文件。您现在应该有一个转发DNS服务器。继续下一部分以验证配置文件并重新启动守护程序。

测试配置并重新启动绑定

现在您已将Bind服务器配置为缓存DNS服务器或转发DNS服务器,我们已准备好实施我们的更改。

在我们采用插件并在我们的系统上重新启动Bind服务器之前,我们应该使用Bind的附带工具来检查配置文件的语法。

我们可以通过输入以下内容轻松完成:

代码语言:javascript复制
sudo named-checkconf

如果配置中没有语法错误,则shell提示将立即返回,而不显示任何输出。

如果配置文件中存在语法错误,则会向您发出错误和行号的警报。如果发生这种情况,请返回并检查文件是否有错误。

验证配置文件没有任何语法错误后,重新启动Bind守护程序以实现更改:

代码语言:javascript复制
sudo systemctl restart bind9

如果您按照初始服务器设置指南进行操作,则会在您的服务器上启用UFW防火墙。我们需要允许DNS流量到我们的服务器以响应客户端请求。

通过键入以下内容为Bind的防火墙策略启用例外:

代码语言:javascript复制
sudo ufw allow Bind9

然后,在设置客户端计算机时,请密切关注服务器日志,以确保一切顺利进行。让它在服务器上运行:

代码语言:javascript复制
sudo journalctl -u bind9 -f

现在,打开一个新的终端窗口来配置客户端计算机。

配置客户端计算机

现在您已启动并运行服务器,您可以将客户端计算机配置为使用此DNS服务器进行查询。

登录到您的客户端计算机。确保在您为DNS服务器设置的ACL组中指定了您正在使用的客户端。否则,DNS服务器将拒绝为客户端提供请求。

我们需要编辑/etc/resolv.conf文件以将服务器指向名称服务器。此处所做的更改将持续到重新启动,这非常适合测试。如果我们对测试结果感到满意,我们可以将这些更改永久化。

在文本编辑器中使用sudo权限打开文件:

代码语言:javascript复制
sudo nano /etc/resolv.conf

该文件将列出用于通过设置nameserver指令来解析查询的DNS服务器。注释掉所有当前条目并添加指向DNS服务器的行nameserver

代码语言:javascript复制
nameserver 192.0.2.2
# nameserver 8.8.4.4
# nameserver 8.8.8.8
# nameserver 209.244.0.3

保存并关闭文件。

现在,您可以通过使用一些常用工具进行测试以确保查询可以正确解析。

您可以用ping来测试可以对域进行的连接:

代码语言:javascript复制
ping -c 1 google.com
代码语言:javascript复制
Output
PING google.com (173.194.33.1) 56(84) bytes of data.
64 bytes from sea09s01-in-f1.1e100.net (173.194.33.1): icmp_seq=1 ttl=55 time=63.8 ms
​
--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 63.807/63.807/63.807/0.000 ms

这意味着我们的客户端可以使用我们的DNS服务器连接google.com

我们可以使用dig等DNS特定工具获取更详细的信息。这次尝试使用其他域名:

代码语言:javascript复制
dig linuxfoundation.org
代码语言:javascript复制
Output
; <<>> DiG 9.9.5-3-Ubuntu <<>> linuxfoundation.org
;; global options:  cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35417
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
​
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;linuxfoundation.org.       IN  A
​
;; ANSWER SECTION:
linuxfoundation.org.    6017    IN  A   140.211.169.4
​
;; Query time: 36 msec
;; SERVER: 192.0.2.2#53(192.0.2.2)
;; WHEN: Wed Jun 25 15:45:57 EDT 2014
;; MSG SIZE  rcvd: 64

您可以看到查询花了36毫秒。如果我们再次发出请求,服务器应该从其缓存中提取数据,从而减少响应时间:

代码语言:javascript复制
dig linuxfoundation.org
代码语言:javascript复制
Output
; <<>> DiG 9.9.5-3-Ubuntu <<>> linuxfoundation.org
;; global options:  cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18275
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
​
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;linuxfoundation.org.       IN  A
​
;; ANSWER SECTION:
linuxfoundation.org.    6012    IN  A   140.211.169.4
​
;; Query time: 1 msec
;; SERVER: 192.0.2.2#53(192.0.2.2)
;; WHEN: Wed Jun 25 15:46:02 EDT 2014
;; MSG SIZE  rcvd: 64

如您所见,缓存的响应速度明显加快。

我们还可以使用我们在dig -x选项中建立的IP地址(在我们的例子中的140.211.169.4)测试反向查找:

代码语言:javascript复制
dig -x 140.211.169.4
代码语言:javascript复制
Output
; <<>> DiG 9.9.5-3-Ubuntu <<>> -x 140.211.169.4
;; global options:  cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61516
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
​
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;4.169.211.140.in-addr.arpa.    IN  PTR
​
;; ANSWER SECTION:
4.169.211.140.in-addr.arpa. 3402 IN CNAME   4.0-63.169.211.140.in-addr.arpa.
4.0-63.169.211.140.in-addr.arpa. 998 IN PTR load1a.linux-foundation.org.
​
;; Query time: 31 msec
;; SERVER: 192.0.2.2#53(192.0.2.2)
;; WHEN: Wed Jun 25 15:51:23 EDT 2014
;; MSG SIZE  rcvd: 117

如您所见,反向查找也成功。

回到DNS服务器上,您应该看到在测试期间是否记录了任何错误。可能出现的一个常见错误如下所示:

代码语言:javascript复制
Output from sudo journalctl -u bind9 -f
. . .
Jun 25 13:16:22 cache named[2004]: error (network unreachable) resolving 'ns4.apnic.net/A/IN': 2001:dc0:4001:1:0:1836:0:140#53
Jun 25 13:16:22 cache named[2004]: error (network unreachable) resolving 'ns4.apnic.com/A/IN': 2001:503:a83e::2:30#53
Jun 25 13:16:23 cache named[2004]: error (network unreachable) resolving 'sns-pb.isc.org/AAAA/IN': 2001:500:f::1#53
Jun 25 13:16:23 cache named[2004]: error (network unreachable) resolving 'ns3.nic.fr/A/IN': 2a00:d78:0:102:193:176:144:22#53

这些表示服务器正在尝试解析IPv6信息,但服务器未配置IPv6。您可以通过告诉Bind仅使用IPv4来解决此问题。

为此,我们可以修改启动Bind9的systemd单元文件:

代码语言:javascript复制
sudo systemctl edit --full bind9

在显示的文件中,添加-4ExecStart行的末尾以将服务器限制为IPv4请求:

代码语言:javascript复制
[Unit]
Description=BIND Domain Name Server
Documentation=man:named(8)
After=network.target
​
[Service]
ExecStart=/usr/sbin/named -f -u bind -4
ExecReload=/usr/sbin/rndc reload
ExecStop=/usr/sbin/rndc stop
​
[Install]
WantedBy=multi-user.target

完成后保存并关闭文件。

重新加载systemd守护程序以将已更改的单元文件读入init系统:

代码语言:javascript复制
sudo systemctl daemon-reload

重新启动Bind9服务以实现更改:

代码语言:javascript复制
sudo systemctl restart bind9

您不会再次在日志中看到这些错误。

使客户端DNS设置永久化

如前所述,将客户端计算机指向我们的DNS服务器的/etc/resolv.conf设置将无法在重新启动后继续存在。要使更改持续,我们需要修改用于生成此文件的文件。

如果客户端计算机正在运行Debian或Ubuntu,请使用sudo权限打开/etc/network/interfaces文件:

代码语言:javascript复制
sudo nano /etc/network/interfaces

寻找dns-nameservers参数。您可以删除现有条目并将其替换为DNS服务器,或者只添加DNS服务器作为以下选项之一:

代码语言:javascript复制
. . .

iface eth0 inet static
        address 192.168.2.100
        netmask 255.255.255.0
        gateway 192.168.2.1
        dns-nameservers 192.0.2.2

. . .

完成后保存并关闭文件。下次启动时,将应用您的设置。

如果客户端运行CentOS或Fedora,则需要打开/etc/sysconfig/network/network-scripts/ifcfg-eth0文件:

代码语言:javascript复制
sudo nano /etc/sysconfig/network-scripts/ifcfg-eth0

在里面,寻找以它开头的线条DNS。切换DNS1到您的DNS服务器。如果您不想将其他DNS服务器用作后备,请删除其他条目:

代码语言:javascript复制
. . .
DNS1=192.0.2.2
. . .

完成后保存并关闭文件。您的客户端应在下次启动时使用这些设置。

结论

您现在应该配置一个缓存或转发DNS服务器来为您的客户端提供服务。这可以是加速您管理的计算机的DNS查询的好方法。

想要了解更多关于配置绑定为缓存或转发DNS服务器的相关教程,请前往腾讯云 社区学习更多知识。


参考文献:《How To Configure Bind as a Caching or Forwarding DNS Server on Ubuntu 16.04》

0 人点赞