Use Oracle Cloud always free tier, OpenVPN, Pi-Hole, and Quad9 DNS to setup your own ad, tracking, and malware blocking VPN!
Oracle Cloud offers an always free tier option which includes the ability to provision up-to two Linux VMs (from a choice of distributions) with 1 GB memory, 50 GB storage each, and public IP addresses. Ideal for this type of work, and considering these VMs are running on HA (high availability) hardware in a datacenter with redundant power and network links makes it hard to beat for the price!
Together with Pi-Hole and OpenVPN which has clients for Windows, macOS, Linux, iOS, and Android it's fairly easy to setup and get working.
Oracle Cloud VM
When creating a VM the default image is Oracle Linux. I chose the Ubuntu 20.04 image (not the minimal one), as I'm most familiar with Debian/Ubuntu.
Once a VM is up and running, and logged in via SSH, update the system and reboot:
apt-get update
apt-get upgrade
reboot
Installing OpenVPN
I went with the defaults except it does not detect the public IP of the Oracle cloud instance, manually enter that. For the DNS servers, I prefer
Quad9 which blocks known Malware domains and doesn't log. This selection doesn't matter too much because we're going to change it later to use the DNS server Pi-Hole installs, which I choose Quad9 for upstream DNS.
After installing the script prompts to setup a user and outputs a config file for the client.
- Port 1194 has to be enabled via the Oracle Cloud Console > Networking > Virtual Cloud Networks > [network name you created] > Public Subnet > Default Security List > add a rule for UDP port 1194 (stateful).
- Angristan's OpenVPN install script made the necessary changes to iptables and everything just worked.
- Note that the default iptables contains a number of rules for the iSCSI boot block volume, do not clear the iptables rules or modify these rules. More info in Oracle-Provided Images > Essential Firewall Rules.
After installing OpenVPN, I tested it with the defaults before moving on to installing Pi-Hole.
Note: This OpenVPN install script creates a pair a iptables scripts that are run when the OpenVPN service starts and stops. One adds rules, one removes them:
/etc/iptables/add-openvpn-rules.sh
/etc/iptables/rm-openvpn-rules.sh
Be aware these use the -I option to insert the rules at the top of their respective chains, if like me you have some
geo whitelist and tor exit node block ipsets being inserted under the "related, established" connection tracking rule (usually 1st) 2nd and 3rd, then you may want to insert the INPUT rules further down by increasing the number after INPUT, e.g:
iptables -I INPUT 7 -i ens3 -p udp -m udp --dport 1194 -j ACCEPT
iptables -I INPUT 8 -i tun0 -j ACCEPT
There is also
PiVPN (better to install it after PiHole if used) which will run on any Debian based system, not used or tested it yet, just making a note of it.
IPv6
The Oracle VM doesn't offer IPv6 (fine by me for now), however I found that on some operating systems if the local network assigned a valid routable IPv6 address it would prefer that and bypass the VPN.
To close that off, in the server config add:
push "block-ipv6"
DNS Servers
I also found that on Apple devices, if you push a private IP for primary DNS (like above with 10.8.0.1), and a public IP for secondary DNS - both are queries, and if the results dont match (because the private IP primary DNS is being filtered by Pi-Hole), then it will use the result from the public secondary!
This effectively bypasses the VPN for DNS, ads and junk will appear.
Only push one DNS server!
Installing Pi-Hole
The Pi-Hole script offers a list of upsteam DNS servers to use, I prefer
Quad9 as they block known malware domains and don't log.
Configure Pi-Hole to listen on all interfaces, by default it picks an Ethernet interface, go-to http://10.8.0.1/admin > login > Settings > DNS > Listen on all interfaces.
Update OpenVPN server configuration to push the VPN tunnel IP for DNS, edit /etc/openvpn/server.conf Comment out the preset servers and add:
push "dhcp-option DNS 10.8.0.1"
# push "dhcp-option DNS 9.9.9.9"
# push "dhcp-option DNS 149.112.112.112"
Restart OpenVPN server:
systemctl restart openvpn@server
Logging
If logging is a concern, this can be disabled.
sudo pihole logging off
In the Pi-Hole interface, Settings > Privacy > Anonymous mode
sudo service pihole-FTL stop
sudo rm /etc/pihole/pihole-FTL.db
sudo service pihole-FTL start
Clear out archived copies of /var/log/pihole.log with
sudo rm /var/log/pihole.log*
This will leave basic stats available on the dashboard, but wont log or display anything specific about clients or DNS queries.
I "think" that is all that is required, searching for info on how to turn off logging doesn't turn up info / explanations on how-to clearly and fully do this in one place.
Automatic Updates
The Oracle Ubuntu image appears to be partially setup for automatic updates, it was already installed and had a config file present.
The options I configured in /etc/apt/apt.conf.d/50unattended-upgrades were:
// Automatically reboot *WITHOUT CONFIRMATION* if
// the file /var/run/reboot-required is found after the upgrade
Unattended-Upgrade::Automatic-Reboot "true";
// Automatically reboot even if there are users currently logged in
// when Unattended-Upgrade::Automatic-Reboot is set to true
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
// Default: "now"
Unattended-Upgrade::Automatic-Reboot-Time "10:00";
Note the time is in UTC (assuming it's the default timezone in Oracle Cloud VMs). 10am UTC is 2am Pacific Time in my case.
Some more info on automatic-updates
Pi-Hole Updates
Running pihole -up manually will update the Pi-Hole software.
To automate it, sudo -i to switch to root, crontab -e to edit the crontab, and enter:
# Pi-Hole weekly update
0 11 * * 0 /usr/local/bin/pihole -up > /var/log/pihole-up.log
Minutes, Hours, Days of month, Months of year, Day of week, Command, What to do with the output.
This will run the update at 11:00 am once a week on Sunday (day zero of the week) in the timezone of the machine, since mine is UTC and I'm Pacific time -8 hours this is 3am every Sunday morning. Output the results to
/var/log/pihole-up.log. Plenty of
crontab generators online.
Speedtest
Speedtest-cli is a command line speed test tool (requires Python). From the VM it reports 420 to 490 mbps in both directions. Over the VPN tunnel I get up-to 100 mbps.
Additional Block Lists
Additional block lists can be added via Group Management > Adlists
These don't seem to be an exact science, DYOR.
See:
Enable client to client communication
In /etc/openvpn/server.conf add an entry/line with: client-to-client
Add an iptables forwarding rule to enable traffic to pass out of and back into the tun0 interface:
iptables -A FORWARD -i tun0 -o tun0 -j ACCEPT
I later found I didn't need this rule, maybe a system reboot after the addition of client-to-client to server.conf works on its own?
Restart OpenVPN server and check status:
systemctl restart openvpn
systemctl status openvpn
Multiple Instances for both UDP and TCP
(Rough notes)
By default OpenVPN is setup to listen on UDP port 1194, UDP is preferred as its more efficient and any TCP traffic being tunneled will handle dropped packet retries.
Some networks may block outgoing UDP traffic and/or limit traffic to web browsing only on TCP ports 80 and 443.
A work around is to enable multiple instances of OpenVPN server, one listening on UDP and one on TCP port 443 which is least likely to be restricted.
Copy /etc/openvpn/server.conf to /etc/openvpn/server2.conf
Edit the original server.conf change dev tun to dev tun0.
Edit server2.conf:
- Change dev tun to dev tun1,
- port to 443 and proto to TCP
- Change the server line to use a new subnet e.g server 10.9.0.0 255.255.255.0
- If clients are assigned static IPs configs in the ccd directory and ipp.txt, duplicate directory and files and update addresses with server configs referencing each one.
Start the new server: systemctl start openvpn@server2.service
Check the new server status: systemctl status openvpn@server2.service
Enable autostart with: systemctl -f enable openvpn@server2.service
Update the iptables rules in /etc/iptables/add-openvpn-rules.sh or /etc/iptables/rules.v4 to enable incoming connections on TCP 443 (depending on where this rule is added), and duplicate any rules related for the new OpenVPN subnet and new tun1 interface. (Need to add details).
Inter client communication (if needed) between each instance needs a pair of iptables rules to forward traffic between tun0 and tun1, e.g:
iptables -I FORWARD -i tun0 -o tun1 -j ACCEPT
iptables -I FORWARD -i tun1 -o tun0 -j ACCEPT
Edit or remove/add a new VPN client profile to duplicate it, edit the duplicated file and change proto to tcp and the port number on the remote entry, we have one profile for UDP, and one for TCP when needed. It may be possible to include several remote lines in one profile such as https://openvpn.net/faq/how-do-i-set-up-my-profile-for-server-failover/. (Need to test this and see if it'll work reliably).
Renew Expired Server Certificate
These will expire after 3 years (I found this out the hard way)!
https://github.com/angristan/openvpn-install/issues/1002#issuecomment-1229525488
Running those commands worked, no changed needed to clients - macOS or iPhone at least.
A later comment on that issue suggested using easyrsa renew, but I couldn't figure out what version of easyrsa I had.
Privacy Badger (EFF)
Adds and additional layer to the browser
https://privacybadger.org/