使用 BIND9 构建小型 DNS

来自 Alpine Linux

本文档展示了如何在 Alpine Linux 上配置 ISC DNS 服务器 BIND9 的基本安装。当您想要为您的家庭或家庭办公室网络设置 DNS 服务器时,这将非常有用。 这些说明从基本的缓存、转发 DNS 服务器开始。它继续添加您的 LAN 主机的查找区域。最后,它简要介绍了如何设置广告拦截。您可以根据您的 DNS 需求,完成尽可能多或尽可能少的操作。

应该注意的是,本文档侧重于防火墙后受信任网络的快速部署和易用性。 请勿在允许来自互联网的 DNS 查询的主机上部署此配置。

安装软件包

通常的 Alpine apk 安装方法可以用于安装 bind9。 这将安装 named DNS 服务器以及 nslookup 和其他实用程序。

# apk update
# apk add bind

配置为转发 DNS 服务器

当配置为转发服务器时,本地 DNS 服务器将缓存查询回复的结果。 未在缓存中找到的查询将转发到公共 DNS 服务器(或您的 ISP)。

下面的示例使用公共 DNS 服务器 1.1.1.1 和 8.8.8.8。 您可以替换为您 ISP 的 DNS 服务器或任何其他受信任的 DNS 服务器。

# cd /etc/bind

# cat << EOF > named.conf

options {
    directory "/var/bind";

    listen-on { any; };
    listen-on-v6 { none; };

    allow-query { any; };

    dnssec-validation no;

    forwarders {
        1.1.1.1;
        8.8.8.8;
    };

    recursion yes;
};
EOF

编写配置后,运行 named-checkconf 以验证其是否正确。 在继续之前修复任何错误。

启动 DNS 服务器

# service named start
# rc-update add named

本地测试查询

首先,在您的 Alpine 主机上运行 nslookup,并将服务器设置为您的 Alpine 主机的 IP 地址。 然后,查询一些互联网 DNS 名称和 IP 地址。 您应该在回复中看到 IP 地址和域名。

如果您看到错误,例如 ** server can’t find example.com: NXDOMAIN,请检查 named.conf 中的配置。

这是一个成功测试的示例。

$ nslookup
> server 192.168.1.100
Default server: 192.168.1.100
Address: 192.168.1.100#53

> example.com
Server:         192.168.1.100
Address:        192.168.1.100#53

Non-authoritative answer:
Name:   example.com
Address: 23.215.0.136

> 1.1.1.1
1.1.1.1.in-addr.arpa    name = one.one.one.one.

注意:为了简洁起见,输出已被截断。

如果测试成功,您将需要配置您主机的 /etc/resolv.conf 以使用其自身的 IP 地址进行 DNS 查找。

从 LAN 客户端测试查询

重复测试,但从您网络上的另一台机器进行。 务必为 nslookup 服务器使用 Alpine 主机的 IP 地址。

如果您看到类似 *** [192.168.1.100] can’t find example.com: Query refused 的错误,请检查您的 named.conf。 验证是否有 recursion yes; 行。

这是一个 Windows 客户端上成功测试的示例。

C:\> nslookup
> server 192.168.1.100

> example.com
Server:  [192.168.1.100]
Address:  192.168.1.100

Non-authoritative answer:
Name:    example.com
Addresses:  2600:1406:bc00:53::b81e:94ce
          23.215.0.136

注意:为了简洁起见,输出已被截断。

如果测试成功,您可以配置您的 DHCP 服务器以使用 Alpine 主机的 IP 地址作为主 DNS。

可选:添加 LAN 主机

到目前为止,只能查询知名的互联网主机。 有时,让您自己网络上的主机也可以在 DNS 中使用会很有用。 这需要设置区域文件。

创建区域文件比到目前为止的配置稍微复杂一些,但并非无法克服。 互联网上可以找到许多区域文件的示例,包括 BIND9 文档Wikipedia 文章 以及 另一个 Alpine Wiki DNS 指南。 所有这些都可以用作参考。

创建区域文件

下面的示例适用于使用保留的私有顶级域名 .home 的简单家庭网络。 文件的上半部分包含有关域名本身的详细信息。 下半部分是列出各个主机及其地址的地方。 您需要根据您的网络配置调整名称和 IP 地址。

# mkdir /etc/bind/zones

# chown named /etc/bind/zones

# cat << EOF > /etc/bind/zones/home

$TTL 3600
@       IN  SOA   ns1.home.  root.home. (
                                      1    ; Serial - increment after modifying
                                 604800    ; Refresh
                                  86400    ; Retry
                                2419200    ; Expire
                                 604800 )  ; Negative Cache TTL
;

