Total Pageviews

Wednesday 14 November 2012

在本地机器上,使用Unbound架设DNS PROXY, 实现用TCP进行DNS查询

Unbound 是一个小巧免费的专业DNS服务器查询程序,运行平台:Linux、Windows,mac

下载页面:http://www.unbound.net/download.html

修改/usr/local/etc/unbound/unbound.conf.default 里的下面蓝色文字表示的5处即可。其他地方其实不用改。
interface: 127.0.0.1
port: 53
forward-zone: 
name: “.” 
forward-addr: 208.67.222.222@5353

简要说一下配置:
     # if yes, perform prefetching of almost expired message cache entries.
    prefetch: yes

    # Enable IPv4, "yes" or "no".
    do-ip4: yes

    # Enable IPv6, "yes" or "no".
    do-ip6:yes

    # Enable UDP, "yes" or "no".
    do-udp: yes

    # Enable TCP, "yes" or "no".
    do-tcp: yes

    # upstream connections use TCP only (and no UDP), "yes" or "no"
    # useful for tunneling scenarios, default no.
    tcp-upstream: yes

do-udp 是 yes,上游查询会使用 tcp;先用 -vc 的 nslookup 确定上游 DNS 服务器是否支持 TCP 查询.

related post: http://briteming.blogspot.co.uk/2011/11/unbound-tcp-dns.html
-------------------------
利用一款unbound软件来支持tcp查询DNS

最近GFW升级DNS污染方案 不少使用ChinaDNS等类似防DNS污染软件的用户都反映依然会有DNS污染。虽然TCP查询方式导致的延迟较高,但是ChinaDNS如今这种等待0.3秒的方式,延迟已经可能高于TCP查询,此时其实我们可以采用TCP方式查询,来防DNS污染。因为污染TCP方式的DNS查询成本较高,加之使用TCP方式查询的比例极其微小,所以GFW至今也未对TCP方式的查询进行污染。

一种简易的方式,可以利用一款unbound软件来支持tcp查询DNS。
首先安装unbound:   
opkg update
opkg install unbound

然后修改 /etc/unbound/unbound.conf 文件,把以下内容相关的条目的注释取消,并按如下形式修改:
interface: 127.0.0.1
# unbound本地端口 由于dnsmasq占用53端口所以改用其他 如5454
port: 5454
# 启用TCP模式
tcp-upstream: yes
# 设置转发的DNS服务器
forward-zone: 
name: "."
forward-addr: 208.67.222.222@5353

启动unbound:   
/etc/init.d/unbound start

接着我们就可以配合ChinaDNS来使用了,将默认使用的8.8.8.8改成127.0.0.1:5454即可.
接下来使一些额外的操作来改善解析速度。这里介绍1种:

使用aa65535的修改版dnsmasq:
使用这个版本:https://github.com/aa65535/openwrt-dnsmasq替换掉系统自带的版本。在 /etc/dnsmasq.conf 中,可以配置 cache-size 和 min-cache-ttl ,分别可以修改DNS缓存最大条目数和最小DNS记录超时时间,可酌情改大。aa65535给出默认的推荐配置是:https://github.com/aa65535/openwrt-dnsmasq/blob/master/etc/dnsmasq.conf
=============================

在OpenWRT路由器中,使用unbound+dnsmasq解决DNS污染与DNS劫持


 首先安装unbound:  
opkg update
opkg install unbound

然后修改/etc/unbound/unbound.conf文件,把以下内容相关的条目的注释取消,并按如下形式修改: 
interface: 127.0.0.1 
# unbound本地端口 由于dnsmasq占用53端口所以改用其他 如5353
port: 5353
# 启用TCP模式
tcp-upstream: yes
# 设置转发的DNS服务器
forward-zone:
name: "."
forward-addr: 208.67.222.222@5353

启动unbound:  
 /etc/init.d/unbound start

配置dnsmasq的转发功能:
修改/etc/dnsmasq.conf文件,在末尾直接按如下格式添加被劫持污染的站点:  
server=/example.com/127.0.0.1#5353

example.com改为需要的域名,127.0.0.1#5353表示转发至unbound,5353是unbound的本地端口号,下面是一个例子:  
#Youtube
server=/youtube.com/127.0.0.1#5353
#Facebook
server=/facebook.com/127.0.0.1#5353
server=/fbcdn.net/127.0.0.1#5353
#Twitter
server=/twitter.com/127.0.0.1#5353

然后转至luci进行下一步配置:

WAN接口的高级设置里,取消“使用端局通告的DNS服务器”的勾并留空下面的自定义服务器,我们只用DHCP/DNS设置中的条目来控制DNS服务器,不希望这里通告的DNS服务器影响我们的配置.

记得点击保存&应用后,切换到DHCP/DNS设置中,在DNS转发配置中填入默认的国内DNS,强烈推荐用114DNS代替ISP的DNS,如果你希望全局转发至unbound完全使用国外公众DNS,此处填写127.0.0.1#5353:
填入完毕后点击保存并应用,dnsmasq自动重启,至此配置完成。


PC端测试(Windows)

清空DNS缓存:  
 ipconfig /flushdns

nslookup直接向GoogleDNS查询twitter.com,结果被污染:
C:Userscokebar>nslookup twitter.com 8.8.8.8
服务器: google-public-dns-a.google.com
Address: 8.8.8.8
非权威应答:
名称: twitter.com
Addresses: 59.24.3.173
59.24.3.173

加 -v 参数的nslookup通过TCP向GoogleDNS获得真实结果:
  
C:Userscokebar>nslookup -v twitter.com 8.8.8.8
服务器: google-public-dns-a.google.com
Address: 8.8.8.8
非权威应答:
名称: twitter.com
Addresses: 199.59.150.39
199.59.150.7
199.59.148.10

不加任何参数的nslookup,默认查询方式,向路由器的dnsmasq查询,结果正常,DNS转发生效:  
 C:Userscokebar>nslookup twitter.com
服务器: OpenWrt.lan
Address: 192.168.1.1
非权威应答:
名称: twitter.com
Addresses: 199.59.149.198
199.59.148.10
199.59.150.39

OVER!
-----------------------

mac下,安装unbound

