One of the benefits of building your own firewall is that you get to decide what you want to block. I’d been using a list from pgl.yoyo.org/adservers. There’s a utility called Pf-badhost that blocks evil hosts. I wanted to do a little more: block bad IPs (sorry, Cloudflare, I know you hate that) and have better control over when things get updated.
So I ultimately decided to adapt some of Pf-badhost to a few scripts I created. First, a script to get the latest list of bad hostnames from pgl.yoyo.org — grab-bad-hosts.sh:
Grabbing Bad Hostnames
#! /bin/sh
/usr/local/bin/wget -O ./pgl-adhosts.conf 'https://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintro=1&mimetype=plaintext'
grep -v -f /var/unbound/etc/unbound-whitelist-ads.txt pgl-adhosts.conf > unbound-adhosts.conf
grep -f /var/unbound/etc/unbound-whitelist-ads.txt pgl-adhosts.conf > unbound-adhosts-whitelist.conf
echo "In a root shell, run:"
echo "cat unbound-adhosts.conf > /var/unbound/etc/unbound-adhosts.conf"
echo "cat unbound-adhosts-whitelist.conf > /var/unbound/etc/unbound-adhosts-whitelist.conf"
echo "rcctl restart unbound"
echo "(or run root-update-hosts.sh as root)"
This builds two files: /var/unbound/etc/unbound-adhosts.conf and /var/unbound/etc/unbound-adhosts-whitelists.conf based on a file I created, /var/unbound/etc/unbound-whitelist-ads.txt, which I had to add to make other users happy. /var/unbound/etc/unbound-whitelist-ads.txt looks like this:
adservice.google.com[^.]
googleadservices.com[^.]
… and I’m going to set up unbound to allow one host to have the whitelisted ads.
Grabbing Bad IPs
I used Pf-badhost as a source of places to grab bad IP addresses from. I ended up with this script, grab-bad-ips.sh:
#! /bin/sh
/usr/local/bin/wget -O ./banlist_firehol_level1 https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset
/usr/local/bin/wget -O ./banlist_firehol_level2 https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level2.netset
/usr/local/bin/wget -O ./banlist_binarydefence https://www.binarydefense.com/banlist.txt
/usr/local/bin/wget -O ./banlist_emergingthreats https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt
cat ./banlist_firehol_level1 > pf-badguys.table
printf "\n">> pf-badguys.table
cat ./banlist_firehol_level2 >> pf-badguys.table
printf "\n">> pf-badguys.table
cat ./banlist_binarydefence >> pf-badguys.table
printf "\n">> pf-badguys.table
cat ./banlist_emergingthreats >> pf-badguys.table
printf "\n">> pf-badguys.table
grep '^[0-9]' pf-badguys.table | sort | uniq > pf-badguys.table.sort.uniq
mv pf-badguys.table.sort.uniq pf-badguys.table
echo "In a root shell, run:"
echo " cat pf-badguys.table > /etc/pf-badguys.table"
echo " pfctl -F Tables -f /etc/pf.conf"
echo "(or run root-update-ips.sh as root)"
This script creates /etc/pf-badguys.table, which I’ll plug into my PF configuration.
Configuring unbound to use the bad hosts lists
It’s not hard to have unbound import the bad hosts, which are already formatted to redirect to 127.0.0.1. Here’s a sample from /var/unbound/etc/unbound-adhosts.conf:
local-zone: "1-1ads.com" redirect
local-data: "1-1ads.com A 127.0.0.1"
unbound-adhosts-whitelist.conf looks the same, but only contains the whitelisted ad servers. After the last local-data:/local-data-ptr: pair for my network, I added the following:
# open a hole for ad servers
# 192.168.150.180 is unblocked desktop
access-control-view: 192.168.150.180/32 adview
After my access-control: directives, I added:
# Host addresses - spam to block
#
include: /var/unbound/etc/unbound-adhosts.conf
include: /var/unbound/etc/unbound-adhosts-whitelist.conf
include: /var/unbound/etc/unbound-adhosts-local.conf
At the end of the unbound.conf file I added:
view:
name: "adview"
include: /var/unbound/etc/unbound-adhosts.conf
include: /var/unbound/etc/unbound-adhosts-local.conf
Then a quick:
# unbound-checkconf
# rcctl restart unbound
… and I was blocking ad servers. I could update this in cron, but I prefer to do it manually every week or so.
Configuring PF to block the bad IP addresses
I know there’s an argument for not blocking bad IP addresses. After all, there may be legitimate sites that are hosted on the same IP address. But… so far I’ve only run into one. So I’m happy to continue blocking them. In my pf.conf, after the
table <badguys> persist file "/etc/pf-badguys.table"
Then after the block for martians, I added an equivalent for badguys:
# Block addresses in the badguys table
# We use the "quick" parameter here to make this rule the last.
# Note that badguys might contain martians, but they get handled before
# this rule.
block in quick on $ext_if from <badguys> to any
block return out quick on $ext_if from any to <badguys>
Then pfctl -F Tables -f /etc/pf.conf
to reread the table.
This post is part of a series on setting up an OpenBSD 7.4 firewall device.