There are lots of places where you can download ad blacklists in the form of simple host files, but they require manual installation on every device. Instead we will make records for our DNS server so we can block ads network wide. I used a blacklist from somewhocares. This github page contains a range of different filters and their stats. If you wish to learn more about setting up Unbound, I have an example configuration fileHere is my script to do it. It also allows you to specifiy a different address than "0.0.0.0". This is useful if you have a web server you wish to point blocked domains (e.g. pihole)

#! /bin/bash

BlocklistURL=${1:-"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"}
EndpointIP=${2:-"0.0.0.0"}
GeneratedOutput=${3:-"ads.conf"}

wget -qO- ${BlocklistURL} | grep '^0\.0\.0\.0' | awk '{print "local-zone: \""$2"\" redirect\nlocal-data: \""$2" A '${EndpointIP}'\""}' > ${GeneratedOutput};

If no arguments are provided, it will use default values.

Now we point /etc/unbound.conf to the file

    include: /etc/unbound/ads.conf

We run unbound-checkconf to verify the data.

Otherwise, any errors will cause unbound to fail to start

 $ sudo unbound-checkconf && dig +short statsfe2.ws.microsoft.com
 unbound-checkconf: no errors in /etc/unbound/unbound.conf
 192.168.255.254

All done. I'll be doing a few more tutorials on Unbound.

Appendix: Running a blank page webserver

While in my experience, DNS blocking on its own works pretty well, you can maximize its effectiveness by running a webserver on your local address. Without a web server running, sometimes scripts will stall and other little glitches. We will create a lighttpd server running on the address 192.168.255.254
It will redirect any .js file to a script that throws a new error, any images to a blank image, and anything else to a blank response.

/etc/lighttpd/lighttpd.conf
(the bottom section is the saliant one)

var.log_root    = "/var/log/lighttpd"
var.server_root = "/var/www"
var.state_dir   = "/var/run"
var.home_dir    = "/var/lib/lighttpd"
var.conf_dir    = "/etc/lighttpd"
var.cache_dir   = "/var/cache/lighttpd"
var.socket_dir  = state_dir + "/sockets"

include "modules.conf"

server.port = 80
server.use-ipv6 = "disable"
server.bind = "192.168.255.254"

server.username  = "lighttpd"
server.groupname = "lighttpd"
server.document-root = server_root + "/lighttpd"
server.pid-file = state_dir + "/lighttpd.pid"
server.errorlog             = log_root + "/error.log"
include "conf.d/access_log.conf"

server.event-handler = "linux-sysepoll"
server.network-backend = "sendfile"
server.stat-cache-engine = "simple"
server.max-connections = 1024

$SERVER["socket"] == "192.168.255.254:80" {
        url.rewrite = ( ".*\.js$" => "/adblock.js", ".*\.(jpeg|jpg|png|gif)$" =>"/adblock.png", ".*"=>"/adblock.txt")
}

Now we configure the adblock files to serve,

$ cd /var/www/lighttpd
$ touch adblock.txt
$ wget -qOadblock.png http://placehold.it/1x1
$ echo "throw new Error();" >adblock.js

Now let's test out images

ad_image="images.outbrain.com/transform/v2/eyJpdSI6IjhlMzdiY2FjMDk3MTQ3Nzc0Njk1ZjI4MTVmZWI5NmNhZmM1MWVjNTRiM2YyNzRmNDljYTk3YzU3ZTA5Yzc1ZTEiLCJ3IjoxNDUsImgiOjExMCwiZCI6MS41LCJjcyI6MCwiZiI6MH0.jpg"

$ wget -qO- $ad_image | diff - /var/www/lighttpd/adblock.png

Next, we test javascript

ad_javascript="widgets.outbrain.com/outbrain.js"

$ wget -qO- $ad_javascript
throw new Error();