Unbound
Unbound 是一个验证性、递归和缓存 DNS 解析器。根据维基百科
- Unbound 已经取代了 Berkeley Internet Name Domain (BIND) 成为多个开源项目中的默认基础系统名称服务器,因为它被认为对于大多数应用程序来说更小、更现代且更安全。
安装
此外,expat 软件包是 #DNSSEC 验证所必需的。
配置
默认配置已包含在 /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 带有默认的内置提示。因此,如果定期更新软件包,则无需手动干预。否则,使用 root-hints 文件是一个好习惯,因为内置提示可能会过时。
首先将 unbound 指向 root.hints
文件
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: trusted-key.key
此设置是默认完成的[1]。/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 go.dnscheck.tools
响应应为 IP 地址,旁边带有单词 (secure)
。
$ unbound-host -vDr badsig.go.dnscheck.tools
这里的响应应包含 (BOGUS (security failure))
。
此外,您可以使用 drill 来测试解析器,如下所示
$ drill badsig.go.dnscheck.tools $ drill go.dnscheck.tools
第一个命令应给出 rcode
为 SERVFAIL
。第二个命令应给出 rcode
为 NOERROR
。
转发查询
如果您只想将查询转发到外部 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 地址范围进行回复[2]
/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 生成的文件[3]
include: "/etc/unbound/resolvconf.conf"
手动指定 DNS 服务器
要为本地计算机和本地网络之外的默认正向区域使用特定服务器,请向配置文件添加名称为 .
的正向区域。在此示例中,所有请求都将转发到 Google 的 DNS 服务器
forward-zone: name: "." forward-addr: 8.8.8.8 forward-addr: 8.8.4.4
使用 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
要控制哪些系统可以通过 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 回复进行响应,请参阅 此页面
- 要将来自另一个来源的 hosts 文件转换为 unbound 格式,请执行
$ grep '^0\.0\.0\.0' hostsfile | awk '{print "local-zone: \""$2"\" always_refuse"}' > /etc/unbound/blacklist.conf
- 可以在 OpenWrt 的 adblock 软件包的 README 中找到黑名单的潜在来源列表。
添加权威 DNS 服务器
对于希望在单台计算机上同时运行验证性、递归、缓存 DNS 服务器以及权威 DNS 服务器的用户,可以参考 wiki 页面 NSD,其中给出了此类系统的配置示例。与单个 DNS 服务器提供所有这些功能相比,使用一个服务器用于权威 DNS 查询,而使用单独的 DNS 服务器用于验证性、递归、缓存 DNS 功能,可以提高安全性。许多用户都使用 Bind 作为单个 DNS 服务器,并且 NSD wiki 页面中提供了一些关于从 Bind 迁移到运行 NSD 和 Bind 的组合的帮助。
面向 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
任意增加到 1
以上。实际上,对于在小型网络或单台计算机上运行的大多数用户来说,无需通过将 num-threads
增加到 1
以上来寻求性能提升。如果您确实希望这样做,请参阅 官方文档,以下经验法则应该有效
- 将
num-threads
设置为系统上的 CPU 核心数。例如,对于 4 个 CPU,每个 CPU 有 2 个核心,请使用 8。
将 outgoing-range
设置为尽可能大的值,请参阅上面引用的网页中的章节,了解如何克服总共 1024
的限制。这可以同时为更多客户端提供服务。对于 1 个核心,尝试 950
。对于 2 个核心,尝试 450
。对于 4 个核心,尝试 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