yudeMacBook-Air:~ brite$ brew install unbound
==> Downloading https://homebrew.bintray.com/bottles/unbound-1.5.4.yosemite.bott
######################################################################## 100.0%
==> Pouring unbound-1.5.4.yosemite.bottle.tar.gz
==> Caveats
To have launchd start unbound at startup:
  sudo cp -fv /usr/local/opt/unbound/*.plist /Library/LaunchDaemons
  sudo chown root /Library/LaunchDaemons/homebrew.mxcl.unbound.plist
Then to load unbound now:
  sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.unbound.plist
==> Summary
  /usr/local/Cellar/unbound/1.5.4: 51 files, 3.3M
yudeMacBook-Air:~ brite$
yudeMacBook-Air:unbound brite$ sudo find / -name unbound
Password:
find: /dev/fd/3: Not a directory
find: /dev/fd/4: Not a directory
/opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/net/unbound
/usr/local/Cellar/unbound
/usr/local/Cellar/unbound/1.5.4/sbin/unbound
/usr/local/etc/unbound
/usr/local/Library/LinkedKegs/unbound
/usr/local/opt/unbound
/usr/local/sbin/unbound
yudeMacBook-Air:unbound brite$ ln -s /usr/local/sbin/unbound /usr/local/bin/unbound
yudeMacBook-Air:unbound brite$ unbound -h
usage:  unbound [options]
start unbound daemon DNS resolver.
-h this help
-c file config file to read instead of /usr/local/etc/unbound/unbound.conf
file format is described in unbound.conf(5).
-d do not fork into the background.
-v verbose (more times to increase verbosity)
Version 1.5.4
linked libs: libevent 2.0.22-stable (it uses kqueue), OpenSSL 1.0.2d 9 Jul 2015
linked modules: dns64 validator iterator
BSD licensed, see LICENSE in source package for details.
Report bugs to unbound-bugs@nlnetlabs.nl
yudeMacBook-Air:unbound brite$
yudeMacBook-Air:unbound brite$ unbound
[1460784185] unbound[88356:0] fatal error: user 'unbound' does not exist.
yudeMacBook-Air:unbound brite$ useradd -s /bin/false unbound
-bash: useradd: command not found
yudeMacBook-Air:unbound brite$

此时需参考在 Mac 上设置用户,创建用户unbound.然后即可运行unbound:
yudeMacBook-Air:unbound brite$ unbound
yudeMacBook-Air:unbound brite$

修改/usr/local/etc/unbound/unbound.conf.default 里的下面蓝色文字表示的5处即可。其他地方其实不用改。
interface: 127.0.0.1
port: 53
forward-zone: 
name: “.” 
forward-addr: 208.67.222.222@5353

然后运行:
unbound -c /usr/local/etc/unbound/unbound.conf.default

实际使用例子:
sudo wg-quick up wg0 

sudo networksetup -setdnsservers "Wi-Fi" 127.0.0.1

unbound -c /usr/local/etc/unbound/unbound.conf.default
--------------------------

推荐大家用Unbound,支持TCP DNS,也支持DNSSEC认证!
大家自己去Unbound的配置说明页去看看.
下面是我的配置,注意:Unbound的配置文件格式要求很高,冒号后面必须得有且只有一个空格.

interface: 127.0.0.1
port: 53
#Append到Server后
prefetch: yes
do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
tcp-upstream: yes

#Append到forward-zone后
      forward-zone:
      name: "."
      forward-addr: 208.67.222.222@5353
      forward-addr: 208.67.222.222@443
      forward-addr: 208.67.220.220@5353
      forward-addr: 208.67.220.220@443
#以上这么多条是我收集的可信任的DNS公共服务器.
-----------------


Unbound

Jump to: navigation, search
start content
Related articles
Unbound is a validating, recursive, and caching DNS resolver. According to Wikipedia:Unbound (DNS Server), "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."
Contents [hide
  • 1 Installation
  • 2 Configuration
    • 2.1 Access control
    • 2.2 Root hints
    • 2.3 Local DNS server
    • 2.4 DNSSEC validation
    • 2.5 Forwarding queries
  • 3 Usage
    • 3.1 Starting Unbound
    • 3.2 Remotely control Unbound
      • 3.2.1 Setting up unbound-control
      • 3.2.2 Using unbound-control
  • 4 Tips and tricks
    • 4.1 Block advertising
    • 4.2 Adding an authoritative DNS server
    • 4.3 WAN facing DNS
    • 4.4 Roothints systemd timer
  • 5 Troubleshooting
    • 5.1 Issues concerning num-threads
  • 6 See also
Installation
Install the unbound package.
Additionally, the expat package is required for DNSSEC validation.
Configuration
A default configuration is already included at/etc/unbound/unbound.conf. Additionally, there is a commented sample configuration file with other available options located at /etc/unbound/unbound.conf.example. The following sections highlight different settings for the configuration file. See man unbound.conf for other settings and more details.
Unless otherwise specified, any options listed in this section are to be placed under the server section in the configuration like so:
/etc/unbound/unbound.conf
server:
  ...
  setting: value
  ...
Access control
You can specify the interfaces to answer queries from by IP address. To listen on localhost, use the default setting:
interface: 127.0.0.1
To listen on all interfaces, use the following:
interface: 0.0.0.0
To control which systems can access the server by IP address, use the access-control option:
access-control: subnet action
For example:
access-control: 192.168.1.0/24 allow
action can be one of deny (drop message), refuse (polite error reply), allow (recursive ok), or allow_snoop (recursive and nonrecursive ok). By default everything is refused except for localhost.
Root hints
For querying a host that is not cached as an address the resolver needs to start at the top of the server tree and query the root servers to know where to go for the top level domain for the address being queried. Unbound comes with default builtin hints, but it is good practice to use a root-hints file since the builtin hints may become outdated.
First point unbound to the root.hints file:
root-hints: "/etc/unbound/root.hints"
Then, put a root hints file into the unbound configuration directory. The simplest way to do this is to run the command:
# curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache
It is a good idea to update root.hints every six months or so in order to make sure the list of root servers is up to date. This can be done manually or by using Systemd/Timers. See #Roothints systemd timer for an example.
Local DNS server
If you want to use unbound as your local DNS server, set your nameserver to 127.0.0.1 in your resolv.conf. You will want to have your nameserver be preserved.
Tip: A simple way to do this is to install the openresolv package and uncomment the line containing name_servers=127.0.0.1 in /etc/resolvconf.conf. Then run resolvconf -u to generate /etc/resolv.conf.
Testing the server before making it default can be done using the drill command from the ldns package with examples from internal and external forward and reverse addresses:
$ drill @127.0.0.1 www.cnn.com
$ drill @127.0.0.1 localmachine.localdomain.com
$ drill @127.0.0.1 -x w.x.y.z 
where w.x.y.z can be a local or external IP address and the -x option requests a reverse lookup. Once all is working, and you have /etc/resolv.conf set to use 127.0.0.1 as the nameserver then you no longer need the @127.0.0.1 in the drill command, and you can test again that it uses the default DNS server - check that the server used as listed at the bottom of the output from each of these commands shows it is 127.0.0.1 being queried.
DNSSEC validation
unbound automatically copies the root server trust key anchor file from /etc/trusted-key.key to /etc/unbound/trusted-key.key. To use DNSSEC validation, point unbound to this file by adding the following setting:
trust-anchor-file: trusted-key.key
Also make sure that if a general forward to a DNS server has been set, then comment them out; otherwise, DNS queries will fail. DNSSEC validation will only be done if the DNS server being queried supports it.
Note: Including DNSSEC checking significantly increases DNS lookup times for initial lookups. Once an address is cached locally, then the lookup is virtually instantaneous.
To test if DNSSEC is working, use drill:
$ drill sigfail.verteiltesysteme.net
$ drill sigok.verteiltesysteme.net
The first command should give an rcode of SERVFAIL. The second should give an rcode of NOERROR.
Forwarding queries
Tip: Unbound can be used with DNSCrypt by setting up forwarding. See DNSCrypt#Example: configuration for Unbound.
If you have a local network which you wish to have DNS queries for and there is a local DNS server that you would like to forward queries to then you should include this line:
private-address: local_subnet/subnet_mask
For example:
private-address: 10.0.0.0/24
Note: You can use private-address to protect against DNS Rebind attacks. Therefore you may enable RFC1918 networks (10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 169.254.0.0/16 fd00::/8 fe80::/10). Unbound may enable this feature by default in future releases.
To include a local DNS server for both forward and reverse local addresses a set of lines similar to these below is necessary with a forward and reverse lookup (choose the IP address of the server providing DNS for the local network accordingly by changing 10.0.0.1 in the lines below):
local-zone: "10.in-addr.arpa." transparent
This line above is important to get the reverse lookup to work correctly.
forward-zone:
name: "mynetwork.com."
forward-addr: 10.0.0.1
forward-zone:
name: "10.in-addr.arpa."
forward-addr: 10.0.0.1
Note: There is a difference between forward zones and stub zones - stub zones will only work when connected to an authoritative DNS server directly. This would work for lookups from a BIND DNS server if it is providing authoritative DNS - but if you are referring queries to an unbound server in which internal lookups are forwarded on to another DNS server, then defining the referral as a stub zone in the machine here will not work. In that case it is necessary to define a forward zone as above, since forward zones can have daisy chain lookups onward to other DNS servers. i.e. forward zones can refer queries to recursive DNS servers. This distinction is important as you do not get any error messages indicating what the problem is if you use a stub zone inappropriately.
You can set up the localhost forward and reverse lookups with the following lines:
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."
Then to use specific servers for default forward zones that are outside of the local machine and outside of the local network (i.e. all other queries will be forwarded to them, and then cached) add this to the configuration file (and in this example the first two addresses are the fast google DNS servers):
  forward-zone:
  name: "."
  forward-addr: 8.8.8.8
  forward-addr: 8.8.4.4
  forward-addr: 208.67.222.222
  forward-addr: 208.67.220.220
This will make unbound use Google and OpenDNS servers as the forward zone for external lookups.
Note: OpenDNS strips DNSSEC records from responses. Do not use the above forward zone if you want to enable #DNSSEC validation.
Usage
Starting Unbound
Start/enable the unbound.service systemd service.
Remotely control Unbound
unbound ships with the unbound-control utility which enables us to remotely administer the unbound server. It is similar to the pdnsd-ctl command of pdnsd.
Setting up unbound-control
Before you can start using it, the following steps need to be performed:
1) Firstly, you need to run the following command
# unbound-control-setup
which will generate a self-signed certificate and private key for the server, as well as the client. These files will be created in the /etc/unbound directory.
2) After that, edit /etc/unbound/unbound.conf and put the following contents in that. The control-enable: yes option is necessary, the rest can be adjusted as required.
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"
Using unbound-control
Some of the commands that can be used with unbound-control are:
  • print statistics without resetting them
 # unbound-control stats_noreset
  • dump cache to stdout
 # unbound-control dump_cache
  • flush cache and reload configuration
 # unbound-control reload
Please refer to man 8 unbound-control for a detailed look at the operations it supports.
Tips and tricks
Block advertising
You can use the following file and simply include it in your unbound configuration: adservers
/etc/unbound/unbound.conf
...
include: /etc/unbound/adservers
Note: In order to return some OK statuses on those hosts, you can change the 127.0.0.1 redirection to a server you control and have that server respond with empty 204 replies, see this page
Adding an authoritative DNS server
For users who wish to run both a validating, recursive, caching DNS server as well as an authoritative DNS server on a single machine then it may be useful to refer to the wiki page nsd which gives an example of a configuration for such a system. Having one server for authoritative DNS queries and a separate DNS server for the validating, recursive, caching DNS functions gives increased security over a single DNS server providing all of these functions. Many users have used bind as a single DNS server, and some help on migration from bind to the combination of running nsd and bind is provided in the nsd wiki page.
WAN facing DNS
It is also possible to change the configuration files and interfaces on which the server is listening so that DNS queries from machines outside of the local network can access specific machines within the LAN. This is useful for web and mail servers which are accessible from anywhere, and the same techniques can be employed as has been achieved using bind for many years, in combination with suitable port forwarding on firewall machines to forward incoming requests to the right machine.
Roothints systemd timer
Here is an example systemd service and timer that update root.hints monthly using the method in #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

[Install]
WantedBy=multi-user.target
/etc/systemd/system/roothints.timer
[Unit]
Description=Run root.hints monthly

[Timer]
OnCalendar=monthly
Persistent=true     

[Install]
WantedBy=timers.target
Start/enable the roothints.timer systemd timer.
Troubleshooting
Issues concerning num-threads
The man page for unbound.conf mentions:
     outgoing-range: <number>
             Number of ports to open. This number of file  descriptors  can  be  opened  per thread.
and some sources suggest that the num-threads parameter should be set to the number of cpu cores. The sample unbound.conf.example file merely has:
       # number of threads to create. 1 disables threading.
       # num-threads: 1
However it is not possible to arbitrarily increase num-threads above 1 without causing unbound to start with warnings in the logs about exceeding the number of file descriptors. In reality for most users running on small networks or on a single machine it should be unnecessary to seek performance enhancement by increasing num-threads above 1. If you do wish to do so then refer to official documentation and the following rule of thumb should work:
Set num-threads equal to the number of CPU cores on the system. E.g. for 4 CPUs with 2 cores each, use 8.
Set the outgoing-range to as large a value as possible, see the sections in the referred web page above on how to overcome the limit of 1024 in total. This services more clients at a time. With 1 core, try 950. With 2 cores, try 450. With 4 cores try 200. The num-queries-per-thread is best set at half the number of the outgoing-range.
Because of the limit on outgoing-range thus also limits num-queries-per-thread, it is better to compile with libevent, so that there is no 1024 limit on outgoing-range. If you need to compile this way for a heavy duty DNS server then you will need to compile the programme from source instead of using the unbound package.
See also

from https://wiki.archlinux.org/index.php/Unbound
-------------------------------------------------------------------------------------------------

Unbound DNS Tutorial


A validating, recursive, and caching DNS server

Unbound is a very secure validating, recursive, and caching DNS server primarily developed by NLnet Labs, VeriSign Inc, Nominet, and Kirei. The software is distributed free of charge under the BSD license. The binaries are written with a high security focus, tight C code and a mind set that it is always under attack or remote servers are always trying to pass it bad information.
Unbound's design is a set of modular components which incorporate features including enhanced security (DNSSEC) validation, Internet Protocol Version 6 (IPv6), and a client resolver library API as an integral part of the architecture. Originally written for Posix-compatible Unix-like operating system, Unbound currently runs on FreeBSD, OpenBSD, NetBSD, and Linux, as well as Microsoft Windows.
The install and configuration of Unbound is incredibly easy. Most modern OS's already have Unbound packages made. We have verified that OpenBSD, FreeBSD, CentOS and Ubuntu have packages available through their current distribution methods. As for the configuration, a simple resolving caching DNS server which can be used for a single machine or multi-machine LAN is only a few lines long. Note that Unbound is not a full fledged authoritative server, but you can put in A records for forward and reverse resolution of a small private LAN.
In the future it is expected that many, if not all, open source distributions will move to Unbound and away from BIND. FreeBSD 10 has already made the change as BIND is no longer included in the default install. BIND, also known as named, is getting extremely code bloated, slow and over complicated. Complication leads to security exploits and over twenty(20) of the last seventy(70) critical bugs in FreeBSD have been due to BIND itself. The other problem is BIND is used for around 70% of the worlds DNS servers leading to a monoculture environment. When an attack or exploit comes out it is advantageous as the attacker to go after the most used software. Unbound in comparison is an incredibly fast and secure DNS name server which, due to its small size, can easily be code audited for security.
Lets take a look at some definitions and then some examples.

Common DNS functions

Before we examine the configuration examples, we need to understand the basic functions available through a modern DNS server. Then you can decide what type of DNS server you want and go right to the configurations below. Note that you can combine multiple functions together in a single DNS server. For example you can have a caching DNS, a recursive caching DNS, a validating recursive caching DNS, an authoritative validating recursive caching DNS, etc.

recursive DNS server

Caching name servers store DNS query results for a period of time determined in the configuration (time-to-live) of the domain name record in question. Recursive name servers resolve any query they receive, even if they are not authoritative for the question being asked, by consulting the server or servers that are authoritative for the query. Caching name servers, as seen in the next section, improve the efficiency of the DNS by reducing DNS traffic across the Internet, and by reducing load on authoritative name servers, particularly root name servers. Because local dns servers can answer questions more quickly, they also increase the performance of end-user applications that use DNS.
A recursive DNS server will, on behalf of the client (resolver), traverse the paths of DNS across the Internet to retrieve the answer to the question. A simple query such as "What is the IP address of calomel.org ?" to a DNS server which supports recursive queries but is not authoritative for calomel.org would look something like the following:
  • Your client resolver sends a query, "What is the IP address of calomel.org ?" to a locally configured DNS server like Unbound.
  • Unbound DNS server looks up calomel.org in local tables (its cache) - not found if we have never asked for this hostname before.
  • Unbound DNS sends a query to one of the root-servers in its root.hints file.
  • The root-server replies with a referral to the TLD servers for ".org".
  • Unbound sends a query, "What is the IP address calomel.org ?" to one of the .org TLD servers.
  • The TLD server replies with a referral to the authoritative name servers for calomel.org at DynDNS.org .
  • Unbound sends query, "What is the IP address calomel.org ?" to an authoritative name server for calomel.org .
  • The authoritative Zone file at DynDNS defines a "A" record which contains the ip address of calomel.org. DynDNS returns the ip of calomel.org .
  • Unbound receives the ip address of calomel.org and returns the answer to the client resolver. Transaction complete.
As you can see a standard query for calomel.org is quite a bit of work and takes a little time to complete. That is why we like to keep a local copy of the answer on our local Unbound DNS server. That local copy is called a "cached" copy which leads to our next section.

caching DNS server

Caching name servers, also called DNS caches, are often also resolving name servers as they perform every step necessary to answer any DNS query they receive. To do this the name server queries each authoritative name server in turn, starting from the DNS root zone. The query process continues until Unbound reaches the authoritative server for the zone that contains the queried domain name. That server provides the answer to the question, or definitively says it can't be answered, and the caching resolver then returns this response to the client that asked the question.This combination of resolver and cache creates a DNS server that will respond to look up requests by delivering answers from its cache if the hostname has been asked for before, or recursively resolving the hostnames if we have never seen this hostname. Cached results are returned in one(1) or two(2) milliseconds while recursive queries can take hundreds of milliseconds or more.

validating DNS server

A validating DNS server is simply a resolver which verifies the response it has received is as correct as it can be sure of. This is usually accomplished using Secure DNS (DNSSEC) or using 0x20-encoded random bits in the query to foil spoof attempts. Validation could also encompass sanity checks of the returned data or making sure a remote host does not try to return an illegal ip for an external hostname (dnsspoof).
To perform a cache poisoning attack for example, the attacker exploits a flaw in the DNS software. If the server does not correctly validate DNS responses to ensure that they are from an authoritative source (for example by using DNSSEC) the server will end up caching the incorrect entries locally and serve them to other users that make the same request. This just means that when you type in the hostname of your bank, you want to make sure that hostname matches you bank's actual ip address and not some phishing site in Cape Town, South Africa.
Paranoia in DNS security is also a reason you really need to have trust in any resolving caching server you do not control. We like to always have a DNS server under our control query the root servers and work their way down to the domain's authoritative server. This way we are sure of the setup as we are the administrators and we are confident in the DNS servers cached data due to the security design we have implemented. If you setup your DNS resolver to query the local ISP's dns cache you really, really need to trust their people and their setup is secure. From the view of an attacker, an ISP's dns cache is the perfect target. The attacker only needs to poison one dns server and all queries from all the users of that ISP go to the attackers compromised machines. This scenario has already happened once to AT&T's DNS cache servers (google for "dns attacks wild at&t") and it will sadly happen again.

authoritative DNS server

An authoritative DNS server is simply the primary owner of the hostname.
When a domain is registered with a domain name registrar, the zone administrator provides a list of name servers (typically at least two, for redundancy) that are authoritative for the zone that contains the domain. The registrar provides the names of these servers to the domain registry for the top level domain containing the zone. The domain registry in turn configures the authoritative name servers for that top level domain with delegations for each server for the zone. If the fully-qualified domain name of any name server for a zone appears within that zone, the zone administrator provides IP addresses for that name server, which are installed in the parent zone as glue records; otherwise, the delegation consists of the list of NS records for that zone.
A name server server indicates that its response is authoritative by setting the Authoritative Answer (AA) bit in the response to a query on a name for which it is authoritative. Name servers providing answers for which they are not authoritative (for example, name servers for parent zones), do not set the AA bit.
Unbound can be setup to supply authoritative names for a local LAN. For example, if we wanted to hostname xbox360.home.lan to resolve to the private ip address 10.0.0.3 .
HELPFUL HINT: Make sure to take a look at our simple DNS Verify script. It will verify forward and reverse name resolution of you local LAN hostnames. This is a very quick way to make sure your DNS setup is correctly.

Unbound DNS install

The first step is to install Unbound. We suggest installing Unbound through your package manager for easy installation and regular version updates. Most modern operating systems have prebuilt packages (rpm, deb, tgz). You can always install Unbound from source if you want to. Either way you decide to install, you want to get the most recent version you can. Here are a few package manager lines just to help out:
## FreeBSD 12
 pkg install unbound     (for libevent enabled Unbound)
  -OR-
 /usr/sbin/local-unbound (base install)

## FreeBSD 11 and earlier
 portmaster dns/unbound
  -OR-
 pkg install unbound

## CentOS
 yum install unbound

## Ubuntu
 apt-get install unbound

## OpenBSD
 pkg_add -i unbound

Unbound DNS configuration examples

Simple recursive caching DNS, UDP port 53 unencrypted (example 1)

This is the most simple, but fully functional Unbound example and a perfect solution for a small LAN with a few hundred machines accessing the Internet. The configuration will query public DNS servers for answers made by localhost or ips on the LAN at 10.0.0.0/8 and cache the results. The log level is at one(1) which will log any errors and print out statistics only when the Unbound daemon is shut down.
Notice that the forward-zone area. You can use the forward-zone directive to query resolving DNS servers. For example, we have Google Public DNS, Quad9 and Cloudflare DNS configured here. You can replace those ips with the DNS servers of your ISP if you wanted to.
All you need to do is make sure Unbound is installed. Then place the following unbound.conf in place of your copy; i.e on the OpenBSD install the config file is located in /var/unbound/etc/unbound.conf , on FreeBSD 10.0 and earlier /usr/local/etc/unbound/unbound.conf and FreeBSD 12 /var/unbound/unbound.conf or /usr/local/etc/unbound/unbound.conf if installed from the FreeBSd pkg's. Then just start up the unbound daemon depending on your OS. That's it.
## Simple recursive caching DNS, UDP port 53
## unbound.conf -- https://calomel.org
#
server:
  access-control: 10.0.0.0/8 allow
  access-control: 127.0.0.0/8 allow
  access-control: 192.168.0.0/16 allow
  aggressive-nsec: yes
  cache-max-ttl: 14400
  cache-min-ttl: 1200
  hide-identity: yes
  hide-version: yes
  interface: 0.0.0.0
  prefetch: yes
  rrset-roundrobin: yes
# tls-cert-bundle: "/usr/local/share/certs/ca-root-nss.crt"
  use-caps-for-id: yes
  verbosity: 1

  # Unbound from pkg built with libevent; increase threads and slabs to the
  # number of real cpu cores to reduce lock contention. Increase cache size to
  # store more records and allow each thread to serve an increased number of
  # concurrent client requests.
# num-threads: 4
# msg-cache-slabs: 4
# rrset-cache-slabs: 4
# infra-cache-slabs: 4
# key-cache-slabs: 4
# msg-cache-size: 256M
# rrset-cache-size: 512M
# outgoing-range: 8192
# num-queries-per-thread: 4096

forward-zone:
   name: "."
   forward-addr: 1.0.0.1@53#one.one.one.one
   forward-addr: 1.1.1.1@53#one.one.one.one
   forward-addr: 8.8.4.4@53#dns.google
   forward-addr: 8.8.8.8@53#dns.google
   forward-addr: 9.9.9.9@53#dns.quad9.net
   forward-addr: 149.112.112.112@53#dns.quad9.net

DNS over TLS, recursive caching DNS, TCP port 853 ENCRYPTED (example 2)

Similar to the simple cache server above, make sure unbound is installed and locate the path for unbound.conf in your distribution. For example, on FreeBSD 11 and 12 the configuration file is placed under /var/unbound/unbound.conf . The following configuration will query the DNS servers listed under the forward-zone using an encrypted TLS connection over port 853. Unbound on FreeBSD 12 is built against OpenSSL 1.1.1 which supports TLS 1.3 . The ssl-upstream directive tells unbound to use TLS only and never send DNS queries in the clear. TLS offers cryptographic hashes which further verifies the data in transit has not been modified, corrupted or maliciously re-written. For additional information check out APNIC's DNS Privacy blog post. Note that "DNS over TLS" are plain DNS queries in TCP wireformat to port 853 using TLS encryption which is different than "DNS over HTTPS" which is a standard http call to an HTTPS server on port 443 using TLS encryption. Make sure to set the proper path to the root.key file for the trust-anchor-file directive so that unbound can validate ('ad' flag) DNSEEC queries; for example, "drill -D calomel.org". The tls-cert-bundle directive should point to your local root certificate file to allow unbound to validate TLS connections. On FreeBSD use "pkg install ca_root_nss" to install the root certificate bundle from the Mozilla Project.
NOTE: In order for Unbound to validate the DNS server certificate, the proper path to the "trust-anchor-file:" must be defined for your OS. For example, The default location of the root certificate bundle is "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" on Fedora, "/etc/ssl/certs/ca-certificates.crt" on Debian/Ubuntu and the FreeBSD public certificate bundle is located at "/usr/local/share/certs/ca-root-nss.crt" after installing Mozilla's public certificate bundle using "pkg install ca_root_nss". Once the certificate bundle is defined, the "forward-addr" format must be the dns ip address, "@", port number 853, "#", the valid public hostname of the DNS server in order for unbound to use the tls-cert-bundle to validate the dns server certificate. Without the valid public hostname, DNS over TLS queries to the Google DNS servers will fail with an error similar to, "error: ssl handshake failed crypto error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed".
## DNS Over TLS, Simple ENCRYPTED recursive caching DNS, TCP port 853
## unbound.conf -- https://calomel.org
## FreeBSD 12 unbound config
#
server:
  access-control: 10.0.0.0/8 allow
  access-control: 192.168.0.0/16 allow
 #access-control: fddd::/48 allow
  aggressive-nsec: yes
 #auto-trust-anchor-file: /usr/local/etc/unbound/root.key
  cache-max-ttl: 14400
  cache-min-ttl: 1200
  chroot: /usr/local/etc/unbound
  directory: /usr/local/etc/unbound
  do-ip4: yes
  do-ip6: yes
  do-tcp: yes
  hide-identity: yes
  hide-version: yes
  interface: 0.0.0.0
 #interface: ::0
  pidfile: /var/run/local_unbound.pid
  port: 53
  prefetch: yes
  rrset-roundrobin: yes
  tls-cert-bundle: "/usr/local/share/certs/ca-root-nss.crt"
  use-caps-for-id: yes
  username: unbound

  # Unbound from pkg built with libevent; increase threads and slabs to the
  # number of real cpu cores to reduce lock contention. Increase cache size to
  # store more records and allow each thread to serve an increased number of
  # concurrent client requests.
# num-threads: 4
# msg-cache-slabs: 4
# rrset-cache-slabs: 4
# infra-cache-slabs: 4
# key-cache-slabs: 4
# msg-cache-size: 256M
# rrset-cache-size: 512M
# outgoing-range: 8192
# num-queries-per-thread: 4096

 # forward-addr format must be ip "@" port number "#" followed by the valid public hostname
 # in order for unbound to use the tls-cert-bundle to validate the dns server certificate.
 forward-zone:
   name: "."
   forward-tls-upstream: yes
   forward-addr: 1.0.0.1@853#one.one.one.one
   forward-addr: 1.1.1.1@853#one.one.one.one
   forward-addr: 8.8.4.4@853#dns.google
   forward-addr: 8.8.8.8@853#dns.google
   forward-addr: 9.9.9.9@853#dns.quad9.net
   forward-addr: 149.112.112.112@853#dns.quad9.net

Authoritative, validating, recursive caching DNS (example 3)

This example is a fully functional authoritative, validating, recursive caching DNS server for a local private LAN and very close to the one we personally use. Unbound will recursively query any hostname from the root DNS servers it does not have a cached copy of. It will validate the queries using DNSSEC and 0x20-encoded random bits to foil spoof attempts. Finally, this server will be the authoritative DNS for a few hostnames on our local private "home.lan" segment.
To get started there are few configuration steps to take. The first is to get a copy of the latest root DNS server listing called root.hints. The second is to get the DNSSEC root trusted key setup. Third, you need to setup any hostnames and ip address of your LAN. These steps are quite easy so lets do them first.

Pre setup

This example install is for OpenBSD. The install path is "/var/unbound/etc/" for all configuration files. You can place the following files anywhere as long as you tell Unbound where they reside. So, you can use this as an example for Ubuntu, RHEL and CentOS as well.
Step 1, root-hints: is the file which contains the listing of primary root DNS servers. Unbound does have a listing of root DNS servers in its code, but we want to make sure we have the most up to date copy. We normally update our copy once every six(6) months.
To query a hostname Unbound has to start at the top at the root DNS servers and work its way down to the authoritative servers (see the definition of a resolving DNS server above). Download a copy of the root hints from Internic and place it in the /var/unbound/etc/root.hints file. This file will be called by the root-hints: directive in the unbound.conf file.
wget https://www.internic.net/domain/named.root -O /var/unbound/etc/root.hints
Step 2, auto-trust-anchor-file: which contains the key for the root server so DNSSEC can be validated. We need to tell Unbound that we trust the root server so it can start to develop a chain of trust down to the hostname we want resolved and validated using DNSSEC.
For this example, we create a file in "/var/unbound/etc/root.key" and put the following line in it. This is the 2017 trust anchor for the root zone. You can independently verify the root zone anchor by going to the IANA.org Index of /root-anchors.
. IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
Also make sure that the "/var/unbound/etc/root.key" is owned by the user the Unbound daemon is running as. Our user on the OpenBSD install is "_unbound". Then make sure the "_unbound" user can write to the file.
Step 3, locally served zones are the hostnames and ips of the local LAN you want Unbound to be authoritative for. Scroll down the unbound.conf and look for the local-zone, local-data and local-data-ptr directives. You just need to change these to match the names of the machines and ip addresses of your network.
In the example we have the hostname firewall.home.lan resolving to the ip address 10.0.0.1. We also have a reverse lookup allowing 10.0.0.1 to resolve back to the hostname firewall.home.lan. There are others just to give you a good idea of the format.
The pre setup is done. We now have a root DNS hints file of the primary root servers. We also have a trust anchor file of the root server so Unbound can create a chain of trust for DNSSEC. In the future as the root DNS key changes Unbound will automatically update the root.key file for us. Lastly, we have a few hostnames and ips of LAN machines we want to authoritatively resolve.

Authoritative, validating, recursive caching DNS setup and install

All you need to do is make sure unbound is installed. Then place the following unbound.conf in place of your copy; i.e. on the OpenBSD install it is located in /var/unbound/etc/unbound.conf . Make sure the root hints and the trust anchor is in place as directed by the instructions above. Then just start up the unbound daemon by typing "unbound". That's it.

unbound.conf

## Authoritative, validating, recursive caching DNS
## unbound.conf -- https://calomel.org
#
server:
  # log verbosity
    verbosity: 1

  # specify the interfaces to answer queries from by ip-address.  The default
  # is to listen to localhost (127.0.0.1 and ::1).  specify 0.0.0.0 and ::0 to
  # bind to all available interfaces.  specify every interface[@port] on a new
  # 'interface:' labeled line.  The listen interfaces are not changed on
  # reload, only on restart.
    interface: 127.0.0.1

  # port to answer queries from
    port: 53

  # Enable IPv4, "yes" or "no".
    do-ip4: yes

  # Enable IPv6, "yes" or "no".
    do-ip6: no

  # Enable UDP, "yes" or "no".
    do-udp: yes

  # Enable TCP, "yes" or "no". If TCP is not needed, Unbound is actually
  # quicker to resolve as the functions related to TCP checks are not done.i
  # NOTE: you may need tcp enabled to get the DNSSEC results from *.edu domains
  # due to their size.
    do-tcp: yes

  # control which client ips are allowed to make (recursive) queries to this
  # server. Specify classless netblocks with /size and action.  By default
  # everything is refused, except for localhost.  Choose deny (drop message),
  # refuse (polite error reply), allow (recursive ok), allow_snoop (recursive
  # and nonrecursive ok)
    access-control: 10.0.0.0/8 allow
    access-control: 127.0.0.0/8 allow
    access-control: 192.168.0.0/16 allow

  # Read  the  root  hints from this file. Default is nothing, using built in
  # hints for the IN class. The file has the format of  zone files,  with  root
  # nameserver  names  and  addresses  only. The default may become outdated,
  # when servers change,  therefore  it is good practice to use a root-hints
  # file.  get one from https://www.internic.net/domain/named.root 
    root-hints: "/var/unbound/etc/root.hints"

  # enable to not answer id.server and hostname.bind queries.
    hide-identity: yes

  # enable to not answer version.server and version.bind queries.
    hide-version: yes

  # Will trust glue only if it is within the servers authority.
  # Harden against out of zone rrsets, to avoid spoofing attempts. 
  # Hardening queries multiple name servers for the same data to make
  # spoofing significantly harder and does not mandate dnssec.
    harden-glue: yes

  # Require DNSSEC data for trust-anchored zones, if such data is absent, the
  # zone becomes  bogus.  Harden against receiving dnssec-stripped data. If you
  # turn it off, failing to validate dnskey data for a trustanchor will trigger
  # insecure mode for that zone (like without a trustanchor).  Default on,
  # which insists on dnssec data for trust-anchored zones.
    harden-dnssec-stripped: yes

  # Use 0x20-encoded random bits in the query to foil spoof attempts.
  # http://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
  # While upper and lower case letters are allowed in domain names, no significance
  # is attached to the case. That is, two names with the same spelling but
  # different case are to be treated as if identical. This means calomel.org is the
  # same as CaLoMeL.Org which is the same as CALOMEL.ORG.
    use-caps-for-id: yes

  # the time to live (TTL) value lower bound, in seconds. Default 0.
  # If more than an hour could easily give trouble due to stale data.
    cache-min-ttl: 3600

  # the time to live (TTL) value cap for RRsets and messages in the
  # cache. Items are not cached for longer. In seconds.
    cache-max-ttl: 86400

  # perform prefetching of close to expired message cache entries.  If a client
  # requests the dns lookup and the TTL of the cached hostname is going to
  # expire in less than 10% of its TTL, unbound will (1st) return the ip of the
  # host to the client and (2nd) pre-fetch the dns request from the remote dns
  # server. This method has been shown to increase the amount of cached hits by
  # local clients by 10% on average.
    prefetch: yes

  # number of threads to create. 1 disables threading. This should equal the number
  # of CPU cores in the machine. Our example machine has 4 CPU cores.
    num-threads: 4


  ## Unbound Optimization and Speed Tweaks ###

  # the number of slabs to use for cache and must be a power of 2 times the
  # number of num-threads set above. more slabs reduce lock contention, but
  # fragment memory usage.
    msg-cache-slabs: 8
    rrset-cache-slabs: 8
    infra-cache-slabs: 8
    key-cache-slabs: 8

  # Increase the memory size of the cache. Use roughly twice as much rrset cache
  # memory as you use msg cache memory. Due to malloc overhead, the total memory
  # usage is likely to rise to double (or 2.5x) the total cache memory. The test
  # box has 4gig of ram so 256meg for rrset allows a lot of room for cacheed objects.
    rrset-cache-size: 256m
    msg-cache-size: 128m

  # buffer size for UDP port 53 incoming (SO_RCVBUF socket option). This sets
  # the kernel buffer larger so that no messages are lost in spikes in the traffic.
    so-rcvbuf: 1m

  ## Unbound Optimization and Speed Tweaks ###


  # Enforce privacy of these addresses. Strips them away from answers.  It may
  # cause DNSSEC validation to additionally mark it as bogus.  Protects against
  # 'DNS Rebinding' (uses browser as network proxy).  Only 'private-domain' and
  # 'local-data' names are allowed to have these private addresses. No default.
    private-address: 192.168.0.0/16
    private-address: 172.16.0.0/12
    private-address: 10.0.0.0/8

  # Allow the domain (and its subdomains) to contain private addresses.
  # local-data statements are allowed to contain private addresses too.
    private-domain: "home.lan"

  # If nonzero, unwanted replies are not only reported in statistics, but also
  # a running total is kept per thread. If it reaches the threshold, a warning
  # is printed and a defensive action is taken, the cache is cleared to flush
  # potential poison out of it.  A suggested value is 10000000, the default is
  # 0 (turned off). We think 10K is a good value.
    unwanted-reply-threshold: 10000

  # IMPORTANT FOR TESTING: If you are testing and setup NSD or BIND  on
  # localhost you will want to allow the resolver to send queries to localhost.
  # Make sure to set do-not-query-localhost: yes . If yes, the above default
  # do-not-query-address entries are present.  if no, localhost can be queried
  # (for testing and debugging). 
    do-not-query-localhost: no

  # File with trusted keys, kept up to date using RFC5011 probes, initial file
  # like trust-anchor-file, then it stores metadata.  Use several entries, one
  # per domain name, to track multiple zones. If you use forward-zone below to
  # query the Google DNS servers you MUST comment out this option or all DNS
  # queries will fail.
  # auto-trust-anchor-file: "/var/unbound/etc/root.key"

  # Should additional section of secure message also be kept clean of unsecure
  # data. Useful to shield the users of this validator from potential bogus
  # data in the additional section. All unsigned data in the additional section
  # is removed from secure messages.
    val-clean-additional: yes

  # Blocking Ad Server domains. Google's AdSense, DoubleClick and Yahoo
  # account for a 70 percent share of all advertising traffic. Block them.
  # local-zone: "doubleclick.net" redirect
  # local-data: "doubleclick.net A 127.0.0.1"
  # local-zone: "googlesyndication.com" redirect
  # local-data: "googlesyndication.com A 127.0.0.1"
  # local-zone: "googleadservices.com" redirect
  # local-data: "googleadservices.com A 127.0.0.1"
  # local-zone: "google-analytics.com" redirect
  # local-data: "google-analytics.com A 127.0.0.1"
  # local-zone: "ads.youtube.com" redirect
  # local-data: "ads.youtube.com A 127.0.0.1"
  # local-zone: "adserver.yahoo.com" redirect
  # local-data: "adserver.yahoo.com A 127.0.0.1"
  # local-zone: "ask.com" redirect
  # local-data: "ask.com A 127.0.0.1"


  # Unbound will not load if you specify the same local-zone and local-data
  # servers in the main configuration as well as in this "include:" file. We
  # suggest commenting out any of the local-zone and local-data lines above if
  # you suspect they could be included in the unbound_ad_servers servers file.
  #include: "/etc/unbound/unbound_ad_servers"

  # locally served zones can be configured for the machines on the LAN.

    local-zone: "home.lan." static

    local-data: "firewall.home.lan.  IN A 10.0.0.1"
    local-data: "laptop.home.lan.    IN A 10.0.0.2"
    local-data: "xboxone.home.lan.   IN A 10.0.0.3"
    local-data: "ps4.home.lan.       IN A 10.0.0.4"
    local-data: "dhcp5.home.lan.     IN A 10.0.0.5"
    local-data: "dhcp6.home.lan.     IN A 10.0.0.6"
    local-data: "dhcp7.home.lan.     IN A 10.0.0.7"

    local-data-ptr: "10.0.0.1  firewall.home.lan"
    local-data-ptr: "10.0.0.2  laptop.home.lan"
    local-data-ptr: "10.0.0.3  xboxone.home.lan"
    local-data-ptr: "10.0.0.4  ps4.home.lan"
    local-data-ptr: "10.0.0.5  dhcp5.home.lan"
    local-data-ptr: "10.0.0.6  dhcp6.home.lan"
    local-data-ptr: "10.0.0.7  dhcp7.home.lan"

  # Unbound can query your NSD or BIND server for private domain queries too.
  # On our NSD page we have NSD configured to serve the private domain,
  # "home.lan". Here we can tell Unbound to connect to the NSD server when it
  # needs to resolve a *.home.lan hostname or IP.
  #
  # private-domain: "home.lan"
  # local-zone: "0.0.10.in-addr.arpa." nodefault
  # stub-zone:
  #      name: "home.lan"
  #      stub-addr: 10.0.0.111@53

  # If you have an internal or private DNS names the external DNS servers can
  # not resolve, then you can assign domain name strings to be redirected to a
  # seperate dns server. For example, our comapny has the domain
  # organization.com and the domain name internal.organization.com can not be
  # resolved by Google's public DNS, but can be resolved by our private DNS
  # server located at 1.1.1.1. The following tells Unbound that any
  # organization.com domain, i.e. *.organization.com be dns resolved by 1.1.1.1
  # instead of the public dns servers.
  #
  # forward-zone:
  #    name: "organization.com"
  #    forward-addr: 1.1.1.1        # Internal or private DNS

  # Use the following forward-zone to forward all queries to Google DNS,
  # OpenDNS.com or your local ISP's dns servers for example. To test resolution
  # speeds use "drill calomel.org @8.8.8.8" and look for the "Query time:" in
  # milliseconds.
  #
  forward-zone:
   name: "."
   forward-addr: 1.1.1.1@53#one.one.one.one
   forward-addr: 8.8.8.8@53#dns.google
   forward-addr: 9.9.9.9@53#dns.quad9.net
   forward-addr: 1.0.0.1@53#one.one.one.one
   forward-addr: 8.8.4.4@53#dns.google
   forward-addr: 149.112.112.112@53#dns.quad9.net

#
#
## Authoritative, validating, recursive caching DNS
## unbound.conf -- https://calomel.org
Calomel.org offers a OpenBSD Pf Firewall "how to" ( pf.conf ) if you need it. We cover a HFSC scheduler example with a DNS priority queue integrated into a working pf.conf rule set.

Unbound DNS thoughts, ideas and theories

Unbound DNS cluster with BIND or NSD master server

Unbound is the perfect front line soldier for DNS queries from LAN clients. It is fast, reliable, stable and very secure. BIND (named) or NSD (Name Server Daemon) can be kept on the back end network to be an authoritative DNS to the Unbound cluster. This way you keep your primary DNS data segregated and unencumbered on the BIND or NSD server while the Unbound cluster servers do the resolving, caching and validation of zones for clients.
The idea is to have a few Unbound validating, recursive and caching DNS servers which LAN clients can query. Then use BIND (named) as an authoritative server which can resolve internal LAN names only. LAN clients will NEVER access the BIND DNS server and BIND will never go out to the Internet. BIND's only job is to serve internal names to the Unbound DNS server cluster. The Unbound cluster will serve all LAN clients. If Unbound needs to resolve a private ip it will ask the BIND server for ips and then cache the response. If the client needs an external ip, lets say from google.com or cnn.com, Unbound will recursively query the Internet root DNS servers and cache the response.
Here is a rough ASCII diagram of the setup. LAN Clients are all the internal machines of the local area network (LAN). The Internet DNS is basically any external DNS server. The entries for Unbound #1 through #3 are separate machines with Unbound running on them. The final machine is the Private BIND LAN DNS.
                 INTERNET DNS
                       |
                       |
                -- Unbound #1 --
              /                  \   private authoritative only
LAN Clients -- --- Unbound #2 --  --   BIND or NSD dns server
              \                  /        ( 10.0.0.111 )
                -- Unbound #3 --
The configuration is quite easy. First take a copy of the Unbound example #3 called "Authoritative, validating, recursive caching DNS" from above. We will be adding directives to the bottom of that config. We just need to add the stub-zone directives for any internal names we want unbound to ask BIND about. Any zones not pointing to our authoritative server will go out to the root DNS servers for an answer. BTW, since BIND is going to be our authentication server you can comment out any of the local-zone, local-data and local-data-ptr directives.
Lets say our private NSD or BIND server is authoritative for this internal LAN domain:
  • home.lan
We need to tell the Unbound cluster servers that if they are looking for the private home.lan domain to ask the authoritative DNS server, otherwise go check with the root DNS servers. The NSD server's ip is 10.0.0.111 as in the ASCII diagram.
Pay special attention to the stub-zone directive we are using. Stub-zone is only used to point queries to an authoritative server like a NSD dns server. The forward-zone directive can only be used to point queries to a resolving dns server like OpenDNS.com or you local ISP's caching server. The two are not interchangeable.
NOTE: We will be using the NSD configuration on the NSD (Name Server Daemon) Tutorial page with this example.
## Add this to the bottom of example #2's unbound.conf configuration
## Check out our NSD Tutorial at https://calomel.org/nsd_dns.html 

   # This local-zone line will tell unbound that private addresses like
   # 10.0.0.0/8 can send queries to a stub zone authoritative server like NSD.
   local-zone: "10.in-addr.arpa." nodefault

   # This is the FORWARD lookup stub zone pointing to the NSD authoritative
   # server. When a client queries for firewall.home.lan the question is sent
   # to the NSD server located at 10.0.0.111 and NSD returns the answer
   # "10.0.0.1". 
   stub-zone:
        name: "home.lan"
        stub-addr: 10.0.0.111

   # This is the REVERSE (rDNS) dns lookup for the home.lan zone. When a client
   # asks for the hostname belonging to the ip address 10.0.0.1 the NSD
   # authoritative server at 10.0.0.111 will send back the answer
   # "firewall.home.lan".
   stub-zone:
        name: "10.in-addr.arpa."
        stub-addr: 10.0.0.111
That's about it. A client asking for an internal dns hostname like, laptop.home.lan.lan will make Unbound query the NSD server (10.0.0.111); the answer will be cached by Unbound for later queries. Any other queries for external hostnames (calomel.org for example) from LAN clients will have Unbound go to Internet servers for the answer. Clients can now query the Unbound cluster for any hostnames they want and we do not have to worry about our primary NSD dns servers being abused or overloaded. This setup is mainly designed to segregate the authoritative server off by itself and keep the primary DNS configuration safe.

Dnsspoof or 'Split horizon' with Unbound DNS

Dnsspoof is the ability to reply with an ip address which is NOT normally associated with a hostname. This is a limited kind of "Split horizon" functionality. The fully generalized form of split-horizon DNS allows the IP number associated with a hostname to vary in a manner dependent upon the network from which the DNS query is made. Unbound does not provide full support for split-horizon DNS because it will not vary its response based on the querying network. But unbound does support DNS spoofing, altering the normal response to a DNS query on all networks unbound serves. For example, lets say you have web server accessible to the internal and external networks. The webserver is in a DMZ on the internal LAN. The public uses the external hostname webserver.example.com which resolves to the ip 111.222.333.444 which traverses a firewall to the DMZ. The problem is when your internal LAN clients would also like to use webserver.example.com . The internal clients traffic would have to go out the firewall, hit the router and then travel back into the firewall into the DMZ thus adding a lot of unnecessary traffic to the external connection. Wouldn't it be nice just to send internal clients directly to the internal DMZ ip address?
We can setup Unbound to spoof the dns query of LAN clients so instead of getting the external address for the external name, they receive an internal ip for the external name. webserver.example.com which normally resolves to 111.222.333.444 now resolves 10.0.0.222 . 10.0.0.222 would be the same web server which is located on the inside of the firewall in a DMZ.
## DnsSpoof of webserver.example.com (exact domain name match)
local-data: "webserver.example.com. IN A 10.0.0.222"
DnsSpoof'ing might also be useful to stop LAN clients from going to sites that might not be appropriate to go to or not allowed on your network. You can also use this method to stop your clients from going to ad servers. For example we do not want anyone going to facebook.com or doubleclick.net, or even any of its sub domains, instead giving them the ip address 10.0.0.111 of our local web server explaining our Internet terms of use.
## DnsSpoof of unwanted or restricted sites
local-zone: "doubleclick.net" redirect
local-data: "doubleclick.net A 10.0.0.111"

local-zone: "facebook.com" redirect
local-data: "facebook.com A 10.0.0.111"
The dns query by an internal client would then result in the following differences. Note that using the redirect method will now redirect all sub domains to 10.0.0.111 as well.
## Normal DNS resolution for facebook.com
$  host facebook.com
facebook.com has address 69.63.189.16
facebook.com has address 69.63.181.12
facebook.com has address 69.63.189.11
facebook.com mail is handled by 10 smtpin.mx.facebook.com.

## DnsSpoof of facebook.com
$  host facebook.com
facebook.com has address 10.0.0.111

## Sub domains are also redirected
$  host ads.facebook.com
ads.facebook.com has address 10.0.0.111

Dnsspoof with yoyo.org, anti-advertising list

Yoyo.org supplies a list of known advertising servers in a convenient text file which is updated periodically and pre-formated for unbound. The list will configure Unbound to redirect the ad server hostnames to localhost (127.0.0.1). Use curl to download the list to a new file called "unbound_ad_servers" and sed to clean up the HTML headers in the output. Once this file is in place you just need to add an "include:" directive to your unbound.conf pointing to the full path of the "unbound_ad_servers" file. Unbound will then redirect all 2400+ advertising servers to localhost keeping most, if not all advertising away from your systems. Simple, but powerful.
NOTE: Make sure you remove any "local-zone" entries that may be duplicated in the Yoyo ad server list. For example, if you have "local-zone: "doubleclick.net" redirect" in the unbound.conf and yoyo has the same "local-zone: "doubleclick.net" redirect" in their list then Unbound will fail to start due to the conflict.
# download the anti-ad server list to Unbound's configuration directory. 

curl -sS -L --compressed "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintro=0&mimetype=plaintext" > /etc/unbound/unbound_ad_servers

#  then add an include line to your unbound.conf pointing to the full path of
#  the unbound_ad_servers file:
#
#   include: /etc/unbound/unbound_ad_servers
#

Questions?

Is the system time critical to Unbounds operation ?
Yes. Unbound is very paranoid about its DNS records. If a record is out of date, or even worse, if the record exists in some future date then Unbound will not resolve that domain correctly.
A common problem is you have to reboot the system and the BIOS time is incorrect. Then Unbound is started on boot and uses the current incorrect system time. You then set the correct time manually. Now either all of your dns records are expired because the time was set to the past or the records are illegal since the time is set to the future.
Make sure that the system time of your machine is as correct as possible by using NTPD of a GPS time server. Then start Unbound when the time is correct.
What random number generator PRNG does Unbound use ?
Unbound uses a cryptographic strength random number generator. The arc4random() generator from OpenBSD is used or Yarrow on FreeBSD. This means that predicting the random numbers generated by unbound is equivalent to cracking an encryption cipher. The random number generator is seeded with entropy. Real entropy from the system /dev/random is used to seed the random number generator. Thus, the starting values of the random number generator cannot easily be predicted. The OpenBSD package install of Unbound uses /dev/arandom instead for a more random entropy and faster seed creation.
What is dns-0x20 capitalization randomization ?
Capitalization randomization is also called dns-0x20. This is an experimental resilience method which uses upper and lower case letters in the question hostname to obtain randomness. On average adding about 7 or 8 bits of entropy. This method currently has to be turned on by the dns admin manually, as it may result in maybe 0.4% of domains getting no answers due to no support on the authoritative server side. In our second example we enable the directive "use-caps-for-id: yes" for better security using dns-0x20.
All this means is that calomel.org is the same as CaLOMeL.Org which is the same as CALOMEL.ORG. When Unbound sends a query to a remote server it sends the hostname string in random upper and lower characters. The remote server must resolve the hostname as if all the characters were lower case. The remote server must then send the query back to Unbound in the same random upper and lower characters that Unbound sent. If the characters of the hostname in the response are in the same format as the query then the dns-0x20 check is satisfied.
Attackers hoping to poison a Unbound DNS cache must therefore guess the mixed-case encoding of the query and the timing of the return dns answer in addition to all other fields required in a DNS poisoning attack. dns-0x20 increases the difficulty of the attack significantly.
How can I query a DNS server for its software name and version ?
Use the "dig" command. The first line will query the local dns server or resolver located at localhost (127.0.0.1). This example shows the response of Unbound version 1.4.7. The next few lines are some examples of other DNS servers. BTW, If you enable the directives in Unbound to hide the identity (hide-identity and hide-version) of the server as we do on our second example the response will be completely blank.
## Unbound version v1.4.7
dig +short version.bind chaos txt
"unbound 1.4.7"

## Verizon running Vantio v4.4.0.2
dig @151.197.0.38 +short version.bind chaos txt
"Nominum Vantio 4.4.0.2"

## Level 3 is more paranoid.
dig @4.2.2.1 +short version.bind chaos txt
"If you have a legitimate reason for requesting this
info, please contact hostmaster@Level3.net"
How can I easily watch DNS traffic in real time ?
Try a program call "dnstop". It is available though most package managers. Once installed just execute the binary with the argument of the interface you want to watch for DNS traffic. For example, we would execute "dnstop em0" to watch traffic on the external Intel based em0 interface. There a few pages of options in dnstop that can be accessed using the number keys. The author's page has some examples of some DnsTop screen output looks like.
Failover in /etc/resolv.conf is too slow. What can I do ?
The normal timeout to failover from one name server to another in the /etc/resolv.conf file is 5 seconds. This is a bit too long. You can use the "options" directive to set the timeout to 3 tenths of a second. This example also enables "rotate" to load balance the name server queries, sets the attempts to one to only try a name server once before going to the next and sets the threshold for the number of dots which must appear in a name before an initial absolute query will be made.
domain domain.lan
search domain.lan domain.lan2 domain.lan3 domain.lan4
nameserver 192.168.0.1
nameserver 192.168.0.2
options ndots:1 timeout:0.3 attempts:1 rotate
How can I properly benchmark Unbound ?
This was a response on the unbound mail list from Wijngaards, one of the developers, to a user regarding performance testing Unbound and getting the proper results. We have included the thread in its entirety.
...Question: I am currently testing unbound as part of a current project however I'm seeing some wildly different results comparing unbound-control stats to what queryperf results show. For example, I've logged the output of total.num.queries to a file every second and calculated the average result which shows 9474 queries per second, queryperf shows 6945 qps. Both results are from the same test load.
...Answer:
This may surprise you, but this is actually a frequently asked question for the unbound server from people that try to measure its speed. (Boast: this is because of its speed).
I see two explanations. The first, and my experience with others doing benchmarks, is that unbound outperforms queryperf. The second is a buffer overrun.
  • Unbound outperforms queryperf. Thus, it sends back more than queryperf can handle. The measurement you got from queryperf is the speed of queryperf itself.
  • Buffer overruns can be seen with netstat -su. The options so-rcvbuf and so-sndbuf can help you stop the buffer overruns for unbound.
For faster results, http://unbound.net/documentation/howto_optimise.html
...Question: What is the proper way to monitor and benchmark the queries per second on an unbound server?
...Answer: Since unbound outperforms your sender, you must make your sender stronger. Start by using its own computer for the sender (do not run it on the server itself, this server is busy with unbound, and you have configured num-threads to the number of cpus in /proc/cpuinfo so it uses all CPUs, right? Also you want to include the speed of the IP stack in the result). Then add another computer that runs queryperf (you can add up the result qps for the two computers that run queryperf). Add more computers until the qps no longer goes up, or goes down a bit (a denial of service on the unbound server). That is the measured speed. From Jan-Piet Mens (who wrote a book about it), I heard he ended up with a whole classroom of pcs running queryperf .
...Conclusion:
The servers I've been testing are Intel E4500s with 2 GB of RAM and Intel gigabit NICs, they are only on 100 mbit ports however and are routed to through Cisco IP SLA. The test client is on an entirely separate subnet and is an 8 core opteron box with an Intel NIC however I've also run queryperf from multiple sources at once using virtual machines.
The actual queries in my data file are captured from real DNS traffic in our data center, about 50% of the queries end up hitting the cache. I can see caching effects in my graphs as well.
We ended up tweaking the unbound.conf a bit and changed the following settings which more than doubled the performance going from 8.8k qps [queries per second] to over 20k.
# outgoing-range: 4096
outgoing-range: 32768

# so-rcvbuf: 0
so-rcvbuf: 32m

# msg-cache-size: 4m
msg-cache-size: 256m

num-queries-per-thread: 4096

# rrset-cache-size: 4m
rrset-cache-size: 256m

# infra-cache-numhosts: 10000
infra-cache-numhosts: 100000
What is DNS Cache Poisoning ?
Poisoning a DNS resolver refers to the act of inserting fake, often malicious data into the resolvers cache. This can cause website visitors to be redirected from the site (e.g. their banking site) they thought to visit to a different web site, for example a phishing site.
Is DnsSpoof also considered cache poisoning? In fact, it is. The difference is that poisoning is the act of inserting bad data maliciously and dnsspoof'ing is inserting averting data we know about. It is a fine line differentiation depending on who is querying the data.
Unbound implements a number of methods to add random bits to secure queries against malicious deflection. The most important means to add randomness is to vary the port numbers from which the question is asked, another means is to use a hack that randomizes unused bits in the query name. Unbound uses 16 bits for the port randomization. To be precise, about 60000 random ports, avoiding ports below 1024 and avoiding IANA allocated UDP ports to avoid system instability of the server. The port randomization uses the same random number generator as the ID. Unbound takes care that a randomly drawn port is used for one query. Thus every query gets a freshly random port number.
Real protection, where you are not subject to the whims of chance, is achieved by using DNSSEC. DNSSEC uses digital signatures to protect the data. With DNSSEC there is no chance of poisoning, independent of the number of random bits used. Unbound implements the DNSSEC standard as specified in the RFCs ( RFC4034, RFC4035 ). Unbound can act as a validator and can thus check the digital signatures attached in replies. Of course, the domain name owner must have inserted these digital signatures in the first place. In the absence of DNSSEC, unbound attempts to provide very good security. Without digital signatures, randomization and filtering are currently the only options.