OpenVPN+PiHole ad-blocking on AWS Lightsail for 3.50$/mo

Arvind Kunday
And Further
Published in
5 min readJul 30, 2019

--

For a while, I’ve been running a network-wide ad-blocker called pi-hole via a local raspberry pi and have been quite happy with how well it blocks ads in the network. Unfortunately, I was unable to use this in my phone on the cellular network because my DNS server was inaccessible from the world for safety reasons. This post explains how to configure pi-hole safely behind OpenVPN.

Considering how cheap instances on AWS Lightsail has gotten, it should be possible to get my DNS in the cloud, and use it everywhere right? The pi-hole Reddit is full of questions and answers on how to get started. Adding to that, some VPS providers provide always free instances like GCP.

Caution: Do not run DNS server that’s exposed to the public internet, unless you are Cloudflare or Google. You will inadvertently be part of DDoS attack or worse have your unpatched system hacked into :)

Running it in public domain can get you into a lot of trouble, either by being inadvertently become part of a DNS amplification attack or an avid hacker is waiting for one unpatched vulnerability to take over your machine. Don’t believe me? check this wonderful list of public pi-holes in shodan.

If you do want a pi-hole accessible everywhere, put it behind a VPN, and that’s the topic of this post.

Step 1: Spin a $3.50/month server on AWS

AWS Lightsail cheapest tier now starts at 3.50$ a month for a TB of network bandwidth, which is quite a good deal. This comes with 1 core and 512 Megs of memory which is more than enough to run pi-hole, OpenVPN and more. Create an instance from the LightSail Console and chose a bare-metal Ubuntu machine and chose the base instance plan(first 30 days free).

Once you get the machine up and running, attach a static IP to your instance from via Networking tab. While AWS rarely public IP doesn’t change often, you are safer to attach a Static IP so you are guaranteed to not accidentally send VPN connection info to the wrong party, if your elastic IP changes on reboot.

Static IP’s not attached to an instance accrue $0.50 an hour, so be mindful if you shut the instance down.

Step 2: Allow public access to UDP port 1194

OpenVPN server by default runs on port 1194(UDP), and you need to let network access to that port. You can change this later to a different port for security purposes. You can enable this in Instance -> Networking -> Firewall section. Without this, AWS will block any network connections on the port.

Open UDP port 1194

Step 3: Install OpenVPN

Connect to the VM either via your SSH key or use the web console in the connect tab.

A handy way to connect to the instance

Once you are in the shell, install OpenVPN. There are a few ways, I use the very popular https://github.com/Nyr/openvpn-install script from GitHub, which sets up all the keys and configures a default user, which is handy!

wget https://git.io/vpn -O openvpn-install.sh && bash openvpn-install.sh

Answer all the prompts and at the end, you can create a new client certificate for your computer. You can then use it connect to VPN on Mac or iPhone. By default, your OpenVPN network runs on 10.8.0.0/32 and your LightSail will have a tun0 network interface pointing to 10.8.0.1. You can check this by running

ip addr show tun0inet 10.8.0.1/24 brd 10.8.0.255 scope global tun0
valid_lft forever preferred_lft forever

Step 4: Push DNS to your clients

By default, OpenDNS is configured to push a public name resolver, but we need to push our PiHole DNS that’s going to be our name resolver in our VPN network. Edit /etc/openvpn/server/server.conf and add the following line:

;Comment this line, or all traffic will go through this network, you can always configure this via client if needed.
;push "redirect-gateway def1 bypass-dhcp"
; remove any other dhcp-option
push "dhcp-option DNS 10.8.0.1"

If everything looks good, make sure you restart your OpenVPN service by running the command:

sudo systemctl restart openvpn-server@server

Now when a client connects to the VPN, it’s DNS is automatically set to that IP address.

Step 5: Install PiHole

Pi-Hole is a network-wide ad blocker that blocks ad in your network by intercepting DNS queries and denying requests that are known to serve ads. Jeff Atwood from Coding Horror has a wonderful article about Pi-Hole which I recommend reading if you are new to Pi-Hole. Installing pi-hole is straight forward by running the installer command in your LightSail instance.

curl -sSL https://install.pi-hole.net | bash

Select tun0 interface instead of eth0 which is the default, to make sure the DNS is only available on the internal network.

DigitalOcean has a wonderful article going into the details if you get stuck in any of the steps.

Step 6: Copy .ovpn profile to your computer and connect

Use scp to copy the file to the local machine, assuming you named your ovpn profile as mac.ovpn you can copy it to your local machine using

scp -i ~/.ssh/aws.key ubuntu@ip-address:/home/ubuntu/mac.ovpn .

I use TunnelBlick which is one of the most popular OpenVPN client’s for macOS or use the official OpenVPN Access Server. Import the profile and hit connect, and voila you should now be connected to the VPN with your DNS now pointing to the PiHole on VPN network. For the iPhone, I recommend the official OpenVPN Connect.

PS: I’m building the next generation of data tools for engineers. If you have a moment, please check out https://fillory.io

References

--

--

Arvind Kunday
And Further

Space Enthusiast, History buff, Zendeskian, ex-thought worker.