Unbound
Unbound 是一个进行验证、递归和缓存的 DNS 解析器。根据 Wikipedia
- Unbound 已在多个开源项目中取代 Berkeley Internet Name Domain (BIND) 成为系统默认的名称服务器,因为它被认为对于大多数应用而言更小、更现代化且更安全。
安装
此外,#DNSSEC 验证 需要 expat 包。
配置
默认配置文件已包含在 /etc/unbound/unbound.conf 中。以下各节将重点介绍配置文件中的不同设置。有关其他设置和更多详细信息,请参阅 unbound.conf(5)。
除非另有说明,本节中列出的所有选项都应放在配置的 server 部分,如下所示:
/etc/unbound/unbound.conf
server: ... setting: value ...
本地 DNS 服务器
如果您想将 unbound 用作本地 DNS 服务器,请在 /etc/resolv.conf 中将您的名称服务器设置为环回地址 ::1 和 127.0.0.1。
/etc/resolv.conf
nameserver ::1 nameserver 127.0.0.1 options edns0 trust-ad
请确保按照 域名解析#覆盖 /etc/resolv.conf 中的说明保护 /etc/resolv.conf 免遭修改。
/etc/resolvconf.conf。/etc/resolvconf.conf
name_servers="::1 127.0.0.1" resolv_conf_options="edns0 trust-ad"
然后运行 resolvconf -u 来生成 /etc/resolv.conf。
有关如何测试您的设置,请参阅 域名解析#查找工具。
在对 resolv.conf 进行永久性更改后,请专门检查正在使用的服务器是 ::1 或 127.0.0.1。
您现在可以设置 unbound,使其 #转发查询,可能将所有查询转发到您选择的 DNS 服务器。
根提示
为了递归查询未被缓存为地址的主机,解析器需要从服务器树的顶部开始,查询根服务器,以了解在查询地址时,针对顶级域的下一步去向。Unbound 自带默认的内置提示。因此,如果软件包定期更新,则无需手动干预。否则,使用根提示文件是一个好习惯,因为内置提示可能会过时。
首先将 unbound 指向 root.hints 文件。
root-hints: root.hints
然后,将一个 根提示 文件放入 unbound 的配置目录。最简单的方法是运行以下命令:
# curl --output /etc/unbound/root.hints https://www.internic.net/domain/named.cache
当实际使用此文件而不是内置提示时,最好每六个月左右更新一次 root.hints,以确保根服务器列表是最新的。这可以通过手动完成,或使用 systemd 定时器。例如,请参阅 #Roothints systemd 定时器。
DNSSEC 验证
要使用 DNSSEC 验证,服务器信任锚的以下设置应放在 server: 下:
/etc/unbound/unbound.conf
trust-anchor-file: "/etc/unbound/trusted-key.key"
此设置已在默认配置文件中启用。
/etc/unbound/trusted-key.key 从 /etc/trusted-key.key 复制而来,该文件由 dnssec-anchors 依赖项提供,其 PKGBUILD 使用 unbound-anchor(8) 生成该文件。
只有当被查询的 DNS 服务器支持 DNSSEC 时,才会执行 DNSSEC 验证。如果一般的 #转发查询 设置为不支持 DNSSEC 的 DNS 服务器,那么它们的应答,无论是什么,都应被视为不安全的,因为无法执行 DNSSEC 验证。
测试验证
要测试 DNSSEC 是否正常工作,请在 启动 unbound.service 后,执行以下操作:
$ unbound-host -vDr test.dnscheck.tools
应答应包含 IP 地址,并且旁边有 (secure) 字样。
$ unbound-host -vDr badsig.test.dnscheck.tools
此处应答应包含 (BOGUS (security failure))。
-r 以获得正确的应答。否则,所有 rcodes 都将响应 SERVFAIL。此外,您可以使用 drill 来测试解析器,如下所示:
$ drill badsig.test.dnscheck.tools $ drill test.dnscheck.tools
第一个命令应返回 SERVFAIL 的 rcode。第二个命令应返回 NOERROR 的 rcode。
转发查询
如果您只想将查询转发到外部 DNS 服务器,请跳至 #转发所有剩余请求。
允许本地网络使用 DNS
使用 openresolv
如果您的网络管理器支持 openresolv,您可以 配置它 以向 Unbound 提供本地 DNS 服务器和搜索域。
/etc/resolvconf.conf
... private_interfaces="*" # Write out unbound configuration file unbound_conf=/etc/unbound/resolvconf.conf
运行 resolvconf -u 来生成文件。
配置 Unbound 以读取 openresolv 生成的文件,并允许应答 私有 IP 地址范围[1]
/etc/unbound/unbound.conf
include: "/etc/unbound/resolvconf.conf" ... server: ... private-domain: "intranet" private-domain: "internal" private-domain: "private" private-domain: "corp" private-domain: "home" private-domain: "lan" unblock-lan-zones: yes insecure-lan-zones: yes ...
此外,您可能希望禁用私有 DNS 命名空间的 DNSSEC 验证(参见 RFC 6762 附录 G)。
/etc/unbound/unbound.conf
... server: ... domain-insecure: "intranet" domain-insecure: "internal" domain-insecure: "private" domain-insecure: "corp" domain-insecure: "home" domain-insecure: "lan" ...
排除本地子网的应答
这将有助于将本地网络从 DNS 应答中排除,因为它能防御 DNS 重新绑定攻击。默认情况下,此功能未激活,但您可以将任何所需的子网添加到配置文件中。
private-address: local_subnet/subnet_mask
您可以通过这些字符串添加所有 私有和链路本地子网。
private-address: 10.0.0.0/8 private-address: 172.16.0.0/12 private-address: 192.168.0.0/16 private-address: 169.254.0.0/16 private-address: fd00::/8 private-address: fe80::/10
请注意,Unbound 在应答中可能包含来自已排除子网的地址,如果它们属于 private-domain 中的域名或由 local-data 指定,因此您需要像在 #使用 openresolv 中描述的那样定义 private-domain,以便能够查询本地域地址。
包含本地 DNS 服务器
为了同时为本地地址的正向和反向查询包含本地 DNS 服务器,需要一组与下面类似的行,并进行正向和反向查找(通过更改下面行中的 10.0.0.1 来选择提供本地网络 DNS 的服务器的 IP 地址)。
local-zone: "10.in-addr.arpa." transparent
上面的这行对于正确处理反向查找很重要。
forward-zone: name: "mynetwork.com." forward-addr: 10.0.0.1
forward-zone: name: "10.in-addr.arpa." forward-addr: 10.0.0.1
您可以使用以下行设置 localhost 的正向和反向查找。
local-zone: "localhost." static local-data: "localhost. 10800 IN NS localhost." local-data: "localhost. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800" local-data: "localhost. 10800 IN A 127.0.0.1" local-zone: "127.in-addr.arpa." static local-data: "127.in-addr.arpa. 10800 IN NS localhost." local-data: "127.in-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 2 3600 1200 604800 10800" local-data: "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost."
转发所有剩余请求
使用 openresolv
如果您的网络管理器支持 openresolv,您可以 配置它 以向 Unbound 提供上游 DNS 服务器。
/etc/resolvconf.conf
... # Write out unbound configuration file unbound_conf=/etc/unbound/resolvconf.conf
运行 resolvconf -u 来生成文件。
最后,配置 Unbound 以读取 openresolv 生成的文件[2]
include: "/etc/unbound/resolvconf.conf"
手动指定 DNS 服务器
要为本地计算机和本地网络之外的默认正向区域使用特定服务器,请将名称为 . 的正向区域添加到配置文件中。在此示例中,所有请求都转发到 Google 的 DNS 服务器。
forward-zone: name: "." forward-addr: 8.8.8.8 forward-addr: 8.8.4.4
- 此示例使用 Google Public DNS。请将其替换为您信任的 DNS 解析器。请参阅 域名解析#第三方 DNS 服务。
- 强烈建议在连接到第三方 DNS 服务时使用 加密协议。请参阅 #使用 DNS over TLS 进行转发。
使用 DNS over TLS 进行转发
要使用 DNS over TLS,您需要启用 tls-system-cert 选项,允许 unbound 转发 TLS 请求,并指定任意数量支持 DNS over TLS 的服务器。
对于每个服务器,您需要使用 @ 指定连接端口,并使用 # 指定其域名。域名对于 TLS 身份验证是必需的,并且还允许设置存根区域和使用带有域名的 unbound-control forward control 命令。forward-addr 规范中不应有空格。
/etc/unbound/unbound.conf
...
server:
...
tls-system-cert: yes
...
forward-zone:
name: "."
forward-tls-upstream: yes
forward-addr: 1.1.1.1@853#cloudflare-dns.com
访问控制
您可以按 IP 地址指定要响应查询的接口。默认是监听 localhost。
要监听所有接口,请使用以下命令:
interface: 0.0.0.0 interface: ::0
0.0.0.0 和 ::)。要通过 IP 地址控制哪些系统可以访问服务器,请使用 access-control 选项:
access-control: subnet action
例如:
access-control: 192.168.1.0/24 allow
action 可以是 deny(丢弃消息)、refuse(礼貌的错误回复)、allow(允许递归)或 allow_snoop(允许递归和非递归)。默认情况下,除 localhost 外,所有请求都被拒绝。
用法
启动 Unbound
启动/启用 unbound.service systemd 服务。
远程控制 Unbound
unbound 附带 unbound-control 工具,该工具使我们能够远程管理 unbound 服务器。它类似于 pdnsd 的 pdnsd-ctl 命令。
设置 unbound-control
在您开始使用它之前,需要执行以下步骤:
1)首先,您需要运行以下命令:
# unbound-control-setup
这将为服务器和客户端生成自签名证书和私钥。这些文件将创建在 /etc/unbound 目录中。
2)之后,编辑 /etc/unbound/unbound.conf 并在此处添加以下内容。control-enable: yes 选项是必需的,其余的可以根据需要进行调整。
remote-control:
# Enable remote control with unbound-control(8) here.
# set up the keys and certificates with unbound-control-setup.
control-enable: yes
# what interfaces are listened to for remote control.
# give 0.0.0.0 and ::0 to listen to all interfaces.
control-interface: 127.0.0.1
# port number for remote control operations.
control-port: 8953
# unbound server key file.
server-key-file: "/etc/unbound/unbound_server.key"
# unbound server certificate file.
server-cert-file: "/etc/unbound/unbound_server.pem"
# unbound-control key file.
control-key-file: "/etc/unbound/unbound_control.key"
# unbound-control certificate file.
control-cert-file: "/etc/unbound/unbound_control.pem"
使用 unbound-control
可以使用 unbound-control 的一些命令包括:
- 打印统计信息而不重置它们
# unbound-control stats_noreset
- 将缓存转储到 stdout
# unbound-control dump_cache
- 刷新缓存并重新加载配置
# unbound-control reload
有关它支持的操作的详细信息,请参阅 unbound-control(8)。
技巧与提示
域名黑名单
要黑名单一个域名,请使用 local-zone: "domainname" always_refuse。
将黑名单保存为一个单独的文件(例如 /etc/unbound/blacklist.conf)以便于管理,并从 /etc/unbound/unbound.conf 中包含它。例如:
/etc/unbound/blacklist.conf
local-zone: "blacklisted.example" always_refuse local-zone: "anotherblacklisted.example" always_refuse
/etc/unbound/unbound.conf
server: ... include: /etc/unbound/blacklist.conf
- 为了在这些主机上返回一些 OK 状态,您可以将 127.0.0.1 重定向更改为您控制的服务器,并让该服务器响应空的 204 响应,请参阅 此页面。
- 要将来自其他来源的主机文件转换为 unbound 格式,请执行:
$ grep '^0\.0\.0\.0' hostsfile | awk '{print "local-zone: \""$2"\" always_refuse"}' > /etc/unbound/blacklist.conf - 有关黑名单的潜在来源列表,请参阅 OpenWrt 的 adblock 包 README。
添加权威 DNS 服务器
对于希望在单台机器上同时运行验证、递归、缓存 DNS 服务器和权威 DNS 服务器的用户来说,参考 NSD Wiki 页面可能是有益的,该页面提供了此类系统的配置示例。拥有一个用于权威 DNS 查询的服务器和一个用于验证、递归、缓存 DNS 功能的独立 DNS 服务器,比一个提供所有这些功能的单一 DNS 服务器具有更高的安全性。许多用户已将 Bind 用作单一 DNS 服务器,并且在从 Bind 迁移到结合使用 NSD 和 Bind 的过程中,NSD Wiki 页面提供了一些帮助。
面向 WAN 的 DNS
也可以更改配置文件和服务器正在监听的接口,以便来自本地网络之外的计算机的 DNS 查询可以访问 LAN 内的特定计算机。这对于可从任何地方访问的 Web 和邮件服务器非常有用,并且可以采用多年来使用 bind 实现的相同技术,并结合防火墙机器的适当端口转发来将传入请求转发到正确的机器。
Roothints systemd 定时器
这是一个示例 systemd 服务和定时器,它使用 #根提示 中的方法每月更新 root.hints:
/etc/systemd/system/roothints.service
[Unit] Description=Update root hints for unbound After=network.target [Service] ExecStart=/usr/bin/curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache
/etc/systemd/system/roothints.timer
[Unit] Description=Run root.hints monthly [Timer] OnCalendar=monthly Persistent=true [Install] WantedBy=timers.target
启动/启用 roothints.timer systemd 定时器。
保持 DNS 缓存始终最新
unbound 支持预取,即缓存的 DNS 条目在过期前会被自动更新,以保持缓存始终最新。引用 unbound.conf(5) 手册页的说法,启用它会增加大约 10% 的流量和机器负载,但热门条目不会从缓存中过期。这在具有高 RTT 的移动链接上尤其有用。
要启用预取,请在 server 部分添加以下内容:
prefetch: yes
提供过期记录
2020 年 3 月,RFC 8767 发布,其中规定了解析器何时以及如何从其缓存中提供陈旧数据。如果数据在 TTL 过期时无法权威性地刷新,则记录可以被视为未过期。自 1.6.0 版本以来,Unbound 能够用过期记录进行响应。
要启用提供过期记录,请在 server 部分添加以下内容:
serve-expired: yes serve-expired-ttl: 172800 # between 86400 (1 day) and 259200 (3 days) serve-expired-client-timeout: 1800 # RFC 8767 recommended value
故障排除
num-threads 相关问题
unbound.conf(5) § outgoing~2 提到:
outgoing-range: <number>
Number of ports to open. This number of file descriptors can be opened per thread.
一些来源建议将 num-threads 参数设置为 CPU 核心数。示例 unbound.conf.example 文件仅包含:
# number of threads to create. 1 disables threading.
# num-threads: 1
然而,在不引起 unbound 日志中出现关于超过文件描述符数量的警告的情况下,无法将 num-threads arbitrarily 增加到 1 以上。实际上,对于大多数运行在小型网络或单台机器上的用户来说,没有必要通过将 num-threads 增加到 1 以上来寻求性能提升。如果您确实想这样做,请参阅 官方文档,并且以下经验法则应该有效:
- 将
num-threads设置为系统 CPU 核心数。例如,对于 4 个 CPU 和每个 CPU 2 个核心,请使用 8。
将 outgoing-range 设置为尽可能大的值,请参阅上面网页中的相关部分,了解如何克服总共 1024 的限制。这可以同时服务更多客户端。单核尝试 950。双核尝试 450。四核尝试 200。num-queries-per-thread 最好设置为 outgoing-range 的一半。
由于 outgoing-range 的限制,这也限制了 num-queries-per-thread,因此最好使用 libevent 进行编译,这样 outgoing-range 就没有 1024 的限制了。如果您需要以这种方式进行编译以用于重负载的 DNS 服务器,那么您将需要从源代码编译程序,而不是使用 unbound 包。
启动后第一次查找失败
如果没有配置存储后端,unbound 将在每次启动和每次服务(重新)启动时都以一个完全空的缓存启动。当缓存为空时,第一次请求将触发大量查询到上游/远程 DNS 服务器。该数量的请求将很快达到 unbound 的配额。默认的 unbound 1.22.0 配置将上游查询数量限制为 128。即使是 未来版本默认值为 200 也无法完全解决此问题。
结果是您的第一次 DNS 查找将失败,第二次查找成功。启用错误日志记录后,您将看到类似的消息:
error: SERVFAIL <1.1.1.1.in-addr.arpa. PTR IN>: all servers for this domain failed, at zone 1.1.1.in-addr.arpa. no server to query no addresses for nameservers}}
在调试模式下,日志将显示类似以下内容:
debug: request 1.1.1.1.in-addr.arpa. has exceeded the maximum global quota on number of upstream queries 131}}
更改您的 unbound.conf 并重启 unbound,以将默认配额增加到 其他遇到此问题的用户认为的更宽松的值,例如:
max-global-quota: 300
(递归)查找超时
即使使用 1 Gbit/s 的 FTTH 连接,默认的 unbound 配置也可能导致递归查找超时。在调试模式下,日志将显示:
debug: drop reply, it is older than discard-timeout
如果您想等待比默认超时时间 1.9 秒稍长的时间来获得应答,请更改您的 unbound.conf:
discard-timeout: 3800 # in milliseconds