How to make your own self-hosted VPN server using OpenVPN
OpenVPN
Table of contents:
In this article you’ll get end-to-end instructions on how to create and operate a self-hosted VPN server using OpenVPN community edition under 5 minutes for just 4 euros per month with unlimited number of connected clients. In this article you’ll also learn how to configure a client’s profile so you can get connected and use your self-hosted VPN server using either your computer or telephone. I’ll try to write as approachable as possible so anyone with decent computer knowledge can go through this and set it up. In the light of some recent changes in my motherland country it is important for people to stay connected with the rest of the world and follow broader sources of information for making personal opinions, avoid group thinking and maintain clear understanding of things happening around.
What is VPN and how does it work? #
VPN stands for Virtual Private Network and it is the easiest and quite often mechanism for making connections between two systems private. It’s also in use quite often these days in a corporate environment (especially with work from home regulations) when an employee needs to connect to a corporate network in order to get access to some internal systems or fileshare to use company’s documents. VPNs can also help to connect multiple branch offices in a secure way so the documents flow as well as the systems communications can be done privately (i.e. central fileshare in the hub-spoke model where employees can access and use the same documents together). These days VPN has another use case which is access to remote systems going above and beyond bypassing either government firewalls or corporate blocks. As bonus VPN’s consumer gets 256-bit encryption traffic so bad actors as well as audit trails will be away from personal data being sent to target systems and it’s getting super important when working in unsecured wifi networks (i.e. cafes or free public wifi) as the request headers and payload are being sent as plain text (or base64 encoded) in the systems without https which is not a big deal to intercept and decode.
When you type for example https://www.google.com
the request hits the DNS server and gets the IP address resolved with the content of the web-site that you are requesting. Once an IP address is being returned the browser sends a https request (GET) to fetch the information from the server with the IP address that has been resolved. Without VPN such request is made by your compute and goes directly to the target server to fetch information from it (i.e. html files, css stylesheets and js - these three are the core of any web site; of course there are more, but let’s leave it for now). With VPN the traffic goes via extra hop, which is a VPN server.
Now in that picture above we also have a firewall with either corporate blocks or government regulations. How does this work? Well there is something called firewall that typically has list of rules what can and what can not be accessed. This list contains either IP(s) or even subnets of IPs typically using CIDR notation for describing blocks of IP addresses (i.e. 10.10.10.0/24 which means block 256 IP addresses in this subnet starting from 10.10.10.1 and finishing 10.10.10.254) or FQDN (domain name) which blocks number of IP addresses to which the DNS is pointing (A/AAAA or CNAME records). In some cases admins set white and black lists by countries meaning that only devices with IPs from certain countries can use the system, access the web site or it’s parts. There are more, including conditional access that forces you to confirm your identity by second factor etc..
These days there are 4.3 billion IPv4 IPs address that back in 1990s engineers thought will be enough for the entire world but failed with the assumption, we are now having deficit of them and hence IPv6 which is 128-bit length space (would give 2**128 addresses for the World ==> 340 undecillion 🚀) is here to help with growing number of devices that needs publicly available IP. But that does not matter, both can be blocked.
So the VPN server can instantiate requests on its behalf by sending request headers that are allowed by the target system or it’s defence. In VPN as a service you can change the country meaning that youre request is being sent via the server in the selected country.
VPN as a service #
ExpressVPV | NordVPN | Surfshark | ProtonVPN | IPVANISH | Namecheap | |
---|---|---|---|---|---|---|
Servers | 3000 | 5000 | 3200 | 560 | 1300 | 1000 |
Countries | 94 | 62 | 65 | 54 | 55 | 53 |
Devices | 5 | 6 | Unlim | 1-10 | Unlim | Unlim |
Price | $ 8.32 | $ 3.71 | $ 2.49 | $ 4.00 | $ 4.99 | $ 1.53 |
Basically you just download the app on your phone or computer and follow the configuration instructions. The server’s part has been set up for you (see line servers indicates number of servers the company owns to handle the load of users like yourself using their VPN services; server is where your device is being connected to use VPN). In this article we build this server part using OpenVPN.
OpenVPN #
OpenVPN as most of the companies these days offer a cloud based version of it’s solution with 3 devices for free (so maybe you don’t even need to read further).
OpenVPN is also available in different other forms (i.e. virtual appliance for on-prem installation to ESXi or HYper-V, they offer OVF template to import), cloud images (AWS, Azure, GCP and Digital Ocean), packages for popular OS. Als there is a VPN client for most of any device can be obtained here.
Where to install #
In my experiment I used Azure (with VM in west europe
) and Yandex Cloud (with VM in ru-central1-a
), but it does not really matter, as long as openVPN package supports the OS you have you can proceed with the further instructions.
One little remark that I need to make here is that the choice of VM and its location should be made based on your device location and access requirements. For Azure regions I used Azure Speed Test to check the latency.
Based on the above the best (closest, lowest latency) would be the west europe region, so I ’ll proceed with the creation of the machine in this region.
Other than that you can consider any other cloud provider that is more comfortable for you and better suits needs and requirements.
Install self-hosted VPN #
While these days I am doing everything as code and specifically for Azure I use Bicep in this article I’ll do works in the portal so it’s clear what has been created and configured. We’ll use Azure cloud for this purpose as has been mentioned, but the approach is possible to transpile and use in any other place (just make sure the underlying OS is supported by OpenVPN packages).
Login to the portal of Azure and create new resource group:
Once the RG is created, go ahead and create a new VM with Ubuntu 20.04. This should be straight forward, I just want to highlight that it is always good to use RSA key authentication versus password. If in Windows, probably WSL (or putty with some utilities can help), in Linux / MacOS you can do something like this:
1ssh-keygen
2cat ~/.ssh/id_rsa.pub | pbcopy
- First command will generate key, follow instructions (if the key is not there yet, otherwise skip this);
- The above generated key is being saved in the home directory,
pbcopy
copies it to the clipboard on your macOS.
- Pick the SKU of VM according to the needs, but most likely for personal use
Standard_B1ls
is good enough; - Think about internet egress (traffic that you download), 100GB is free, everything above is charged;
- If in doubt use the following calculator to find out the estimated price for the resource usage.
So the bare minimum for the infrastructure in Azure would be 3.99 euro. Keep in mind that this VPN server can be used for multiple clients, so at some point it’s cheaper than SaaS. If stuck with the VM creation, there is always good Microsoft documentation.
By default OpenVPN uses port 1194 for the communications (you can also change this), but let’s stick with the default. We also need port 22 to SSH into our machine. Let’s make sure that Security Group allows this for our machine:
Now, let’s SSH into the machine and install the packages. If everything has been properly followed and SG has the port for SSH available you should be able to connect to your VM by now.
1sudo -i
2wget https://raw.githubusercontent.com/weekendsprints/openvpn-install/master/openvpn-install.sh
3chmod +x openvpn-install.sh
4./openvpn-install.sh
We just used the shortcut to install all the dependencies and OpenVPN itself along with the client’s configuration (this involved apt package manager to install openvpn and easy-rsa to generate certificates as well). Kudos to Nyr. If all is good by the end of the script run you should be able to see the client profile /root/client.ovpn
.
In the above 4 lines we:
- elevated permissions to root (
sudo
command); - downloaded
openvpn-install.sh
file from the github (feel free to fork and change according to your needs); - changed permissions to executable (
chmod
command); - and ran the script.
We need to fetch that client’s profile. Disconnect from the VM and scp it.
1scp <public_ip>:/home/evgeny/client.ovpn .
File should be like this and as you can see it has port 1194 and server’s public IP that client will use to connect to. OpenVPN can work with both TCP and UDP protocols (in the above excersice I’ve added both protocols in the security group).
1client
2dev tun
3proto udp
4remote [REDACTED] 1194
5resolv-retry infinite
6nobind
7persist-key
8persist-tun
9remote-cert-tls server
10auth SHA512
11cipher AES-256-CBC
12ignore-unknown-option block-outside-dns
13block-outside-dns
14verb 3
15<ca>
16[REDACTED]
17</ca>
18<cert>
19[REDACTED]
20</cert>
21<key>
22[REDACTED]
23</key>
24<tls-crypt>
25[REDACTED]
26</tls-crypt>
27
Client configuration #
Let’s try this file on macOS first.
- Download the client from here and install (should be “next-next” type of process);
- Import the
.ovpn
file; - Switch on VPN.
The fastest way to check if you are working via VPN is to check your IP or in terminal curl ifconfig.me
to see what is the output (should be equal to the public server IP in Azure).
Let’s repeat the same for iPhone.
- In the App Store search for OpenVPN and install;
- Open up and notice that it needs either url or file for the profile (it needs
ovpn
file); - To send this to iPhone you can use AirDrop (right click on the file and send to your iPhone);
OpenVPN makes changes to VPN configuration, you’ll need to allow this action.
Sumamary #
While this has been implemented on Azure with use of macOS and iPhone, there is no big difference to have it done with any other cloud provider and Windows PC and Android (OpenVPN client is available there as well).
Keep calm and use VPN!