It is always the DNS!
I have several jails and virtual machines on my Dell T5600 home lab. It is much easier to operate when each machine is having a FQDM, so I decided to play with Unbound DNS which is a kind of default for OpenBSD and FreeBSD.
Here is the setup – the host OS is FreeBSD 13.1 (in the example below with IP 192.168.1.115), OpenBSD 7.2 (IP 192.168.1.9) is a virtual machine with bhyve on top of the host OS.
I have configured all my hosts with a domain name under *.dilyan.be + the reverse record. Below you’ll see in the example postgres.dilyan.be, openbsd.dilyan.be, wp.dilyan.be, etc with their addresses configured.
In OpenBSD you just have to enable it:
# rcctl enable unbound
# rcctl start unbound
unbound(ok)
the config files are under /var/unbound/etc
here’s my config:
[root@openbsd etc]$ cat unbound.conf
# $OpenBSD: unbound.conf,v 1.21 2020/10/28 11:35:58 sthen Exp $
server:
interface: 127.0.0.1
interface: 192.168.1.9
interface: ::1
port: 53
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: ::0/0 refuse
access-control: ::1 allow
access-control: 10.0.0.0/8 allow
access-control: 127.0.0.0/8 allow
access-control: 192.168.0.0/16 allow
root-hints: "/var/unbound/db/root.hints"
hide-identity: yes
hide-version: yes
auto-trust-anchor-file: "/var/unbound/db/root.key"
val-log-level: 2
aggressive-nsec: yes
verbosity: 1
harden-glue: yes
harden-dnssec-stripped: yes
use-caps-for-id: yes
do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
cache-min-ttl: 3600
cache-max-ttl: 86400
prefetch: yes
num-threads: 2
msg-cache-slabs: 8
rrset-cache-slabs: 8
infra-cache-slabs: 8
key-cache-slabs: 8
rrset-cache-size: 512m
msg-cache-size: 256m
so-rcvbuf: 2m
private-address: 172.16.0.0/12
private-domain: "dilyan.be"
unwanted-reply-threshold: 10000
val-clean-additional: yes
statistics-cumulative: yes
extended-statistics: yes
use-syslog: yes
local-zone: "dilyan.be" static
local-data: "dilyan.be IN A 52.208.215.96"
local-data: "www.dilyan.be IN A 52.208.215.96"
local-data: "vpn.dilyan.be IN A 212.5.153.206"
local-data: "django.dilyan.be IN A 192.168.1.119"
local-data: "mongodb.dilyan.be IN A 192.168.1.118"
local-data: "test.dilyan.be IN A 192.168.1.120"
local-data: "wp.dilyan.be IN A 192.168.1.116"
local-data: "postgres.dilyan.be IN A 192.168.1.117"
local-data: "neo4j.dilyan.be IN A 192.168.1.121"
local-data: "rpi.dilyan.be IN A 192.168.0.115"
local-data: "wiki.dilyan.be IN A 192.168.1.124"
local-data: "openbsd.dilyan.be IN A 192.168.1.9"
local-data: "freebsd.dilyan.be IN A 192.168.1.115"
local-data: "obsd.dilyan.be IN A 192.168.1.223"
local-data-ptr: "192.168.1.119 django.dilyan.be"
local-data-ptr: "192.168.1.118 mongodb.dilyan.be"
local-data-ptr: "192.168.1.120 test.dilyan.be"
local-data-ptr: "192.168.1.116 wp.dilyan.be"
local-data-ptr: "192.168.1.117 postgres.dilyan.be"
local-data-ptr: "192.168.1.121 neo4j.dilyan.be"
local-data-ptr: "192.168.0.115 rpi.dilyan.be"
local-data-ptr: "192.168.1.124 wiki.dilyan.be"
local-data-ptr: "192.168.1.9 openbsd.dilyan.be"
local-data-ptr: "192.168.1.115 freebsd.dilyan.be"
local-data-ptr: "192.168.1.223 obsd.dilyan.be"
forward-zone:
name: .
forward-addr: 8.8.8.8 #Google-1
forward-addr: 1.1.1.1 #Cloudflare-1
forward-addr: 9.9.9.9 #Quad9.net
forward-addr: 1.0.0.1 #Cloudflare-2
forward-addr: 8.8.4.4 #Google-2
forward-addr: 149.112.112.112 #Quad9-2
forward-addr: 208.67.222.222 #OpenDNS-1
forward-addr: 208.67.220.220 #OpenDNS-2
remote-control:
control-enable: yes
control-interface: /var/run/unbound.sock
After completing the config, restart the service with
# rcctl restart unbound
unbound(ok)
So, what do I gain, apart from having the local machines with DNS? Well, a couple of milliseconds :).
Here’re are some tests from the local machine compared to Google, Cloudflare, Quad. When asking for the IP address of bbc.co.uk, Cloudflare replied in 5 msec, Google in 31 msec, the local OpenBSD in 2 ms.
[root@openbsd etc]$ drill bbc.co.uk @1.1.1.1
;; HEADER;- opcode: QUERY, rcode: NOERROR, id: 33177
;; flags: qr rd ra ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; bbc.co.uk. IN A
;; ANSWER SECTION:
bbc.co.uk. 261 IN A 151.101.64.81
bbc.co.uk. 261 IN A 151.101.128.81
bbc.co.uk. 261 IN A 151.101.192.81
bbc.co.uk. 261 IN A 151.101.0.81
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 5 msec
;; SERVER: 1.1.1.1
;; WHEN: Fri Mar 31 11:53:16 2023
;; MSG SIZE rcvd: 91
———
[root@openbsd etc]$ drill bbc.co.uk @8.8.8.8
;; HEADER;- opcode: QUERY, rcode: NOERROR, id: 30222
;; flags: qr rd ra
; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; bbc.co.uk. IN A
;; ANSWER SECTION:
bbc.co.uk. 21 IN A 151.101.0.81
bbc.co.uk. 21 IN A 151.101.64.81
bbc.co.uk. 21 IN A 151.101.128.81
bbc.co.uk. 21 IN A 151.101.192.81
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 31 msec
;; SERVER: 8.8.8.8
;; WHEN: Fri Mar 31 11:53:23 2023
;; MSG SIZE rcvd: 91
——–
[root@openbsd etc]$ drill bbc.co.uk @192.168.1.9
;; HEADER;- opcode: QUERY, rcode: NOERROR, id: 55555
;; flags: qr rd ra
; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; bbc.co.uk. IN A
;; ANSWER SECTION:
bbc.co.uk. 3580 IN A 151.101.128.81
bbc.co.uk. 3580 IN A 151.101.192.81
bbc.co.uk. 3580 IN A 151.101.0.81
bbc.co.uk. 3580 IN A 151.101.64.81
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 2 msec
;; SERVER: 192.168.1.9
;; WHEN: Fri Mar 31 11:53:27 2023
;; MSG SIZE rcvd: 91
Now, in FreeBSD is a little bit confusing, as they have local_unbound and “normal” unbound. The configs are under /var/unbound, but the structure is a little different than in OpenBSD. For example, there’re different files for forwarders, blocked sites, etc. that are included in the main unbound.conf at the end:
include: /var/unbound/forward.conf
include: /var/unbound/lan-zones.conf
include: /var/unbound/control.conf
include: /var/unbound/conf.d/*.conf
include: /var/unbound/blocked_servers
Then the example from the OpenBSD is identical, just the forwarders (Google, Cloudflare, Quad9 DNS addresses are in the file forward.conf). I also noticed that some of the parameters in the OpenBSD are giving errors, so I had to remove the following lines from the above config to make it work:
# auto-trust-anchor-file: "/var/unbound/root.key"
# num-threads: 2
# rrset-cache-size: 512m
# msg-cache-size: 256m
# so-rcvbuf: 2m
I did not have the time to play and make the FreeBSD options work, just commented them. The rest is identical with the OpenBSD config. Restart the service with:
#service local_unbound restart
N.B. local_unbound is different than unbound in FreeBSD!
Now the test of the drill, from the FreeBSD shell, this time with cnn.com:
[root@fbsd /var/unbound]# drill cnn.com @1.1.1.1
;; HEADER opcode: QUERY, rcode: NOERROR, id: 11433
;; flags: qr rd ra ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; cnn.com. IN A
;; ANSWER SECTION:
cnn.com. 58 IN A 151.101.195.5
cnn.com. 58 IN A 151.101.131.5
cnn.com. 58 IN A 151.101.3.5
cnn.com. 58 IN A 151.101.67.5
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 2 msec
;; SERVER: 1.1.1.1
;; WHEN: Fri Mar 31 12:08:20 2023
;; MSG SIZE rcvd: 89
——–
[root@fbsd /var/unbound]# drill cnn.com @8.8.8.8
;; HEADER opcode: QUERY, rcode: NOERROR, id: 29708
;; flags: qr rd ra
; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; cnn.com. IN A
;; ANSWER SECTION:
cnn.com. 18 IN A 151.101.195.5
cnn.com. 18 IN A 151.101.3.5
cnn.com. 18 IN A 151.101.131.5
cnn.com. 18 IN A 151.101.67.5
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 28 msec
;; SERVER: 8.8.8.8
;; WHEN: Fri Mar 31 12:08:25 2023
;; MSG SIZE rcvd: 89
——–
[root@fbsd /var/unbound]# drill cnn.com @192.168.1.115
;; HEADER opcode: QUERY, rcode: NOERROR, id: 62215
;; flags: qr rd ra
; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; cnn.com. IN A
;; ANSWER SECTION:
cnn.com. 3595 IN A 151.101.131.5
cnn.com. 3595 IN A 151.101.195.5
cnn.com. 3595 IN A 151.101.3.5
cnn.com. 3595 IN A 151.101.67.5
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 0 msec
;; SERVER: 192.168.1.115
;; WHEN: Fri Mar 31 12:08:37 2023
;; MSG SIZE rcvd: 89
Cloudflare replied in 2 ms, Google in 28 msec, the FreeBSD in 0 msec .. obviously it was cached 🙂
To be honest, the FreeBSD is _very_ fast if the DNS is in the cache and has been requested recently. If it is the first time request, it can go to 100 ms, as it asks the forwarders (Google, Cloudflare, Quad9, OpenDNS that I’ve configured). It is normal to see 0 msec for hours after the DNS was cached, something that I’ve never seen in OpenBSD, so looks like the caching mechanisms are different.
A great how-to with more explanations is https://calomel.org/unbound_dns.html