@       IN  NS    ns1
@       IN  A     192.168.1.1
router  IN  A     192.168.1.1
ns1     IN  A     192.168.1.100
alpine  IN  A     192.168.1.100
media   IN  A     192.168.1.101
EOF

务必使用 named-checkzone 检查文件,并在继续之前修复任何错误。 位置参数是区域名称文件名

# named-checkzone home /etc/bind/zone/home
zone home/IN: loaded serial 1
OK

如果您在输出中遇到错误,则会包含行号,这将帮助您追踪到错误。

在 named.conf 中引用区域文件

编辑 /etc/bind/named.conf 并附加以下行

zone "home" {
    type primary;
    file "/etc/bind/zones/home";
};

使用命令验证配置:named-checkconf。 在继续之前修复任何错误。

通知 DNS 服务器新的配置

使用通常的 Alpine service 命令重新加载配置。

service named reload

如果出现错误,请使用 named-checkconf 和 named-checkzone 命令来帮助缩小原因范围。

进行一些测试查询

作为最后的检查,重新访问使用 nslookup 的测试,这些测试用于验证转发 DNS 服务器。 这次,除了查找互联网主机之外,还可以尝试查询您区域文件中的主机。

这是一个成功测试的示例。

$ nslookup
> server 192.168.1.100
Default server: 192.168.1.100
Address: 192.168.1.100#53

> example.com
Server:         192.168.1.100
Address:        192.168.1.100#53

Non-authoritative answer:
Name:   example.com
Address: 23.215.0.136

> router.home
Server:         192.168.1.100
Address:        192.168.1.100#53

Name:   router.home
Address: 192.168.1.1

注意:为了简洁起见,输出已被截断。

为 localhost 添加区域

为了使配置完整,应该为 localhost 名称设置一个区域,以便 DNS 服务器在被查询时返回熟悉的 127.0.0.1 地址。 当查询 IP 地址 127.0.0.1 时,DNS 服务器也应响应 localhost

创建正向查找区域的过程与创建 home 区域的过程相同。 此步骤中的新内容是反向查找区域的概念。 这仅仅是 DNS 服务器在被询问 IP 地址时返回名称。

以下是步骤

  1. 创建区域文件
  2. 在 named.conf 中引用区域
  3. 重新加载配置

不要忘记在进行过程中使用 named-checkzone、named-checkconf 和 nslookup 进行测试。

创建正向查找区域文件

localhost 的区域文件非常简单,只有一个 A 记录。 下面显示了一个示例。 创建一个新文件,路径为 /etc/bind/zones/localhost,并将示例的内容复制到其中。

$TTL 3600
@       IN  SOA   localhost.  root.localhost. (
                                            1    ; Serial - increment after modifying
                                       604800    ; Refresh
                                        86400    ; Retry
                                      2419200    ; Expire
                                       604800 )  ; Negative Cache TTL
;

@       IN  NS    localhost.
@       IN  A     127.0.0.1

创建反向查找区域文件

反向查找区域文件与正向查找几乎相同,但在最后一行具有 PTR 记录而不是 A 记录。 创建一个新文件,路径为 /etc/bind/zones/1.0.0.127.in-addr.arpa,并将以下内容复制到其中。

$TTL 3600
@       IN  SOA   localhost.  root.localhost. (
                                            1    ; Serial - increment after modifying
                                       604800    ; Refresh
                                        86400    ; Retry
                                      2419200    ; Expire
                                       604800 )  ; Negative Cache TTL
;

@       IN  NS    localhost.
1       IN  PTR   localhost.     

该文件(以及区域本身)的相当奇怪的命名约定只是反向区域的 IP 地址,其八位字节顺序相反,并在末尾添加了后缀 .in-addr.arpa。 您实际上可以随意命名它,只要它与 named.conf 中的配置匹配即可。 一些示例将使用 localhost.rev 作为反向查找文件名。

在 named.conf 中引用区域文件

使用 named-checkzone 检查新区域文件后,在 named.conf 文件中附加对它们的引用。 要添加的配置如下所示。

zone "localhost" {
    type primary;
    file "/etc/bind/zones/localhost";
};

zone "1.0.0.127.in-addr.arpa" {
    type primary;
    file "/etc/bind/zones/1.0.0.127.in-addr.arpa";
};

如果 named-checkconf 没有引发任何错误,则下一步是使用 service named reload 重新加载配置

LAN 主机的反向查找区域

如果您为本地网络上的主机创建了区域文件,则应创建一个反向查找区域以使其完整。 该过程与创建 localhost 反向查找区域非常相似。 一种快捷方法是将正向查找区域文件复制到 LAN IP 的新文件名,然后将 A 记录替换为相应的 PTR 记录。

按照正向查找中给出的示例,反向区域将如下所示。

