ftp https://www.geoghegan.ca/scripts/unbound-adblock.sh
Ever want to get rid of all those annoying internet ads? Me too. I’d been planning on using something like Pi-hole, but recently stumbled upon unbound-adblock, which is perfect for my OpenBSD home router. The setup is very well-documented there, but I provide my own, slightly-modified setup instructions here. Most notably, the cron-job runs at 6:30 AM, not midnight, and I refined the PF rule which redirects DNS requests to Google’s DNS servers.
First, set your expectations. Get a base-line of what ads should be blocked by working through the test steps on https://ads-blocker.com/testing.
Disable any browser-based ad-blockers you might have enabled, otherwise you won’t be able to verify your setup actually blocks ads. |
Download the unbound-adblock.sh script.
ftp https://www.geoghegan.ca/scripts/unbound-adblock.sh
Install the script with the appropriate permissions.
install -g bin -m 644 -o root unbound-adblock.sh /usr/local/bin/ (1)
1 | The script will be owned by root, belong to the bin group, and be readable by everyone and writeable by the owner. |
Create a new user, _adblock
, who will not be allowed to login.
useradd -s /sbin/nologin _adblock
Install an empty adblock.conf
file owned by the _adblock
user which is readable by everyone but only writeable by the owner.
install -m 644 -o _adblock /dev/null /var/unbound/etc/adblock.conf
Include the adblock.conf
file at the end of the server
section.
server:
...
# Include the unbound-adblock configuration file.
include: /var/unbound/etc/adblock.conf
Allow the _adblock
user to reload the unbound service without requiring a password.
# Allow the unbound-adblock user / script to reload the unbound service.
permit nopass _adblock cmd rcctl args reload unbound
Edit the _adblock
users crontab file.
crontab -u _adblock -e
Add a rule to run the unbound-adblock.sh
script every morning at 6:30.
# use /bin/sh to run commands, no matter what /etc/passwd says
SHELL=/bin/sh
# Update unbound-adblock at 6:30 every morning.
30 6 * * * /usr/local/bin/unbound-adblock.sh
Run the unbound-adblock.sh
script once.
doas -u _adblock sh /usr/local/bin/unbound-adblock.sh
Restart the unbound service.
rcctl restart unbound
Add a PF rule to redirect all DNS queries bound for Google’s DNS servers, 8.8.8.8
and 8.8.4.4
to your unbound DNS server, i.e. 192.168.1.1
.
The example below uses a macro lan_if
to represent the LAN network interface, em1
.
# Redirect any DNS requests to Google's DNS servers to the LAN's unbound server.
lan_if = "em1"
lan_dns_server = 192.168.1.1
table <google_dns_servers> { 8.8.8.8 8.8.4.4 }
...
pass in quick on $lan_if quick inet proto { tcp udp } to <google_dns_servers> port domain rdr-to $lan_dns_server port domain
Be careful to position this rule in a place where it is not superseded by a preceding quick rule.
|
My actual configuration is a bit more complex, but I have included it here for reference.
lan1_if = "em1"
lan2_if = "em2"
lan3_if = "em3"
lan4_if = "em4"
lan5_if = "em5"
secure_wifi_if = "vlan2"
guest_wifi_if = "vlan3"
lan1_dns_server = 192.168.1.1
lan2_dns_server = 192.168.2.1
lan3_dns_server = 192.168.3.1
lan4_dns_server = 192.168.4.1
lan5_dns_server = 192.168.5.1
secure_wifi_dns_server = 192.168.6.1
guest_wifi_dns_server = 192.168.7.1
table <google_dns_servers> { 8.8.8.8 8.8.4.4 }
...
pass in quick on $lan1_if inet proto { tcp udp } to <google_dns_servers> port domain rdr-to $lan1_dns_server port domain
pass in quick on $lan2_if inet proto { tcp udp } to <google_dns_servers> port domain rdr-to $lan2_dns_server port domain
pass in quick on $lan3_if inet proto { tcp udp } to <google_dns_servers> port domain rdr-to $lan3_dns_server port domain
pass in quick on $lan4_if inet proto { tcp udp } to <google_dns_servers> port domain rdr-to $lan4_dns_server port domain
pass in quick on $lan5_if inet proto { tcp udp } to <google_dns_servers> port domain rdr-to $lan5_dns_server port domain
pass in quick on $secure_wifi_if inet proto { tcp udp } to <google_dns_servers> port domain rdr-to $secure_wifi_dns_server port domain
pass in quick on $guest_wifi_if inet proto { tcp udp } to <google_dns_servers> port domain rdr-to $guest_wifi_dns_server port domain
...
Reload the updated PF rules.
pfctl -f /etc/pf.conf
Test your new-found adblocking by revisiting the test steps. Those pesky ads should have mystically vanished.