« Previous 1 2 3 Next »
DNSSEC-aware DNS caching with Unbound
Name Game
Configuring Unbound
After I prove that Unbound does validate DNSSEC, I need to make some changes to the config files for both Unbound and the Docker container
To change the Unbound configuration, I edit the configuration file:
cd /var/lib/docker/volumes/unbound_unbound_conf/_data/ cp unbound.conf unbound.conf.old #just in case
I do not want to use any forward DNS servers, so I delete all the lines of the forward section (Listing 2, with hashes). No forward zone at all should remain in the config file.
Listing 2
Forward Section
forward-zone: # Forward all queries (except those in cache and # local zone) to upstream recursive servers #name: "." # Queries to this forward zone use TLS #forward-tls-upstream: yes # Cloudflare #forward-addr: 1.1.1.1@853#cloudflare-dns.com #forward-addr: 1.0.0.1@853#cloudflare-dns.com
I will also tweak the security settings (Listing 3). You'll need to adjust the access-control
setting to your internal LAN IP range: the IP ranges you provide are networks allowed to use recursive resolving. If you don't set up this section properly, you might end up amplifying distributed denial of service (DDoS) attacks on the Internet.
Listing 3
Security Settings
# only give access to recursion clients from LAN IPs access-control: 127.0.0.1/32 allow access-control: 192.168.0.0/24 allow # adjust to your lan ip-range auto-trust-anchor-file: "var/root.key" chroot: "/opt/unbound/etc/unbound" harden-algo-downgrade: no harden-below-nxdomain: yes harden-dnssec-stripped: yes harden-glue: yes harden-large-queries: yes harden-referral-path: no harden-short-bufsize: yes hide-identity: yes hide-version: yes identity: "DNS" # These private network addresses are not allowed to be returned for public # internet names. Any occurrence of such addresses are removed from DNS # answers. Additionally, the DNSSEC validator may mark the answers bogus. # This protects against DNS Rebinding private-address: 10.0.0.0/8 private-address: 172.16.0.0/12 private-address: 192.168.0.0/16 private-address: 169.254.0.0/16 ratelimit: 1000 tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt unwanted-reply-threshold: 10000 use-caps-for-id: no #gives many false errors val-clean-additional: yes
You also should adjust the performance settings according to the number of CPU cores you have (Listing 4). My VM has one CPU with two cores. See the Unbound documentation for more on optimizing Unbound [8].
Listing 4
Performance Settings
## performance settings infra-cache-slabs: 4 key-cache-slabs: 4 msg-cache-size: 302921045 msg-cache-slabs: 4 num-queries-per-thread: 4096 num-threads: 2 outgoing-range: 8192 rrset-cache-size: 605842090 rrset-cache-slabs: 4 minimal-responses: yes so-reuseport: yes prefetch: yes prefetch-key: yes serve-expired: yes
Of course, if the server does not work after a change; start it again with:
docker-compose up
Look for the errors, then look for a solution online.
You can also move into the container and ask Unbound to check the configuration:
docker exec -ti unbound /bin/bash sudo unbound-checkconf exit
Adding a Local Zone
In my LAN, I have a few (Dockerized) servers I want to be able to find easily: let's say time.hanscees.com
, canon.hanscees.com
(a printer), and bananas
(a Banana Pi NAS server). Unbound can serve these DNS resource records (RRs) without a problem. It is handy to give zones their own file by adding a line in unbound.conf
pointing to a separate file:
include: /opt/unbound/etc/unbound/a-records.conf include: /opt/unbound/etc/unbound/ptr-records.conf
To define local records, edit a-records.conf
and add entries for the local records (Listing 5).
Listing 5
Adding Local Records
#local-zone: "hanscees.com" static local-data: "canon.hanscees.com A 192.168.0.60" local-data: "time.hanscees.com A 192.168.0.61" local-data: "bananas.hanscees.com A 192.168.0.62"
Notice you can choose whether to define the zone in the config file or not: uncheck the local-zone
line if you want to define the local zone. If you do, Unbound assumes that somename.hanscees.com
does not exist if you have not added it to the config file. If you do not define the local-zone
, and a name does not exist in the config file, Unbound will try to look it up on the Internet.
Control Client
Unbound has a control feature that lets you connect the Unbound client to the Unbound server. This way, you can get statistics and add hosts and changes to your configuration while Unbound is running.
The default config file has the control feature switched off. To enable it, you need to tweak the configuration file, generate some keys for authentication, and expose the port via Docker. For better security, I will configure the Unbound server to allow only one IP address to the control port. See the changes in Listing 6.
Listing 6
The Control Client
01 remote-control: 02 control-enable: yes 03 control-interface: 172.18.0.2 04 control-port: 953 05 server-key-file: "/opt/unbound/etc/unbound/unbound_server.key" 06 server-cert-file: "/opt/unbound/etc/unbound/unbound_server.pem" 07 control-key-file: "/opt/unbound/etc/unbound/unbound_control.key" 08 control-cert-file: "/opt/unbound/etc/unbound/unbound_control.pem"
The control-interface
line is a bit tricky: you need to pick the IP address Unbound can see inside the container, and it needs to be the interface that the VM exposes via your LAN device.
You can easily see the necessary address and gateway with:
docker inspect caa97f2fe1fe | egrep "Gateway|IPAddress" | egrep 172
To generate the keys, enter:
docker exec -ti unbound /bin/bash #log into container unbound-control-setup
You will see Unbound generating keys. Now restart container and test whether nothing has broken:
docker restart caa97f2fe1fe dig @192.168.0.110 time.hanscees.com
To install the remote client, just install Unbound on a remote Linux machine. In my case, this also installed the Unbound server, so I had to stop it.
The client needs a config file with the right keys to authenticate itself to the server. These commands worked on the client PC (running Ubuntu 18):
sudo apt-get install unbound sudo systemctl stop unbound.service sudo systemctl disable unbound.service
To authenticate the client to the Unbound server, move some of the control keys from the server to the control client:
sudo scp root@192.168.0.110:/var/lib/docker/volumes/unbound_unbound_conf/_data/unbound_control.key ~/keys/ sudo scp root@192.168.0.110:/var/lib/docker/volumes/unbound_unbound_conf/_data/unbound_server.pem ~/keys/
Also, reflect this information in the config file for the client (Listing 7).
Listing 7
Remote Control Settings
remote-control: server-cert-file: "/home/hanscees/keys/unbound_server.pem" control-key-file: "/home/hanscees/keys/unbound_control.key" control-cert-file: "/home/hanscees/keys/unbound_control.pem"
Now I can start using the client. I'll enable extended stats and then take a look at some statistics:
sudo unbound-control -c ~/keys/unbound.conf -s 192.168.0.112@953 set_option extended-statistics: yes sudo unbound-control -c ~/keys/unbound.conf -s 192.168.0.112@953 stats_noreset | egrep "total.num|secure"
The output appears in Listing 8.
Listing 8
Statistics
[sudo] password for hanscees: total.num.queries=88937 total.num.queries_ip_ratelimited=0 total.num.cachehits=83513 total.num.cachemiss=5424 total.num.prefetch=22534 total.num.zero_ttl=11075 total.num.recursivereplies=5424 num.answer.secure=238
The statistics there show that, from 88,937 queries, 8,351 were served out of the cache (94%), and 238 of these queries were validated by DNSSEC.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)