$TTL 3600
@       IN  SOA   ns1.home.  root.home. (
                                      1    ; Serial - increment after modifying
                                 604800    ; Refresh
                                  86400    ; Retry
                                2419200    ; Expire
                                 604800 )  ; Negative Cache TTL
;

@       IN  NS    ns1
@       IN  A     192.168.1.1
router  IN  A     192.168.1.1
ns1     IN  A     192.168.1.100
alpine  IN  A     192.168.1.100
media   IN  A     192.168.1.101

LAN 主机的持续维护

当为自己的网络主机使用 DNS 时,在添加或删除主机时需要记住以下几个步骤。

  1. 增加区域文件上的序列号。
  2. 使用 named-checkzone 测试区域文件
  3. 使用 named-checkconf 测试配置
  4. 重新加载 named 服务以使更改生效。

阻止广告

BIND9 的响应策略区 (RPZ) 功能可以轻松阻止对不需要的域的访问,方法是返回域未找到响应而不是 IP 地址。 需要三个步骤才能使其工作。

  1. 在 named.conf 的 options 部分中启用 RPZ 功能
  2. 创建一个区域文件,列出不需要的域。
  3. 在 named.conf 中引用区域文件

在 named.conf 选项中启用 RPZ

下面是到目前为止所有示例中使用的 named.conf 的 options 部分,但添加了响应策略区。 RPZ 的新行出现在 recursion yes; 指令之后。 为了简洁起见,省略了 named.conf 的其余部分。

options {
    directory "/var/bind";

    listen-on { any; };
    listen-on-v6 { none; };

    dnssec-validation no;

    forwarders {
        1.1.1.1;
        8.8.8.8;
    };

    recursion yes;

    response-policy {
        zone "rpz";
    };
};

进行更改后,运行 named-checkconf 以确保文件没有问题。

创建 RPZ 文件

RPZ 区域文件看起来很像常规区域文件。 快速创建它的方法之一是首先复制 localhost 区域文件,然后附加要阻止的主机。

例如

# cd /etc/bind/zones

# cp localhost rpz

# cat << EOF >> rpz
example.com    CNAME .
*.example.com  CNAME .
EOF

CNAME . 记录指示 BIND9 在查询列出的域时返回 NXDOMAIN(域未找到)响应。 您可能不想阻止 example.com,但它对于演示目的非常有效。

通过运行 named-checkzone rpz /etc/bind/zone/rpz 检查文件是否有错误,并在继续下一步之前修复任何错误。

在 named.conf 中引用 RPZ 文件

就像添加 localhost 和 LAN 主机区域的说明一样,添加 RPZ 区域文件也需要在 named.conf 中附加几行,并在重新加载服务之前运行 named-checkconf。

现在您应该熟悉新区域的格式了。 它看起来像下面显示的那样。

zone "rpz" {
    type primary;
    file "/etc/bind/zones/rpz";
};

在将其附加到 named.conf 后,请务必运行 named-checkconf。 然后使用 service named reload 重新加载配置

测试 RPZ 阻止

要进行测试,请像之前测试转发配置、LAN 主机等时一样使用 nslookup。 只是这次,您希望看到错误消息。

下面是一个示例,显示了阻止 example.com 的成功配置。

$ nslookup
> example.com
Server:         192.168.1.100
Address:        192.168.1.100#53

** server can't find example.com: NXDOMAIN

继续测试一些其他应该被允许的域,以确保它是被 RPZ 策略阻止,而不是因为服务器配置错误。

维护 RPZ 文件

手动将阻止的域添加到 RPZ 区域文件可能很快变得乏味,但通过这个涉及 example.com 的简单测试,您可以看到它是如何完成的。 互联网上有一些人策划和维护阻止列表。 其中一个来源是 https://github.com/hagezi/dns-blocklists

要使用广告拦截 RPZ,您需要执行以下步骤

  1. 从源位置下载文件。
  2. 使用 named-checkzone 检查文件的有效性
  3. 将现有的 /etc/bind/zones/rpz 文件替换为下载的文件。
  4. 通过运行 service named reload 重新加载配置

新的广告域名随时出现。 诀窍是在新的阻止列表发布时自动下载它们。 下面的 shell 脚本可以提供帮助。

#! /bin/sh

cd /etc/bind/zones || exit 1
curl -Os https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/multi.txt || exit 2
named-checkzone rpz ./multi.txt || exit 3
cp rpz rpz~
mv multi.txt rpz
service named reload

后续步骤

本文档已引导您了解在 Alpine 服务器上设置 BIND9 的基础知识。 还有许多其他未涵盖的功能。 一些有趣的功能包括

  • 通配符子域名
  • IPv6 域名
  • 辅助 DNS 服务器
  • DNSSEC

您可以自行选择要继续学习的内容。 有关更多信息,请参阅 BIND9 文档