C#, .Net and Azure
I recently set up a Raspberry Pi (3, Model B) with PiVPN and Pi-hole running hand in hand on the default Raspbian Jessie distro.
I wanted the adblocking from Pi-hole for all my devices and the ability to securely connect to my home network from anywhere.
While both setups themself are quite easy and well explained in many tutorials, getting them to work together nicely took some time. By connecting them, OpenVPN will also use the Pi-hole for adblocking. By default, any connection made via OpenVPN would not use Pi-hole but the default DNS specified in the OpenVPN setup (Google, ISP, ..).
This post will outline the necessary steps I had to take to get them to coexist nicely.
(If you already have Pi-hole and OpenVPN fully setup and just want them to work together, skip to section "Final config")
Pi-hole acts as a DNS blackhole that supports blacklisting (and whitelisting) of DNS entries. This allows network wide adblocking by adding specific domains to the blacklist.
It comes with a set of default blacklists. As soon as Pi-hole is setup, ad-serving and tracking domains should be blocked.
Despite me running uBlock with most filter lists active, Pi-hole still blocks some DNS requests (mainly Windows telemetry endpoints and google analytics) so it's good to know that it's doing its job.
In order to make Pi-hole network-wide effective, you need a router that supports setting a custom DNS server (that way any device accessing your network has its DNS requests automatically redirected via Pi-hole which means automatic adblocking for all of them).
Unfortunately not all routers (esp. the cheaper ones) support this basic feature. In such a case you can either manually set the DNS server on each device for your home connection or buy a router that supports it.
While the later will probably cost you some money, you'll be able to forget about your Raspberry and all (future) devices that connect to the network will have the adblocking enabled automatically.
PiVPN is a very simple installer that makes installing OpenVPN on a Raspberry a breeze. Simple does not mean it skips anything important but rather it guides you through a step-by-step installer that will ask you all the relevant options.
There really isn't much more to say about this. PiVPN will install OpenVPN and add all the required configs. Once you created your profile you can export it and connect from any OpenVPN capable device.
This section assumes that you have just installed a Raspbian Jessie (full) image on your Raspberry.
On first login you should change the default password. Raspberry defaults to:
Afterwards you should configure your system properly. Set the timezone, locale and enable SSH if you want to remotely connect later (since Nov 2016 SSH is disabled by default on all new images).
Important: Ensure the time and timezone is correctly set, if not the OpenVPN installer might fail on key generation due to the server time being off.
I personally also disable bluetooth and wifi (my Raspberry is strapped to the router and connected via a short cable and if I need to access it, I can just SSH in).
By now Raspberry should probably have promted you for a reboot so just reboot it.
Next it's a good idea to update the base system. Depending on how old your image was this will take some time but shouldn't cause any problems:
sudo apt-get update
sudo apt-get dist-upgrade
You might have to confirm (Y) that you want to download the packages and after some time all should be well.
Reboot one more time.
At this point you should also set your Raspberry to a static IP. That way all network devices will be able to reach it consistently. Without it, your router may hand out a new IP to your Raspberry every now and then, causing all devices to fail to connect.
I picked 192.168.0.250 for my Raspberry.
Both PiVPN and Pi-hole offer very simple GUI installers that will ask you all the relevant questions.
A comprehensive tutorial showing installer screenshots for PiVPN can be found here.
After the install add a user to OpenVPN via:
This will prompt for a username/password that is then used by anyone connecting via OpenVPN.
The output is a file 'username.ovpn' in /ovpns/ dir. Copy it to a target machine (I used WinSCP via sftp). Now you should be able to connect using a OpenVPN client.
Don't forget to forward the port in your router as per the tutorial (default OpenVPN port: 1194 UDP).
A tutorial for Pi-hole is available on their github.
After install use this command to set a new password for the web interface:
pihole -a -p
The web interface is reachable via <raspberry ip>/admin (e.g. 192.168.0.250/admin for me).
Now verify that both of them work independently:
Connecting to the DNS server should blackhole common tracking domains such as google-analytics.com while allowing google.com)
Remotely connecting to the VPN should allow you to see your home IP (I tested it using OpenVPN for android and disabling wifi; that way I should have a different public IP than my desktop, due to being on the mobile network. After connecting to the VPN I had the same public IP as my desktop -> OpenVPN works correctly).
Now that OpenVPN and Pi-hole are both running independently it's time to connect them.
If you use OpenVPN from outside your network, you'll notice that it doesn't forward the DNS requests to Pi-Hole yet (e.g. google-analytics.com isn't blocked) so let's fix that:
sudo nano /etc/openvpn/server.conf
Remove all existing "dhcp-option" entries you can find and add a single new one.
push "dhcp-option DNS 10.8.0.1"
(10.8.0.X being the default OpenVPN subnet, if you changed this in the installer, use your custom values).
Presss Ctrl + X to exit, then Y to confirm saves then Enter to select the existing file name and to overwrite it.
sudo nano /etc/pihole/setupVars.conf
Update: eth0 stands for ethernet connection. If your raspberry is not connected by cable or you want to use wifi, you will have to use wlan0 instead of eth0. You can also see the network names by typing ifconfig into a terminal.
Add "PIHOLE_INTERFACE=tun0" belowe the "eth0".
You should now have entries:
Save the file.
sudo nano /etc/dnsmasq.d/02-ovpn.conf
Add single line "interface=tun0" and save it. This will create the file.
A file "01-pihole.conf" exists in the same directory and we could add this entry there, but we shouldn't. Edits to it may be overriden by any Pi-hole update.
Luckily, Pi-hole also respects config values from all *.conf files in the same directory and won't touch other files when updating, so this config should remain intact on future updates!
One final reboot: "sudo reboot" and we're finished!
Now any device (outside the network) that connects via OpenVPN (to the network) should also use Pi-hole as a DNS server (as evident by blocking of tracking domains).
Log into the dashboard at <raspberry ip>/admin, using the password you set (if you did not set a password for the Pi-hole dashboard, use "pihole -a -p" to set a new one).
Once logged in, the Query log shows all connections made to the Pi-hole server. You can easily verify that it is working, by navigating to some domain with one of your devices and then checking to see if a log entry was made for your device ip + domain name (note that most OSes cache resent DNS requests, so either pick a unique new name or flush your DNS cache).
One final tip:
In my Raspberry hosts file, I added one entry "pi.hole" to redirect to my Rasberry IP.
That way I can just browse to the short url "pi.hole" while in my network and my Pi-hole dashboard pops up.