Use at least version 1.5.5 of Unbound if you want to configure your server with a certificate (as support for intermediate certificates was introduced in this version).
Version 1.6.7 or later is recommended.
Config file
An example configuration file for Unbound that runs DNS-over-TLS on port 853 is below.
server:
directory: "/etc/unbound"
username: unbound
chroot: "/etc/unbound"
# logfile: "/etc/unbound/unbound.log"#uncomment to use logfile.
pidfile: "/etc/unbound/unbound.pid"
# verbosity: 1# uncomment and increase to get more logging.
# listen on all interfaces on port 853, answer queries from the local subnet.
interface: 0.0.0.0@853
interface: ::0@853
tls-service-key: ""
tls-service-pem: ""
tls-port: 853
incoming-num-tcp: 1000# Number of simultaneous incoming TCP connections per thread to allow
# Listen on UDP but still issues queries upstream over UDP.
# Only available in 1.6.7and later
udp-upstream-without-downstream: yes
qname-minimisation: yes # Enable QNAME minimisation to increase client privacy
Depending on how your certificate is issued you may to add the intermediate certificate to your certificate file for clients to be able to validate. For example, if you use Let's encrypt to create your certificate you will need to add the intermediate certificate (found in the /etc/letsencrypt/certs/000_chain.pem file) to the cert file.
If you are using a version earlier than 1.6.7 then Unbound listens on UDP on port 853 with the above configuration. If want to disable UDP both upstream and downstream then use
do_udp: no
however this means all queries authoritative resolvers use TCP which may lead to resolution failures.
Also in older versions of unbound the tls-* parameters where called ssl-*
Docker Image
A docker image kindly provided by Lard de Bruin is also available.
Our home network is connected to more than 10 terminals including smartphones, tablets, client PCs and server machines.
Because of the large number, it is troublesome to use an IP address to access the terminal. I can not remember. Therefore, in order to manage the correspondence between machine names (host names) and IP addresses, we are constructing and operating a DNS (Domain Name System) server dedicated to the home network using BIND, an open source software. .
So far, the "authoritative DNS server function" which mainly manages the correspondence between host names and IP addresses, and "cache DNS servers" for resolving IP addresses from host names mainly when accessing services on the Internet Function has been co-resident on a single BIND server.
However, it is widely known that combining the functions of the authoritative DNS server and the cache DNS server with one server is a bad practice, mainly from the viewpoint of security.
How to improve the security and stability of DNS ~ Is your DNS server OK? ... (Japan Registry Services)
It was used only in the home LAN and was not accessible from the Internet.
By the way, in the article of the other day, we introduced that the next Android P supports DNS over TLS, and Intra, which is an Android application that provides secure DNS service.
As its name suggests, DNS over TLS uses a secure protocol called Transport Layer Security (TLS) instead of UDP or TCP as a transport when resolving IP addresses from host names. By using TLS, you can protect DNS communication from security threats such as eavesdropping and tampering.
On this occasion, I decided to make DNS server of home LAN correspond to DNS over TLS. There are three points below.
Separate functions of authoritative server and cache server and make them separate servers
→ Create a new cache server, leaving only the function of the authoritative server for home LAN in BIND
Cache server sends name resolution request to public DNS server supporting DNS over TLS
→ Protect DNS communication from eavesdropping and tampering
The cache server verifies the name resolution result signature using DNSSEC
→ Protect DNS resource records (results of name resolution) from tampering
Below is a block diagram that summarizes the three points.
Unbound-DNSSEC + DNS over TLS
I decided to use open source software called Unbound instead of BIND for the cache server to be newly built.
In this article, we will explain the steps to build a DNSSEC & DNS over TLS compatible cache server using Unbound on FreeBSD. The following two articles were taken into consideration for construction.
Unbound DNS Tutorial (CALOMEL)
Actually secure DNS over TLS in Unbound (Ctrl blog)
Unbound installation
The first step is to install the required packages.
Note: The FreeBSD base system already includes unbound (unbound 1.5.10 is included with FreeBSD 11.2-RELEASE). However, this version does not seem to support DNS over TLS, so we will install unbound 1.7.3 (as of July 23, 2018) from the package.
pkg install unbound ca_root_nss
In addition to the unbound package, also install the ca_root_nss package. The ca_root_nss package is a collection of root certification authority certificates (root certificates), and is required when unbound authenticates a public DNS server.
Unbound settings
When the unbound package is installed, the sample configuration file (unbound.conf.sample) is placed under / usr / local / etc / unbound. Copy this sample and change the contents as needed, referring to the two sites mentioned above.
Let's look at the main parts of the configuration file. (In the following example, the configuration file is divided into sections, and a total of four files are created. Division of the file is optional, so you may combine them into a single configuration file to your liking. Configuration file will be put together in unbound.conf.)
The complete configuration file is stored in the following GitHub repository, so please refer to it as needed.
Unbound-DNSSEC-DNS-over-TLS-Configuration files for Unbound as a DNS server with DNSSEC validation and DNS over TLS forwarding
/usr/local/etc/unbound/unbound.conf
Unbound's main configuration file. (If the file is divided) Specify include: at the end of this file to read other files.
L24-30: Standby address
interface: :: 0
interface: 0.0.0.0
This is the address that Unbound listens for queries (name resolution requests) from clients. By specifying ::: 0 and 0.0.0.0, both IPv6 and IPv4 listen for queries on all network interfaces.
L53-67: Access control
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: 192.168.0.0/24 allow
access-control: :: / 0 refuse
access-control: :: 1 allow
access-control: :: ffff: 127.0.0.1 allow
access-control: 2001: db8 :: / 64 allow
The cache server constructed in this article is for home LAN only and access from the Internet is not accepted. Let's control access appropriately so that access is possible only from home LAN. In the above settings, only local host and home LAN addresses are allowed. (Please refer to the figure above for the address of the home LAN. This address is for illustration only, so please replace as appropriate for your environment.)
You may think that "access control is unnecessary because it is a server that can not be accessed from the Internet", but be sure to set up access control so that you are not an open resolver.
Specify the file path of the trust anchor required when verifying the resource record (result of name resolution) by DNSSEC. This file is automatically updated by unbound according to the provisions of RFC 5011. (Please refer to the acquisition of the trust anchor mentioned later.)
L102-103: Root certificate
tls-cert-bundle: "/etc/ssl/cert.pem"
Specify the file path of the root certificate necessary to authenticate the DNS server when establishing a TLS connection with the public DNS server to which the query (name resolution request) from the client is transferred. . If you installed the ca_root_nss package, specify the above path.
The following is required only if you are operating a private domain used only in the home LAN and an authoritative server for this domain.
domain-insecure: "example.jp" # Do not perform DNSSEC signature verification
domain-insecure: "0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa" # Do not perform DNSSEC signature verification
local-zone: "168.192.in-addr.arpa." nodefault # Disable default record of address in LAN
Specify that example.jp is a private domain name that operates only on the home LAN. Also specify that this domain does not use DNSSEC. Queries from clients related to this domain will be forwarded to the DNS server specified in stub-zone described later. (This domain name is for illustration only, so please replace as appropriate for your environment.)
/usr/local/etc/unbound/remote-control.conf
Settings related to control of unbound using unbound-control (8) command. In the example of this article, it is set to enable control only from the same host as running unbound.
remote-control:
control-enable: yes
control-interface: /var/run/unbound.ctl
control-use-cert: no
/usr/local/etc/unbound/forward-zone.conf
Specify the DNS server (s) to which the query received from the client is forwarded for each domain name.
In this article's configuration, queries for. (Root domain), that is, all domains are forwarded to the DNS server listed by forward-addr. forward-tls-upstream: By specifying yes, TLS is used to connect to the DNS server.
We selected the servers provided by Cloudflare and Quad 9 from the following articles as public DNS servers. Note that port 853 for DNS over TLS is specified as the port number, not port 53 of DNS standard.
DNS over TLS-Public DNS Servers (Wikipedia)
forward-zone:
name: "."
forward-first: no
forward-tls-upstream: yes # Connect to upstream server with TLS
Add this file when using a private domain dedicated to home LAN. Queries from clients related to private domain (forward lookup and reverse lookup) are sent to the authoritative server for home LAN specified in this file.
Note: It is assumed that DNSSEC and DNS over TLS are not supported for DNS servers configured in the home network.
stub-zone:
name: "example.jp" # For private domain name resolution
stub-addr: 2001: db8 :: 53 # query authority server for home LAN
stub-addr: 192.168.0.53 #
stub-zone:
name: "0.168.192.in-addr.arpa" # The same applies to reverse lookup (IPv4)
stub-addr: 2001: db8 :: 53
stub-addr: 192.168.0.53
stub-zone:
name: "0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa" # The same applies to reverse lookup (IPv6)
stub-addr: 2001: db8 :: 53
stub-addr: 192.168.0.53
Acquisition of trust anchor
As mentioned in the configuration file section, a trust anchor file is required to validate resource records using DNSSEC. Before starting Unbound, execute the following command to get the initial file of trust anchor. Also, since this file is updated as needed by unbound, change the owner to unbound user.
/ usr / local / sbin / unbound-anchor -a /usr/local/etc/unbound/root.key
chown unbound /usr/local/etc/unbound/root.key
Automatic startup settings
Finally, let's set up unbound to start automatically when FreeBSD starts.
sysrc unbound_enable = YES
Once configured, reboot the FreeBSD machine, or run the following command to start unbound.
service unbound start
Operation check
Finally we were able to start the unbound server. Let's check whether the name resolution can be done correctly. In the following example, we try to resolve the A record (IP address) corresponding to the host name (domain name) www.nic.ad.jp.
The confirmation points are as follows.
Confirm using drill command bundled with Unbound
Specify -D option to enable DNSSEC signature verification
About the result of command execution,
rcode is NOERROR
that ad is included in flags
ANSWER SECTION contains A record (IP address) and signature (RRSIG record) corresponding to this record
Note: For domains that do not support DNSSEC, the latter two (checks regarding RRSIG in flags and ANSWER SECTION) about the command execution result do not apply.
flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; www.nic.ad.jp. IN A
ANSWER SECTION:
www.nic.ad.jp. 269 IN A 192.41.192.145
www.nic.ad.jp. 269 IN RRSIG A 8 4 300 20181018010414 20180720010414 34431 nic.ad.jp. qcrwMmDJb9mZjusNAZ8nQk4Oq6C / N7me9Skvmso1vhtW0YMObCa2 + C + MD / 6koAljbeHAGpA4u5BzvEPflPmzvqhSMP8jv + 4dUYc5Gghkor5GPcgsBPyoz870oJ9De7BRJZke4vfpzDE4 + bcbzAaQ998 / XUDKVcUv3GPctIJlRdVCwkNoxKsksmAAuHM9sNTuPhr4Sd08wmtqxEFJViRlpbH4CDBP329TkQq4JEiw3eVvr4tpoMgjaDLgUF54CIS / M21FzWyn1xOeq4K0lyPl8qYDbqTaN9rycaTxnqd4XdhJDXIbP923oGrOZqO61yx3HTyk588MtvSEF3oUWBeDvA ==
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 1 msec
;; EDNS: version 0; flags: do; udp: 4096
;; SERVER: 192.168.0.1
;; WHEN: Sun Jul 22 19:16:12 2018
;; MSG SIZE rcvd: 355
Client settings
Finally, let's review the client side configuration to use the cache DNS server we built this time. The configuration file for DNS clients is generally /etc/resolv.conf. Let's specify the address of nameserver as the address of cache DNS server.
/etc/resolv.conf
domain example.jp
search example.jp
nameserver 2001: db8 :: 1 # Specify the address of the constructed cache server
nameserver 192.168.0.1 # (same as above)
options edns0
This completes the construction of the DNSSEC & DNS over TLS-enabled cache DNS server using Unbound.
You’ll find quite a few blog posts and tutorials on how to configure encrypted DNS over TLS forwarding in Unbound. I’ve yet to find a single one that sets up TLS securely with certificate domain validation, however. Without TLS certificate domain validation your DNS can still be intercepted, monitored, or manipulated by a man-in-the-middle attacker with nothing more than a self-signed certificate. Here is how you set it up more securely.
I’ve already covered the use and configuration of a local and remote DNS caching service in my Knot Resolver tutorial. I’ll not go over those parts again, but I’ll focus exclusively on the required Unbound configuration and, of course, the necessary parts everyone else skips.
Here is a minimal example configuration for Unbound, /etc/unbound/unbound.conf, that uses both Quad9 and Cloudflare Resolver as the forwarding resolvers and validates their TLS certificates against the expected domain names for each service:
The blue highlighted sections of the above configuration example highlights which parts are missing from most other tutorials and thus the focus of my tutorial.
The first thing you’ll notice is the tls-cert-bundle option that points to the local system’s root certificate authority bundle; including all the trusted root certificates of the operating system. You’ll get this bundle by installing the ca-certificates package in most Linux distributions.
The default location of the root certificate bundle is /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem on Fedora, and /etc/ssl/certs/ca-certificates.crt on Debian/Ubuntu. Refer to the documentation of your distribution if you can’t locate their root certificate bundle.
If you haven’t setup the tls-cert-bundle option correctly, you may end up with certificate validation errors (below) and Unbound refusing to connect to the remove resolver:
The domain names to validate the certificates against may appear as comments behind the forward-addr configuration lines at first glance. The syntax for forward-addr is IP address of the resolver an @ sign and then the resolver’s port number followed by a # sign and then the expected TLS domain name to validate the certificate the resolver will present.
It’s important that you get these domain names right or otherwise you’ll end up with the same error messages as shown above. Unfortunately, Unbound doesn’t produce different error messages when the certificate domain mismatch, is expired, or when the root certificate is missing or otherwise not trusted.
You should keep an eye on your logs and watch out for any certificate errors. It may be an indication that someone is trying to intercept, monitor, or modify your DNS requests. You can add an additional layer of protection against this by enabling DNSSEC validation.
I’ve added both IPv4 and IPv6 addresses in the above configuration example. Unbound will figure out which protocol is available and which is faster on its own. You can get better reliability from your DNS server by configuring more routes and more options to cover for outages or routing disruptions.
I also wrote about randomizing DNS forwarding servers with Knot Resolver a few weeks back. This ensures you’re not sending all your DNS traffic to one provider; making it more difficult for any one provider to build a complete profile on your online activities and behavior.
Unbound will do this by default with no additional configuration assuming each of your configured DNS forwarders respond within 400 milliseconds. Note that you’re not limited to just four DNS forwarders as you are with Knot Resolver. You can configure as many DNS forwarders as you want with Unbound and it will spread your forwarding requests out among each of them automatically.