In the last blogpost, we set up a Raspberry Pi to be a DNS level ad-blocker, using Ubuntu Server, Cockpit, Podman, and Pi-Hole.
Now lets go one step further and take back control by running our own recursive DNS server in a Podman container. We'll do this by installing an unbound container.
This is a follow-on from: Install Cockpit and Pi-Hole on your Raspberry Pi.
What you'll need
- A computer running Ubuntu Server
- Cockpit installed with the cockpit-podman addon
- Optionally a Pi-Hole installation.
Create the Unbound config
SSH into your server, or use the 'Terminal' link in Cockpit.
Create a folder for your config file:
$ cd
$ mkdir unbound/
Use nano (or your editor of choice) to create the config file for unbound:
/home/ubuntu/unbound/unbound.conf:
server:
interface: 0.0.0.0
verbosity: 0
port: 53
do-ip4: yes
do-udp: yes
do-tcp: yes
do-ip6: no
prefer-ip6: no
harden-glue: yes
harden-dnssec-stripped: yes
use-caps-for-id: no
edns-buffer-size: 1232
prefetch: yes
num-threads: 1
access-control: 10.0.0.0/8 allow
access-control: 192.168.0.0/16 allow
so-rcvbuf: 1m
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: fd00::/8
private-address: fe80::/10
Create the Unbound container
Go to Cockpit, and click the 'Podman containers' link on the left-hand side.
Click on "Create container".
In the "Image" box, type "unbound", and choose the Docker image from Alpine. Set the following options:
- Command - change to
bash
- Memory limit - change to 128 MB. It's a lightweight Alpine Linux container, that's more than enough
- Restart policy - change to 'On failure', and '5 retries'
Next, click on the 'Integration' Tab. Map the following ports if you're setting this up with a Pi-Hole container:
- Port 5353/tcp -> 53/tcp
- Port 5353/udp-> 53/udp
If you're just setting a recursive DNS server on it's own, and you don't have any other containers using port 53, then you can map directly:
- Port 53/tcp -> 53/tcp
- Port 53/udp-> 53/udp
Next we need to create a link to the config file we created. Click on "Add volume", in "Host path" type the location of the config file, in my case, that was /home/ubuntu/unbound/unbound.conf
. For the "Container path", set it to /etc/unbound/unbound.conf
. Uncheck the "Writable" tickbox".
Now click the "Create and run" link, in the blue box.
Test and update Pi-Hole
Once the container is up and running (it should be very quick, Alpine container images are very minimal), let's test it. Use the -p
to pass through the correct port to the dig command.
$ dig @192.168.88.252 -p5353
; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> @192.168.88.252 -p5353
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8533
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 27
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;. IN NS
;; ANSWER SECTION:
. 86400 IN NS h.root-servers.net.
. 86400 IN NS i.root-servers.net.
. 86400 IN NS j.root-servers.net.
. 86400 IN NS k.root-servers.net.
. 86400 IN NS l.root-servers.net.
. 86400 IN NS m.root-servers.net.
. 86400 IN NS a.root-servers.net.
. 86400 IN NS b.root-servers.net.
. 86400 IN NS c.root-servers.net.
. 86400 IN NS d.root-servers.net.
. 86400 IN NS e.root-servers.net.
. 86400 IN NS f.root-servers.net.
. 86400 IN NS g.root-servers.net.
;; ADDITIONAL SECTION:
a.root-servers.net. 86400 IN A 198.41.0.4
b.root-servers.net. 86400 IN A 199.9.14.201
c.root-servers.net. 86400 IN A 192.33.4.12
d.root-servers.net. 86400 IN A 199.7.91.13
e.root-servers.net. 86400 IN A 192.203.230.10
f.root-servers.net. 86400 IN A 192.5.5.241
g.root-servers.net. 86400 IN A 192.112.36.4
h.root-servers.net. 86400 IN A 198.97.190.53
i.root-servers.net. 86400 IN A 192.36.148.17
j.root-servers.net. 86400 IN A 192.58.128.30
k.root-servers.net. 86400 IN A 193.0.14.129
l.root-servers.net. 86400 IN A 199.7.83.42
m.root-servers.net. 86400 IN A 202.12.27.33
a.root-servers.net. 86400 IN AAAA 2001:503:ba3e::2:30
b.root-servers.net. 86400 IN AAAA 2001:500:200::b
c.root-servers.net. 86400 IN AAAA 2001:500:2::c
d.root-servers.net. 86400 IN AAAA 2001:500:2d::d
e.root-servers.net. 86400 IN AAAA 2001:500:a8::e
f.root-servers.net. 86400 IN AAAA 2001:500:2f::f
g.root-servers.net. 86400 IN AAAA 2001:500:12::d0d
h.root-servers.net. 86400 IN AAAA 2001:500:1::53
i.root-servers.net. 86400 IN AAAA 2001:7fe::53
j.root-servers.net. 86400 IN AAAA 2001:503:c27::2:30
k.root-servers.net. 86400 IN AAAA 2001:7fd::1
l.root-servers.net. 86400 IN AAAA 2001:500:9f::42
m.root-servers.net. 86400 IN AAAA 2001:dc3::35
;; Query time: 48 msec
;; SERVER: 192.168.88.252#5353(192.168.88.252) (UDP)
;; WHEN: Tue Aug 22 22:09:29 BST 2023
;; MSG SIZE rcvd: 811
Looks good! Last thing to do, is to login to Pi-Hole, go to Settings > DNS, and change the DNS server to our new container. The IP address will be the same as the Pi, use the #
symbol to designate a non-standard port.
Job done
I really hope this helps! If you'd like watch me do this on video, I've embedded a YouTube video below for your viewing pleasure.
Tools used
- Ubuntu Server ARM 22.04.03 LTS
- Cockpit >= 264
- Podman>= 3.4.4
- Alpine Linux Unbound container Latest pull from docker.io
More information
Ubuntu Server for Pi Cockpit Podman Pi-Hole Unbound
Setting up Pi-hole as a recursive DNS server solution