How I started hosting my own VPN

I’m generally not too concerned about my ISP seeing what sites I visit, unlike other parts of the world, there’s very little that is banned (torrents for illegal copies of movies is the only thing that comes to mind). Then vpnMentor reported that the browsing history of African cellular users was leaked online, linked to their cell phone number and sometimes also social media accounts. Welcome to SIM-swap fraud! Any 2-factor authentication that relies on sending you an SMS can now be defeated as long as the criminal has a friend in the cellular provider. I’m sure someone can speak up and say “serves you right for putting information online.” Honestly, I would have expected better security from software used by cellular providers. While I appear to be fortunate enough not to have been affected by this breach, it is a bit of a wakeup call.

After some Googling, I came across Algo VPN for automatically configuring a WireGuard VPN server in the cloud. WireGuard has Ubuntu, Android and Windows clients, so all my devices can be covered. Setup ran pretty smoothly, following the instructions exactly as given in the link. On the cost side, I find that DigitalOcean turns out to be the cheapest provider, primarily because their instances include a generous 1TB pool of data that can be downloaded per month. AWS, Azure and Google Cloud Platform all charge for data leaving their cloud, with a very small free tier. This is a VPN, so of course there will be lots of data being transferred in and out of the cloud! Signing up is a little harder than other cloud providers, as you have to go through an identity verification process, but the process works smoothly.

Before getting on to additional server-side configuration steps, just a quick word on Windows WireGuard clients. You’ll need to download the WireGuard software, install it and add the configuration file for the VPN. AlgoVPN will leave these configuration files in configs/<server public IP>/wireguard inside the folder containing the AlgoVPN scripts. You’ll probably want the desktop.conf file. Copy this over to your Windows PC and add it to WireGuard. Lastly, take a look at my follow-on blog post about the configuration settings you’ll need to redirect LAN traffic back to your LAN, instead of having it go over the VPN (which makes it impossible to reach any other device on your LAN). This isn’t needed on Linux, but is necessary on Windows.

The next important step is securing the server. By default it doesn’t have any more than the essential services running AFAIK, but I’d rather not accidentally lose my VPN server. Here’s a list of the things I changed:

  1. Add a non-root user with sudo privileges and SSH access, because logging in as root makes it too easy to mess up your configuration. Use su to switch from root to your new user. Now generate an SSH key, or use the one created by Algo VPN and manually add the public key into ~/.ssh/authorized_keys.
  2. Disable root login via SSH. By default, DigitalOcean droplets only have the root user and that is the user that you log in with. Since we never want to log in as root (that’s what sudo is for), lets disable root login via SSH for a small bit of extra security. Now restart SSH using sudo service ssh restart for all your changes to take effect. Log out of your server and try logging in again with the user you created above. If anything goes wrong, remember that DigitalOcean also provides a console through which you can log in to the VM and fix your mistakes. The console is much slower than using an SSH session, so I only use it when I’ve made a mess.
  3. Setup a firewall that blocks all incoming connections except SSH and UDP connection on port 51820, which is used by WireGuard. The commands to do this are:
    sudo ufw default allow outgoing
    sudo ufw default deny incoming
    sudo ufw allow ssh
    sudo ufw allow 51820/udp
  4. Install Fail2ban, which checks for failed login attempts and blocks the IP addresses from which those login attempts originate. By default, it monitors SSH. The configuration file has separate jails that can be enabled for other popular services, e.g. web servers. This is actually pretty important, as there have been almost 100 failed SSH login attempts in the ~2 days this server has been running.
  5. Install sendmail with sudo apt install sendmail. Fail2ban can be configured to send emails whenever something interesting happens, but it needs sendmail to do that. Unfortunately, the default configuration results in a very slow sendmail, e.g. taking 2 minutes to send a simple email. It appears that sendmail requires a fully qualified domain name for the VM, if it doesn’t have one, it waits for about 2 minutes before trying again to get the name, before settling on a short name (the host name). The solution for me was to edit /etc/hosts, replacing the line 127.0.0.1 localhost with 127.0.0.1 localhost <hostname>.<hostname> <hostname> solved this problem. Note that you’ll need to make this change to /etc/cloud/templates/hosts.debian.tmpl as this file is used to generate /etc/hosts. Note that this template allows using {{hostname}} as a placeholder for the actual host name. The <hostname>.<hostname> part can actually be anything that makes a valid fully qualified domain name (even if it isn’t a real domain). Just having something looking like a fully qualified domain name is enough for sendmail.

All of the above steps are an amalgamation of advice sourced from the following links:

There are also some steps to increase security when there are multiple users sharing the same server. While this doesn’t apply to me, if it applies to you here are the guides:

There is one irritating kink, Netflix and ShowMax don’t like VPNs. It’s understandable, I could be using my VPN to view US shows that I normally can’t access in South Africa. It is possible to add routes to the IP routing table so that accessing IP addresses used by Netflix get routed directly to the network interface, instead of the WireGuard VPN. This can be done using ip route add <IP address range> via <gateway IP> dev eth0. Example IP address ranges are 45.57.0.0/16 and 52.40.0.0/14. Unfortunately, these keep changing, and the last range corresponds to AWS IP addresses. It hardly seems wise to operate a VPN but then allow all traffic to AWS to bypass that VPN! I also gave OpenVPN a try, using the OpenVPN+Pi hole configuration available on DigitalOcean. OpenVPN does allow providing routes that redirect entire domains to your gateway instead of the VPN server. I tried this with every Netflix-related domain I encountered, but still no luck. Behind the scenes, OpenVPN looks up several IP addresses associated with the domains I provide. However, it seems that the IP address ranges it identifies aren’t large enough to successfully reroute all Netflix traffic.

One solution could be to move my VPN server to South Africa, but the cost ends up being much higher, not just for the compute instance itself, but also the data transfer out of the cloud, which ends up being much more expensive. If only DigitalOcean operated a data centre in South Africa.

Another funny consequence of using a VPN is that Google gets confused about what language I speak. Come on Google, I’ve logged in to you, I have an Android cell phone, how can you get something so basic wrong when you know exactly where I am? A funny paranoid thought that comes to mind is that presenting some suggestions in the language of the country hosting my VPN server is to lull me into a false sense of security, making one think Google knows less about you than they actually do. Yeah right, why would they bother :).

The final disadvantage of running my own VPN in a different continent is the added latency, especially when gaming. With the VPN off, the average, minimum and maximum pings to one of the Dota 2 servers in South Africa is 11ms, 3.5ms, and 60.4ms. Switching to the VPN increases the average, minimum and maximum latencies to 441.7ms, 388.7ms and 517.8ms respectively. Fortunately, the list of IP addresses that need to routing rules added seems to be small and fixed, so this is relatively minor.

One thought on “How I started hosting my own VPN

Leave a comment