Unbound (简体中文)
Unbound 是一个具有验证,递归和缓存等功能的 DNS 解析器。根据Wikipedia:
- Unbound has supplanted the Berkeley Internet Name Domain (BIND) as the default, base-system name server in several open source projects, where it is perceived as smaller, more modern, and more secure for most applications.
安装
安装 unbound 软件包。 此外, expat 是使用DNSSEC验证请求所必须的。
配置
默认配置已经位于/etc/unbound/unbound.conf
文件中。此外,/etc/unbound/unbound.conf.example
文件包含了其他的可配置设置项,并以注释的形式给出了示范设置。以下章节重点解释和默认配置文件不同的设置项。如需了解更多细节,参见unbound.conf(5)。
除非特别声明,这一节列出的选项都是放置在配置文件的server
节中,类似这样:
/etc/unbound/unbound.conf
server: ... setting: value ...
do-daemonize: no
,否则unbound.service
会无法启动.本地DNS服务器
如果你想要使用unbound作为本地DNS服务器,请把resolv.conf中的域名服务器(nameserver)设置到回环地址::1
和127.0.0.1
。你可能想要让你的配置Domain name resolution (简体中文)#覆盖 /etc/resolv.conf。
/etc/resolvconf.conf
中包含name_servers="::1 127.0.0.1"
的那一行的注释。然后运行resolvconf -u
来重新生成/etc/resolv.conf
。要了解如何测试设置项,参见Domain name resolution#Lookup utilities。
在把resolv.conf中的设置更改为持久化设置后,请特别注意检查正在使用的服务器是::1
或127.0.0.1
。
你还需要对“unbound”进行设置,以使它#转发查询到你所选择的DNS服务器。
访问控制
你可以通过IP地址来指定响应请求的端口。默认监听的是localhost。
为了在所有端口上监听,使用以下配置:
interface: 0.0.0.0
为了通过IP地址来控制可以访问服务器的系统,使用access-control
选项:
access-control: subnet action
例如:
access-control: 192.168.1.0/24 allow
action可以是deny
(drop message), refuse
(polite error reply), allow
(recursive ok), or allow_snoop
(recursive and nonrecursive ok)中的任意一个。默认除了localhost之外的所有东西都会被拒绝。
使用DNS over TLS进行转发
为了使用这个功能,你需要设置tls-cert-bundle
选项来指定本地系统的根证书认证包,以使得unbound可以转发TLS请求并指定允许DNS over TLS的服务器数量。
对每个服务器你都需要用 @ 来指定连接的端口,同时你也要用 # 来指明它的域名是什么。虽然它看起来像注释,the hashtag name allows for the TLS authentication name to be set for stub-zones and with unbound-control forward control
command。在 @ 和 # 之间不应该有空格。
/etc/unbound/unbound.conf
... server: ... tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt ... forward-zone: name: "." forward-tls-upstream: yes forward-addr: 1.1.1.1@853#cloudflare-dns.com
根域名服务器
为了查询一个没有被缓存成地址的主机,解释器需要从服务器树的根开始、对根服务器进行请求来知道去哪里找到目标地址的顶级域名。Unbound内置了一些根节点,但是推荐你提供一个根节点文件给它以免内置的过于老旧。
首先,告诉unbound使用root.hints
文件:
root-hints: root.hints
然后把你的root hints文件放进unbound的配置文件夹。实现这个目标最简单的方法是运行下面的命令:
# curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache
建议每六个月更新一次root.hints
来保持根服务器列表是最新的。你可以手动完成这个任务,也可以使用Systemd/Timers。详情参见#根域名服务器与systemd timer。
DNSSEC验证
为了使用DNSSEC验证,你需要在server:
节中添加以下设置来告诉unbound服务器根证书文件的位置:
/etc/unbound/unbound.conf
trust-anchor-file: trusted-key.key
/etc/unbound/trusted-key.key
是从依赖项dnssec-anchors所提供的的/etc/trusted-key.key
复制而来的,它的PKGBUILD按照unbound-anchor(8)生成了/etc/trusted-key.key
。
如果总的#转发查询设置到了不支持DNSSEC的DNS服务器,那么请确保已经把这些DNS服务器注释掉,否则DNS请求会失败。DNSSEC验证只会在被请求的DNS服务器支持它的时候成功完成。
测试DNSSEC
为了测试DNSSEC是否工作,在starting unbound.service
之后:
$ unbound-host -C /etc/unbound/unbound.conf -v sigok.verteiltesysteme.net
得到的回应应该是附带(secure)
字样的ip地址。
$ unbound-host -C /etc/unbound/unbound.conf -v sigfail.verteiltesysteme.net
这次的回应应该包含(BOGUS (security failure))
字样。
另外你也可以使用“drill”来测试:
$ drill sigok.verteiltesysteme.net $ drill sigfail.verteiltesysteme.net
第一个命令应该返回NOERROR
的rcode
;而第二个命令应该返回SERVFAIL
的rcode
。
转发查询
如果你只想转发请求到外部的DNS服务器,请跳到#转发所有其余的请求。
允许本地网络使用DNS
使用openresolv
如果你的网络管理器支持openresolv,你可以通过设置来使它提供本地DNS服务器、使用unbound来查询域名。 [2]
/etc/resolvconf.conf
... private_interfaces="*" # Write out unbound configuration file unbound_conf=/etc/unbound/resolvconf.conf
运行resolvconf -u
来生成文件。
配置unbound读取openresolv生成的文件并允许回应private IP address ranges:
/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[3]:
/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请求的本地网络,同时你想要把请求都转发给一个本地的DNS服务器,那么你需要添加这一行:
private-address: 本地子网/子网掩码
例如:
private-address: 10.0.0.0/24
包含本地DNS服务器
为了包含一个本地DNS服务器,以用于转发和反代本地地址,类似下面的一组配置是必要的(请把下面的10.0.0.1替换为本地网络中提供DNS服务的服务器的地址):
local-zone: "10.in-addr.arpa." transparent
上面这一行对于让反向查询正常工作是非常重要的。
forward-zone: name: "mynetwork.com." forward-addr: 10.0.0.1 forward-zone: local-data: "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost."
你可以通过下面的配置来设定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,你可以通过配置使它提供上游DNS服务器给unbound。 [4]
/etc/resolvconf.conf
... # Write out unbound configuration file unbound_conf=/etc/unbound/resolvconf.conf
运行resolvconf -u
来生成文件。
最后配置unound读取openresolv生成的文件:
include: "/etc/unbound/resolvconf.conf"
手动指定DNS服务器
为了使本地机器之外的、本地网络外部的默认转发区域使用指定的服务器,请在配置文件中添加一个名字是.
的转发区域。在这个例子里,所有的请求都被转发到谷歌的DNS服务器:
forward-zone: name: "." forward-addr: 8.8.8.8 forward-addr: 8.8.4.4
使用
启动unbound
Start/enable unbound.service
systemd服务。
远程控制unbound
unbound安装的时候自带了unbound-control
工具,利用这个工具我们可以远程控制unbound服务器。它和pdnsd的pdnsd-ctl命令很类似。
配置unbound-control
在能够使用它之前你需要做下面的事情:
1) 首先,运行:
# unbound-control-setup
来为你的服务器和客户端生成一个self-signed的证书和private key。生成的文件位于/etc/unbound
文件夹。
2) 然后,把下面的内容放进/etc/unbound/unbound.conf
文件。control-enable: yes
是一定要有的,其余的内容可以按照所需进行调整。
remote-control: # Enable remote control with unbound-control(8) here. # 用unbound-control-setup生成的keys and certificates进行配置。 control-enable: yes # 设定监听哪个地址. # give 0.0.0.0 and ::0 to listen to all interfaces. control-interface: 127.0.0.1 # 远程控制用的端口. 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
- 把cache dump到stdout
# unbound-control dump_cache
- 清空cache并且重新加载配置
# unbound-control reload
请参考unbound-control(8)来了解unbound-control支持的操作。
提示与技巧
域名黑名单
你可以打开这个网页adservers,把它的内容保存到/etc/unbound/adservers
,然后把下面的配置直接添加到unbound配置文件里就可以了:
/etc/unbound/unbound.conf
server: ... include: /etc/unbound/adservers
- 为了在查询这些hosts的时候返回OK状态指示,你可以更改默认的127.0.0.1重定向,改成重定向到你所控制的服务器并让那台服务器返回空的204回应,参考[5]
- 如果需要把其他格式的hosts文件转换成unbound的格式的,请运行这个命令:
$ grep '^0\.0\.0\.0' hostsfile | awk '{print "local-zone: \""$2"\" always_nxdomain"}' > /etc/unbound/adservers
添加一个authoritative DNS服务器
对于想要在一台机器上同时两个DNS服务器(一个是提供验证、递归、缓存功能的DNS服务器,另一个是authoritative DNS服务器)的用户来说,参考NSD的维基页面可能会有所帮助。那个页面提供了一个示范配置。一个服务器专门响应authoritative DNS请求,另一个服务器提供验证、递归、缓存等DNS功能,这样会比一个服务器提供所有功能会更安全。很多用户已经在使用Bind作为DNS服务器,而针对从Bind变成Bind和NSD协同工作的过程的帮助在NSD页面有提供。
WAN facing DNS
通过更改配置文件和服务器所监听的接口(地址)来允许来自本地网络之外的机器的DNS请求进入本地网络(LAN)内的某台特定机器,这个想法是可行的。这个功能对于公开的网站服务器和邮件服务器是非常有用的。这个在bind上已经实现了多年的技术,通过正确配置防火墙机器上的端口转发——转发这些请求到正确的机器上——也可以在unbound上实现。
根域名服务器与systemd timer
下面是一个systemd服务和timer的示例文件,它用来每隔一个月更新一次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
最后Start/enable roothints.timer
systemd timer就可以了。
疑难解答
有关num-threads的问题
unbound.conf
的man page提到:
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
但是人为地把num-threads
提高到比1
就一定会造成unbound在启动的时候在log里写一个warning提示说exceeding the number of file descriptors。实际上对于大多数在小型网络或是单机上运行unbound的用户来说,通过让num-threads
超过1
来得到性能提升是徒劳的。如果你一定要这么做,那么请参考official documentation。下面这条经验法则应该对你有所帮助:
- Set
num-threads
equal to the number of CPU cores on the system. E.g. for 4 CPUs with 2 cores each, use 8.
把outgoing-range
设置得尽可能大,参考上面的链接来突破总数是1024
这个限制。这样就会使得unbound可以同时为更多客户端提供服务。1个核心设置950
,2个核心设置450
,四个核心设置200
。num-queries-per-thread
最好设置成outgoing-range
的一半。
因为outgoing-range
是有限制的,同时num-queries-per-thread
也因此受到了限制,所以最好在编译的时候带上libevent,这样就不会有1024
限制了。如果你有一个高负荷DNS服务器使得你不得不这样编译,你需要从源码编译unbound而不是直接安装unbound。