Difference between revisions of "Unbound"

From ArchWiki
Jump to: navigation, search
(Configuration: add link to example)
 
(97 intermediate revisions by 20 users not shown)
Line 1: Line 1:
 
[[Category:Domain Name System]]
 
[[Category:Domain Name System]]
Unbound is a validating, recursive, and caching DNS resolver.
+
[[ja:Unbound]]
 +
[[zh-hans:Unbound]]
 +
{{Related articles start}}
 +
{{Related|DNSSEC}}
 +
{{Related|BIND}}
 +
{{Related|DNSCrypt}}
 +
{{Related|dnsmasq}}
 +
{{Related|Pdnsd}}
 +
{{Related articles end}}
 +
[https://unbound.net/ 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.
  
==Installation==
+
== Installation ==
  
Install {{Pkg|unbound}}, and {{Pkg|expat}} which is dependency for [[DNSSEC]]:
+
[[Install]] the {{Pkg|unbound}} package.
pacman -S unbound expat
 
  
==Pre-configuration==
+
Additionally, the {{Pkg|expat}} package is required for [[#DNSSEC validation]].
  
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.  Therefore it is necessary to put a "root hints" file into the unbound config directory. The simplest way to do this is to run the command:
+
== Configuration ==
  
{{ic|wget ftp://FTP.INTERNIC.NET/domain/named.cache -O /etc/unbound/root.hints}}
+
A default configuration is already included at{{ic|/etc/unbound/unbound.conf}}. Additionally, there is a commented sample configuration file with other available options located at {{ic|/etc/unbound/unbound.conf.example}}. The following sections highlight different settings for the configuration file. See {{man|5|unbound.conf|url=http://unbound.net/documentation/unbound.conf.html}} for other settings and more details.
  
It is a good idea to run this 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 setting up a cron job for the task.
+
Unless otherwise specified, any options listed in this section are to be placed under the {{ic|server}} section in the configuration like so:
  
If you are going to use DNSSEC then you will need the root server trust key anchor in the file root.key which you can place in a directory owned by user unbound.  
+
{{hc|/etc/unbound/unbound.conf|
 +
server:
 +
  ...
 +
  ''setting'': ''value''
 +
  ...
 +
}}
  
mkdir /etc/unbound/keys
+
See also [[#Example configuration]].
chown unbound:unbound /etc/unbound/keys
 
  
Then create the file root.key and place it in this directory [/etc/unbound/keys/] and make sure the file root.key is owned by user unbound as below.
+
=== Local DNS server ===
  
The line below is the 2010 trust anchor for the root zone, and this line is the only line in the file root.key. You can independently verify the root zone anchor by going to the IANA.org Index of /root-anchors.
+
If you want to use ''unbound'' as your local DNS server, set your nameserver to {{ic|127.0.0.1}} in your [[resolv.conf]]. You will want to have your nameserver be [[Resolv.conf#Preserve_DNS_settings|preserved]].
  
. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
+
{{Tip|1=A simple way to do this is to install the {{pkg|openresolv}} package and uncomment the line containing {{ic|1=name_servers=127.0.0.1}} in {{ic|/etc/resolvconf.conf}}. Then run {{ic|resolvconf -u}} to generate {{ic|/etc/resolv.conf}}.}}
  
Once the file is created make unbound the owner:
+
See [[Resolv.conf#Testing]] on how to test your settings.
  
{{ic|# chown unbound:unbound /etc/unbound/keys/root.key}}
+
Check specifically that the server being used is {{ic|127.0.0.1}} after making permanent changes to [[resolv.conf]].
  
 +
You will also need to setup ''unbound'' such that it is [[#Forwarding queries]] to the DNS servers of your choice.
  
If you will want logging for unbound then create a log file which can also be in the same directory, but you can choose any location. One way is then to do as root:
+
=== Root hints ===
  
# touch /etc/unbound/unbound.log
+
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.  
# chown unbound:unbound /etc/unbound/unbound.log
 
  
Then you can include the logging parameter when you set up the main unbound.conf file as below.
+
First point ''unbound'' to the {{ic|root.hints}} file:
  
==Basic configuration==
+
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:
 +
 
 +
{{bc|<nowiki># curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache</nowiki>}}
 +
 
 +
It is a good idea to update {{ic|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.
 +
 
 +
=== DNSSEC validation ===
 +
 
 +
To use [[DNSSEC]] validation, point ''unbound'' to the server trust anchor file by adding the following setting under {{ic|server:}}:
 +
 
 +
{{hc|/etc/unbound/unbound.conf|
 +
trust-anchor-file: trusted-key.key}}
 +
 
 +
Also make sure that if general [[#Forwarding queries]] have been set to DNS servers that do not support DNSSEC, 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 before the address is cached.}}
 +
 
 +
==== Testing validation ====
  
===Unbound configuration===
+
To test if DNSSEC is working, after [[starting]] {{ic|unbound.service}}, do:
  
Unbound is easy to configure. In the directory /etc/unbound/ there is a sample config file [unbound.conf.example] which can be copied to /etc/unbound/unbound.conf and with the adjustments to the file for your own needs it is enough to run on both IPv4 and IPv6 without access restrictions. Once copied to unbound.conf and then uncomment lines or add in lines as needed.
+
$ unbound-host -C /etc/unbound/unbound.conf -v sigok.verteiltesysteme.net
  
For the case where you want the unbound server to listen to requests from the machine that it is running on then make sure that the line defining which address it is going to listen on is included:
+
The response should be the ip address with the word {{ic|(secure)}} next to it.
  
  interface: 127.0.0.1
+
  $ unbound-host -C /etc/unbound/unbound.conf -v sigfail.verteiltesysteme.net
  
It is also important to include a line to point to the root.hints file that was prepared before editing the unbound.conf file:
+
Here the response should include {{ic|(BOGUS (security failure))}}.
  
  root-hints: "/etc/unbound/root.hints"
+
Additionally you can use ''drill'' to test the resolver as follows:
 +
 
 +
$ drill sigfail.verteiltesysteme.net
 +
$ drill sigok.verteiltesysteme.net
 +
 
 +
The first command should give an {{ic|rcode}} of {{ic|SERVFAIL}}. The second should give an {{ic|rcode}} of {{ic|NOERROR}}.
 +
 
 +
==== Automatic updates ====
 +
 
 +
{{ic|trusted-key.key}} can become out of date. To have unbound automatically update the file, use the following instead of the above configuration:
 +
 
 +
{{hc|/etc/unbound/unbound.conf|
 +
auto-trust-anchor-file: trusted-key.key}}
 +
 
 +
Additionally, the {{ic|unbound}} user needs write permissions to the directory:
 +
 
 +
  # chown root:unbound /etc/unbound
 +
# chmod 775 /etc/unbound
 +
 
 +
Lastly, one can also automatically check for updates before unbound is run by adding the following to the systemd unit under the {{ic|[Service]}} section using a [[drop-in snippet]]:
 +
 
 +
ExecStartPre=/usr/bin/unbound-anchor -a /etc/unbound/trusted-key.key
 +
 
 +
=== Forwarding queries ===
 +
 
 +
{{Tip|Unbound can be used with [[DNSCrypt]] by setting up forwarding. See [[DNSCrypt#Unbound]].}}
 +
 
 +
If you only want to forward queries to an external DNS server, skip ahead to [[#Forward all remaining requests]].
 +
 
 +
==== Allow local network to use DNS ====
 +
 
 +
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''
  
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 the line: private-address for say the 10. or 192.168. networks as:  
+
For example:
  
{{ic|private-address: 10.0.0.0/24}}
+
private-address: 10.0.0.0/24
  
or
+
{{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.}}
  
{{ic|private-address: 192.168.0.0/16}}
+
==== Include local DNS server ====
  
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):
+
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
 
  local-zone: "10.in-addr.arpa." transparent
Line 68: Line 133:
 
  forward-zone:
 
  forward-zone:
 
  name: "mynetwork.com."
 
  name: "mynetwork.com."
  forward-addr: 10.0.0.1       # Home DNS
+
  forward-addr: 10.0.0.1
  
 
  forward-zone:
 
  forward-zone:
Line 74: Line 139:
 
  forward-addr: 10.0.0.1
 
  forward-addr: 10.0.0.1
  
Note that 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 won't 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 don't get any error messages indicating what the problem is if you use a stub zone inappropriately.
+
{{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:
 
You can set up the localhost forward and reverse lookups with the following lines:
Line 87: Line 152:
 
  local-data: "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost."
 
  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 all remaining requests ====
 +
 
 +
To use specific servers for default forward zones that are outside of the local machine and outside of the local network add a forward zone with the name {{ic|.}} to the configuration file. In this example, all requests are forwarded to Google's DNS servers:
  
 
  forward-zone:
 
  forward-zone:
Line 93: Line 160:
 
   forward-addr: 8.8.8.8
 
   forward-addr: 8.8.8.8
 
   forward-addr: 8.8.4.4
 
   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.
+
=== Access control ===
 +
 
 +
You can specify the interfaces to answer queries from by IP address. The default, is to listen on ''localhost''.
 +
 
 +
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 {{ic|access-control}} option:
 +
 
 +
access-control: ''subnet'' ''action''
 +
 
 +
For example:
 +
 
 +
access-control: 192.168.1.0/24 allow
 +
 
 +
''action'' can be one of {{ic|deny}} (drop message), {{ic|refuse}} (polite error reply), {{ic|allow}} (recursive ok), or {{ic|allow_snoop}} (recursive and nonrecursive ok). By default everything is refused except for localhost.
 +
 
 +
== Usage ==
 +
 
 +
=== Starting Unbound ===
 +
 
 +
[[Start/enable]] the {{ic|unbound.service}} systemd service.
 +
 
 +
=== Remotely control Unbound ===
 +
 
 +
''unbound'' ships with the {{ic|unbound-control}} utility which enables us to remotely administer the unbound server. It is similar to the [[Pdnsd#pdnsd-ctl|pdnsd-ctl]] command of {{Pkg|pdnsd}}.
 +
 
 +
==== Setting up unbound-control ====
 +
 
 +
Before you can start using it, the following steps need to be performed:
  
{{Note|OpenDNS strips DNSSEC records from responses. Do not use the above forward zone if you want to enable DNSSEC validation (below).}}
+
1) Firstly, you need to run the following command
  
=== Adding unbound to boot process ===
+
# unbound-control-setup
  
Start the service:
+
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 {{ic|/etc/unbound}} directory.
  
systemctl start unbound
+
2) After that, edit {{ic|/etc/unbound/unbound.conf}} and put the following contents in that. The {{ic|control-enable: yes}} option is necessary, the rest can be adjusted as required.
  
Then enable it so that it starts at boot once you have tested that it works.
+
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"
  
systemctl enable unbound
+
==== Using unbound-control ====
  
=== Set /etc/resolv.conf to use the local DNS server ===
+
Some of the commands that can be used with ''unbound-control'' are:
  
Edit {{ic|/etc/resolv.conf}} (See also [[resolv.conf]]):
+
* print statistics without resetting them
 +
  # unbound-control stats_noreset
  
nameserver 127.0.0.1
+
* dump cache to stdout
 +
  # unbound-control dump_cache
  
Also if you want to be able to use the hostname of local machine names without the fully qualified domain names, then add a line with the local domain such as:
+
* flush cache and reload configuration
 +
  # unbound-control reload
  
domain localdomain.com
+
Please refer to {{ic|man 8 unbound-control}} for a detailed look at the operations it supports.
nameserver 127.0.0.1
 
  
That way you can refer to local hosts such as mainmachine1.localdomain.com as simply mainmachine1 when using the ssh command, but the drill command below still requires the fully qualified domain names in order to perform lookups.
+
== Tips and tricks ==
  
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:
+
=== Block advertising ===
 +
You can use the following file and simply include it in your unbound configuration: [https://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintro=0&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D=&mimetype=plaintext adservers]
 +
{{hc|/etc/unbound/unbound.conf|
 +
server:
 +
...
 +
  include: /etc/unbound/adservers
 +
}}
  
drill @127.0.0.1 www.cnn.com
+
{{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 [http://www.shadowandy.net/2014/04/adblocking-nginx-serving-1-pixel-gif-204-content.htm this page]}}
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.
+
=== Adding an authoritative DNS server ===
  
== Configuring Unbound to Validate DNSSEC ==
+
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.
  
Make sure that the root anchor key file exists as described earlier in the page:
+
=== WAN facing DNS ===
  
Edit unbound.conf, adding the following line to the ''server:'' block:
+
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.
  
    auto-trust-anchor-file: "/etc/unbound/keys/root.key"
+
=== Roothints systemd timer ===
  
Also make sure that if a general forward to the google servers had been in place, then comment them out otherwise dns queries will fail.
+
Here is an example systemd service and timer that update {{ic|root.hints}} monthly using the method in [[#Root hints]]:
  
Restart unbound:
+
{{hc|1=/etc/systemd/system/roothints.service|2=
 +
[Unit]
 +
Description=Update root hints for unbound
 +
After=network.target
  
systemctl restart unbound
+
[Service]
 +
ExecStart=/usr/bin/curl -o /etc/unbound/root.hints <nowiki>https://www.internic.net/domain/named.cache</nowiki>
 +
}}
  
Now dnssec validation will be done if the dns server being queried supports it. Note that including dnssec checking siginificantly increases dns lookup times for initial lookups. Once an address is cached then the lookup is virtually instantaneous.
+
{{hc|1=/etc/systemd/system/roothints.timer|2=
 +
[Unit]
 +
Description=Run root.hints monthly
  
==Adding an authoritative dns server==
+
[Timer]
 +
OnCalendar=monthly
 +
Persistent=true   
 +
 +
[Install]
 +
WantedBy=timers.target}}
  
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.
+
[[Start/enable]] the {{ic|roothints.timer}} systemd timer.
  
==WAN facing dns==
+
=== Sandboxing ===
  
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.
+
{{Remove|If the service works, propose it upstream and link either the upstream bug or the resulting packaged service. Doing so will ensure all users benefit and it is tracked on package updates.}}
  
==Issues concerning num_threads==
+
It is possible to sandbox the default {{ic|unbound.service}} by restricting [[capabilities]] and enforcing  [[Systemd#Sandboxing application environments]] features.
  
The man page for unbound.conf mentions:
+
[[Systemd#Drop-in_files|Edit]] {{ic|unbound.service}} and add the following contents (cf. {{Bug|52700}}):
 +
 
 +
[Service]
 +
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE
 +
MemoryDenyWriteExecute=true
 +
NoNewPrivileges=true
 +
PrivateDevices=true
 +
PrivateTmp=true
 +
ProtectHome=true
 +
ProtectControlGroups=true
 +
ProtectKernelModules=true
 +
ProtectKernelTunables=true
 +
ProtectSystem=strict
 +
ReadWritePaths=/etc/unbound /run
 +
RestrictAddressFamilies=AF_INET AF_UNIX
 +
RestrictRealtime=true
 +
SystemCallArchitectures=native
 +
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete
 +
 
 +
* {{Ic|CapabilityBoundingSet}} defines a whitelisted set of allowed capabilities
 +
** {{Ic|CAP_IPC_LOCK}} = Prevents paging by allowing ''unbound'' to lock data in memory
 +
*** Not a hard requirement for ''unbound'' but rather a personal security choice 
 +
** {{Ic|CAP_NET_BIND_SERVICE}} = Allows for socket binding to privileged ports < 1024
 +
** {{Ic|CAP_SETGID CAP_SETUID}} = Modifies the ''user'' ''group'' to ''nobody'' ''nobody''
 +
** {{Ic|CAP_SYS_CHROOT}} = Allows the creation of a chroot at {{Ic|/etc/unbound}}
 +
* {{Ic|ReadWritePaths}} specifies paths to override from {{Ic|1=ProtectSystem=strict}}
 +
** {{Ic|/etc/unbound}} = Allows the ''ExecStartPre'' command to complete
 +
** {{Ic|/run}} = Allows access to the PID file at {{Ic|/run/unbound.pid}}
 +
* The ''@mount'' system call set includes ''chroot()'' which is required by unbound to build its environment
 +
* {{Ic|mount}} and {{Ic|unmount2}} require explicit listing if they are to be blacklisted apart from the ''@mount'' macro
 +
* The above example blacklists {{Ic|CAP_SYS_ADM}} which should be one of the [https://lwn.net/Articles/486306/ goals of a secure sandbox]
 +
 
 +
=== Example configuration ===
 +
 
 +
The following is a minimal configuration that automatically updates the trusted key file for [[#DNSSEC validation]] and uses [[#Root hints]]. All [[#Forwarding queries|queries are forwarded]] to Google's DNS servers.
 +
 
 +
{{hc|/etc/unbound/unbound.conf|
 +
server:
 +
  auto-trust-anchor-file: /etc/unbound/trusted-key.key
 +
  root-hints: /etc/unbound/root.hints
 +
  forward-zone:
 +
    name: "."
 +
    forward-addr: 8.8.8.8
 +
    forward-addr: 8.8.4.4}}
 +
 
 +
== Troubleshooting ==
 +
 
 +
=== Issues concerning num-threads ===
 +
 
 +
The man page for {{ic|unbound.conf}} mentions:
  
 
       outgoing-range: <number>
 
       outgoing-range: <number>
 
               Number of ports to open. This number of file  descriptors  can  be  opened  per thread.
 
               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 file merely has:
+
and some sources suggest that the {{ic|num-threads}} parameter should be set to the number of cpu cores. The sample {{ic|unbound.conf.example}} file merely has:
  
 
         # number of threads to create. 1 disables threading.
 
         # number of threads to create. 1 disables threading.
 
         # num-threads: 1
 
         # 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 http://www.unbound.net/documentation/howto_optimise.html and the following rule of thumb should work:
+
However it is not possible to arbitrarily increase {{ic|num-threads}} above {{ic|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 {{ic|num-threads}} above {{ic|1}}. If you do wish to do so then refer to [http://www.unbound.net/documentation/howto_optimise.html official documentation] and the following rule of thumb should work:
 +
 
 +
:''Set {{ic|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 {{ic|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 {{ic|1024}} in total. This services more clients at a time. With 1 core, try {{ic|950}}. With 2 cores, try {{ic|450}}. With 4 cores try {{ic|200}}. The {{ic|num-queries-per-thread}} is best set at half the number of the {{ic|outgoing-range}}.
  
Set num-threads equal to the number of CPU cores on the system. E.g. for 4 CPUs with 2 cores each, use 8.
+
Because of the limit on {{ic|outgoing-range}} thus also limits {{ic|num-queries-per-thread}}, it is better to compile with {{Pkg|libevent}}, so that there is no {{ic|1024}} limit on {{ic|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 {{Pkg|unbound}} package.
  
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.
+
== See also ==
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 more 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 arch package.
+
* [https://fedoraproject.org/wiki/Changes/Default_Local_DNS_Resolver Fedora change to Unbound]
 +
* [https://github.com/jodrell/unbound-block-hosts/ Block hosts that contain advertisements]

Latest revision as of 16:51, 22 April 2017

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.

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 unbound.conf(5) 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
  ...

See also #Example configuration.

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.

See Resolv.conf#Testing on how to test your settings.

Check specifically that the server being used is 127.0.0.1 after making permanent changes to resolv.conf.

You will also need to setup unbound such that it is #Forwarding queries to the DNS servers of your choice.

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.

DNSSEC validation

To use DNSSEC validation, point unbound to the server trust anchor file by adding the following setting under server::

/etc/unbound/unbound.conf
trust-anchor-file: trusted-key.key

Also make sure that if general #Forwarding queries have been set to DNS servers that do not support DNSSEC, 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 before the address is cached.

Testing validation

To test if DNSSEC is working, after starting unbound.service, do:

$ unbound-host -C /etc/unbound/unbound.conf -v sigok.verteiltesysteme.net

The response should be the ip address with the word (secure) next to it.

$ unbound-host -C /etc/unbound/unbound.conf -v sigfail.verteiltesysteme.net

Here the response should include (BOGUS (security failure)).

Additionally you can use drill to test the resolver as follows:

$ 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.

Automatic updates

trusted-key.key can become out of date. To have unbound automatically update the file, use the following instead of the above configuration:

/etc/unbound/unbound.conf
auto-trust-anchor-file: trusted-key.key

Additionally, the unbound user needs write permissions to the directory:

# chown root:unbound /etc/unbound
# chmod 775 /etc/unbound

Lastly, one can also automatically check for updates before unbound is run by adding the following to the systemd unit under the [Service] section using a drop-in snippet:

ExecStartPre=/usr/bin/unbound-anchor -a /etc/unbound/trusted-key.key

Forwarding queries

Tip: Unbound can be used with DNSCrypt by setting up forwarding. See DNSCrypt#Unbound.

If you only want to forward queries to an external DNS server, skip ahead to #Forward all remaining requests.

Allow local network to use DNS

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.

Include local DNS server

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."

Forward all remaining requests

To use specific servers for default forward zones that are outside of the local machine and outside of the local network add a forward zone with the name . to the configuration file. In this example, all requests are forwarded to Google's DNS servers:

forward-zone:
  name: "."
  forward-addr: 8.8.8.8
  forward-addr: 8.8.4.4

Access control

You can specify the interfaces to answer queries from by IP address. The default, is to listen on localhost.

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.

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
server:
...
  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
/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.

Sandboxing

Tango-edit-cut.pngThis section is being considered for removal.Tango-edit-cut.png

Reason: If the service works, propose it upstream and link either the upstream bug or the resulting packaged service. Doing so will ensure all users benefit and it is tracked on package updates. (Discuss in Talk:Unbound#)

It is possible to sandbox the default unbound.service by restricting capabilities and enforcing Systemd#Sandboxing application environments features.

Edit unbound.service and add the following contents (cf. FS#52700):

[Service]
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
PrivateTmp=true
ProtectHome=true
ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectSystem=strict
ReadWritePaths=/etc/unbound /run
RestrictAddressFamilies=AF_INET AF_UNIX
RestrictRealtime=true
SystemCallArchitectures=native
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete
  • CapabilityBoundingSet defines a whitelisted set of allowed capabilities
    • CAP_IPC_LOCK = Prevents paging by allowing unbound to lock data in memory
      • Not a hard requirement for unbound but rather a personal security choice
    • CAP_NET_BIND_SERVICE = Allows for socket binding to privileged ports < 1024
    • CAP_SETGID CAP_SETUID = Modifies the user group to nobody nobody
    • CAP_SYS_CHROOT = Allows the creation of a chroot at /etc/unbound
  • ReadWritePaths specifies paths to override from ProtectSystem=strict
    • /etc/unbound = Allows the ExecStartPre command to complete
    • /run = Allows access to the PID file at /run/unbound.pid
  • The @mount system call set includes chroot() which is required by unbound to build its environment
  • mount and unmount2 require explicit listing if they are to be blacklisted apart from the @mount macro
  • The above example blacklists CAP_SYS_ADM which should be one of the goals of a secure sandbox

Example configuration

The following is a minimal configuration that automatically updates the trusted key file for #DNSSEC validation and uses #Root hints. All queries are forwarded to Google's DNS servers.

/etc/unbound/unbound.conf
server:
  auto-trust-anchor-file: /etc/unbound/trusted-key.key
  root-hints: /etc/unbound/root.hints
  forward-zone:
    name: "."
    forward-addr: 8.8.8.8
    forward-addr: 8.8.4.4

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