DNS Adblocking with OpenBSD

You can totally set up your own DNS resolver, and have an automatically updating adblock list, using only the OpenBSD base system, no extra packages needed!

Configuring Unbound

OpenBSD ships with unbound, a DNS resolver. First, configure unbound to listen and allow connections on the appropriate interfaces at /var/unbound/etc/unbound.conf.

server:
    ...
    interface: 0.0.0.0 # binds all ip4 addresses
    ...
    access-control: 192.168.0.0/24 # or the appropriate subnet

Enable forwarding DNS queries to an upstream DNS server:

...
forward-zone:
    ...
    forward-addr: 8.8.8.8 # or whatever upstream you prefer
    forward-addr: 8.8.4.4
    ...

Enable and start unbound by ~# rcctl enable unbound && rcctl start unbound.

Configuring Adblocking

Add an include line to /var/unbound/etc/unbound.conf for a blacklist configuration:

server:
    ...
    include: "/var/unbound/etc/blacklist.conf"
    ...

Entries in blacklist.conf take the form local-zone: "blacklisted.example" always_refuse (to unbound, you are just creating a local zone which handles the name).

You can write a script which will download a blacklist and formats that blacklist appropriately. For example, I use this script to automatically set up StevenBlacks blacklist:

#!/bin/sh
ftp -o - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts \
        | sed -e '1,/Start StevenBlack/d' \
        | grep '^0\.0\.0\.0' \
        | awk '{print "local-zone: \""$2"\" always_refuse"}' \
        > /var/unbound/etc/blacklist.conf \
        && rcctl reload unbound

Save this to /root/update-adblocking.sh, set the execute bit, and add a cron entry as root:

~ 0 * * * /root/update-adblocking.sh

Bonus: Tailscale

I don’t want to expose my DNS server to the public. Instead, I only expose it on my tailnet, which all of my devices are part of anyways. Setting up tailscale on OpenBSD is easy and should just work:

~# pkg_add tailscale
~# rcctl enable tailscaled && rcctl start tailscaled
~# tailscale up

Make sure you modify /var/unbound/etc/unbound.conf to listen on your tailscale interface and accept connections for your tailnet subnet (100.64.0.0/10). Reload unbound.

Both the commerical tailscale control server and headscale support setting nameservers for the tailnet. For the commercial control server, navigate to https://login.tailscale.com/admin/dns, and add the tailscale address of your Unbound host to Global nameservers and toggle Override local DNS ON.

Now, unbound will be available to all devices on your tailnet, and tailscale will auomatically configure your devices to use that DNS server.