Adding Adblocking Capabilities to Your OpenVPN Server

Thursday, May 4, 2017 @ 4:26 pm

Because I couldn’t find any guides on how to add adblocking capabilities to an OpenVPN server using dnsmasq, this post contains the steps and code I used.

Assumptions:

  • You already have OpenVPN server set up (if not, this is an excellent guide)
  • Your OpenVPN configuration is set to use the 10.8.0.0/24 range for connected clients (which is default)
  • You have ufw installed

This guide is intended for Debian/Ubuntu systems, but can be adapted easily for other systems.

While I came across scattered tutorials for adding adblocking capabilities to OpenVPN servers using Bind9 and Unbound, I chose dnsmasq because it is lightweight and simplest to configure (just 10 lines of code).

After following this guide, your VPN clients will enjoy an improved browsing experience with less ads and more privacy courtesy of Steven Black’s unified hosts file.

Install dnsmasq

Run the below command to install dnsmasq:

apt-get update && apt-get install dnsmasq

Configure dnsmasq

Run:

mv /etc/dnsmasq.conf /etc/dnsmasq-orig.conf
nano /etc/dnsmasq.conf

Paste in the following configuration:

bogus-priv
domain-needed
no-resolv
server=8.8.8.8
server=8.8.4.4
#uncomment below 3 lines (and comment above 2) if using dnscrypt with a dnssec-enabled resolver
#proxy-dnssec
#server=127.0.0.1#5353
#server=127.0.0.2#5353
interface=tun0
listen-address=127.0.0.1
listen-address=10.8.0.1
addn-hosts=/home/adblock
host-record=YOURHOSTNAME,127.0.0.1,10.8.0.1,::1

Four things to note:

  • run ifconfig | grep encap to get a list of your interfaces and adjust the “interface=tun0” line
  • replace YOURHOSTNAME in the above code with your actual host name (run hostname to get it)
  • (optional) change the two server values in the above code to your preferred DNS provider (above uses Google DNS)
    • if you have dnscrypt set up, you can point it to server=127.0.0.1#5353 and server=127.0.0.2#5353 for example (config: /etc/systemd/system)
  • if you need to revert back to the original configuration, access /etc/dnsmasq-orig.conf

Configure OpenVPN

Run the below commands:

ls /etc/openvpn

Find the .conf file for your OpenVPN server(s) then run:

nano /etc/openvpn/FILENAME.conf

Find and comment out any lines that contain push “dhcp-option DNS x.x.x.x”

Add the following line:

push "dhcp-option DNS 10.8.0.1"

Save the updates and repeat if you have more than one OpenVPN server.

Update the Firewall

If you do not have an existing allow rule for port 53 (dnsmasq), run:

ufw allow from 10.8.0.0/24 to any port 53

The above rule will only allow your VPN clients to access port 53 (dnsmasq).

Blocklist

We’ll be creating a simple script that grabs Steven Black’s unified blocklist and reloads dnsmasq to load the latest domains.

nano /home/adblockget

Paste/type in the below code:

#!/bin/bash
newfile="/home/adblock-dled"
goodfile="/home/adblock"
blocklistdl="https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hosts"

nc -z 8.8.8.8 53  >/dev/null 2>&1
online=$?

if [ $online -eq 0 ]; then
    wget -qO- --no-check-certificate $blocklistdl \
    | sort -u \
    | awk '/^0/ {print;print ":: " $2}' \
    > $newfile
    new=$(wc -l < $newfile)
    echo "Downloaded blocklist. Checking if empty."
    if [ $new -gt 0 ]; then
        echo "Blocklist is not empty. Checking if updated."
        if cmp -s "$goodfile" "$newfile"
        then
            rm $newfile
            echo "No updates detected."
        else
            good=$(wc -l < $goodfile)
            mv $newfile $goodfile
            let unique=new/2
            let oldunique=good/2
            /etc/init.d/dnsmasq reload
            echo "Successfully applied blocklist: $unique unique domains (formerly $oldunique)."
        fi
    else
        rm $newfile
        echo "Downloaded file was empty."
    fi
fi

Feel free to visit https://github.com/StevenBlack/hosts for other host file variants and update the blocklistdl variable URL in the above code.

Save the new file then run:

chmod +x /home/adblockget
/home/adblockget

Next we will schedule a cron job so the latest blocklists are downloaded daily.

Run the following command:

crontab -e

Add a new line:

0 12 * * * /home/adblockget

The above will run our script to grab the latest blocklist at 12:00pm every day.

Finishing Touches

Restart dnsmasq and OpenVPN to enforce our modifications.

service dnsmasq restart
service openvpn restart

Troubleshooting

The below two lines will help you debug any issues with dnsmasq or OpenVPN:

grep vpn /var/log/syslog
systemctl status dnsmasq.service