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会无法启动.如果你想要使用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之外的所有东西都会被拒绝。
为了使用这个功能,你需要设置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验证,你需要在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是否工作,在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服务器,请跳到#转发所有其余的请求。
如果你的网络管理器支持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服务器,那么你需要添加这一行:
private-address: 本地子网/子网掩码
例如:
private-address: 10.0.0.0/24
为了包含一个本地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,你可以通过配置使它提供上游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服务器:
forward-zone: name: "." forward-addr: 8.8.8.8 forward-addr: 8.8.4.4
Start/enable unbound.service systemd服务。
unbound安装的时候自带了unbound-control工具,利用这个工具我们可以远程控制unbound服务器。它和pdnsd包的pdnsd-ctl命令很类似。
在能够使用它之前你需要做下面的事情:
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 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
对于想要在一台机器上同时两个DNS服务器(一个是提供验证、递归、缓存功能的DNS服务器,另一个是authoritative DNS服务器)的用户来说,参考NSD的维基页面可能会有所帮助。那个页面提供了一个示范配置。一个服务器专门响应authoritative DNS请求,另一个服务器提供验证、递归、缓存等DNS功能,这样会比一个服务器提供所有功能会更安全。很多用户已经在使用Bind作为DNS服务器,而针对从Bind变成Bind和NSD协同工作的过程的帮助在NSD页面有提供。
通过更改配置文件和服务器所监听的接口(地址)来允许来自本地网络之外的机器的DNS请求进入本地网络(LAN)内的某台特定机器,这个想法是可行的。这个功能对于公开的网站服务器和邮件服务器是非常有用的。这个在bind上已经实现了多年的技术,通过正确配置防火墙机器上的端口转发——转发这些请求到正确的机器上——也可以在unbound上实现。
下面是一个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就可以了。
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-threadsequal 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包。