Configure a self-hosted VPN Server using OpenVPN Access Server and Azure VM
Creating and configurating the Virtual Machine
First you must create an Azure VM. If you intend to use it only for you I suggest using a very low power VM running Ubuntu.
You can check hardware requirements for an Access Server installation on the official OpenVPN documentation: https://openvpn.net/as-docs/system-requirements.html#hardware-requirements
For memory requirements it says that you should start with at least 1GB of RAM and add 1GB for every 150 connected devices. For hard disk it says that typically, 16GB of disk space is sufficient, as it only needs to store connection logs, program logs, user certificates and settings.
For this example we will be using a Standard_B1s, which has 1 vcpu, 1GiB of RAM and 4GiB of local storage. Remember that in the creation of the disks you can use a different sized disk, the default should be a 30 GiB disk, so we will be using that. Also a Standard SSD LRS is enough for our use, you do not need the Premium SSD. You can use a larger disk if you feel it would not be enough, but in my case it has been enough so far.
For networking we will be creating a new Public IP to assign it to the VM. This public IP will be the one that will be connecting from when connected to the VPN, so all our connections are made from this IP.
We will be using the latest Ubuntu Server LTS available, at the time of writing this the latest version is 24.04 LTS
Once our VM is created and ready, I suggest configuring the following Inbound port rules inside the Network Settings on the Virtual machine resource:
Priority | Name | Port | Protocol | Source | Destination | Action |
---|---|---|---|---|---|---|
Default (300) | SSH | 22 | TCP | Your IP | Any | Allow |
Default (320) | HTTPS | 443 | TCP | Any | Any | Allow |
Default (330) | OpenVPN | 1194 | UDP | Any | Any | Allow |
Default (340) | OpenVPNAdmin | 943 | TCP | Your IP | Any | Allow |
I will briefly explain each rule and its configuration:
- SSH: This is for connecting through SSH so you can configure your VM. I recommend using your IP in the Source field, and even change it from Allow to Deny once you have completely configured the VM to reduce the attack surface. Remember that this VM is going to be exposed to the internet.
- HTTPS: Used only for downloading user profiles from the OpenVPN Connect client. Once you have the profile downloaded on all your devices, you could change this rule to Deny to reduce the attack surface.
- OpenVPN: This UDP port is what we will use to establish the VPN connection. Leave Source as Any to be able to connect from anywhere, otherwise if you are on a network that has a static IP you could set this field to that IP to reduce the attack surface.
- OpenVPNAdmin: Port used to connect to the web panel. Set the source to your IP or either Deny any connection after all the set up is done.
Installing and configuring OpenVPN Access Server
Open an elevated terminal using sudo su -
and run the following command:
bash <(curl -fsS https://packages.openvpn.net/as/install.sh) --yes
You can check if the service is running by executing systemctl status openvpnas.service
You will need to create a user using the OpenVPN Admin web panel. The default port (and the one we exposed on the network settings of the VM) is 943, so you would access the web panel by accesing to https://{your-vm-public-ip}:943
You will need to retrieve the auto generated password which is set when OpenVPN initializes. You can get it by executing cat /usr/local/openvpn_as/init.log
At the end of the file you should see something like this:
To login please use the "openvpn" account with "{REDACTED}" password.
openvpn
is the default admin user, your randomly generated password should be in place of {REDACTED}
Enter to the OpenVPN web admin and create a new user that you will be using for connecting to the VPN. Also make sure to change the openvpn
user password to something more secure.
Installing OpenVPN Connect
If you are on a desktop computer download the OpenVPN Connect client from the official website: https://openvpn.net/client/
You can also get the client either for Android or iOS from their respective app stores by searching OpenVPN Connect, make sure the developer is either OpenVPN or OpenVPN Inc.
Configuration and connection procedures are the same on all platforms, Windows, macOS, Android and iOS, as they all share the same UI. Linux is the exception as it uses a command line tool, you can refer to the documentation on the link provided earlier in this section.
Configuring a profile and connecting to the VPN
Open OpenVPN Connect and you will be asked right away to insert a "Server Address or Cloud ID". We will write the virtual machine public IP address where we installed OpenVPN Access Server.
At this point is important to have configured the HTTPS port and is accessible from our current network IP. If it is, most probably you will be greeted with a certificate error, you can choose to accept it because we have not configured any SSL certificate and is using a self signed certificate. You can check the Common name under Issued by to ensure the hsotname of your VM matches with this.
Then we will be asked for a username, password, profile name and port. Use the username and password you created previously on the OpenVPN web admin panel. You can choose to give it a name to identify it easily. For the port, you can leave it blank as it will use the default 1194 UDP.
Before connecting, press the pencil icon at the right of the profile. You will see an empty field named "Server Override (optional)". I'm not sure if it is a bug or is something which is misconfigured and I'm not yet aware, but if you do not configure this field you will receive a timeout and never reach the VPN server. In this field write the virtual machine public IP as we did when configuring the profile. Server Hostname and Server Override must match.
While at it, you can also check "Save password" if you want to avoid writing the password everytime you want to connect to the VPN, make sure to write the password on the field that just appeared when you pressed on the checkbox.
Press Save at the top right and you will returned to the main screen. With all this in you should be able to connect to your VPN, press on the slider on your VPN profile and you should connect to the VPN right away. You should see a graph indicating bytes in and bytes out, along other information.
Make VM safer using fail2ban
As I said previously, after configuring users and profiles you can deny access to most of these ports except the OpenVPN port which corresponds to UDP 1194
Either way, if you want to make your VM even stronger against attacks, specifically brute force attacks, you can install fail2ban. This is not necessary for OpenVPN but is presented here for completeness. Notice that you can also configure a "block account" setting on the OpenVPN admin web panel which disables an account if too many failed login were attempted, which is similar to what fail2ban does, except fail2ban bans the IP from which these requests were done, and for much time as wanted. This in fact deny access to the source IP to the VPN server, where it doesn't even have an opportunity to connect to the server.
Installing fail2ban
You can install fail2ban by running the following command:
sudo apt install fail2ban
You can check if the service is properly running by executing systemctl status fail2ban.service
Configuring OpenVPN Access Server filter and jail
Configuring a jail and its filters is an involved procedure that takes some time as, at least in this case, we must check failed login attempts looking at the log files that OpenVPN Access Server writes, while also retrieve the IP from which these requests are being made.
You can use command fail2ban-regex
to test your regex for parsing the log files, this is an example I was using against the OpenVPN Access Server logs:
fail2ban-regex -v --print-all-matched /var/log/openvpnas.log "^(.*)\"<HOST>\"\s\-\s\-.*\"GET.*HTTP.*401\s177.*" "127\.0\.0\.1"
Hard to understand at first sight, but it basically does some regex operations, while also adding an exception for the 127.0.0.1
IP, which I don't want to block. I added this just in case because I have seen some requests made from that IP, which is basically the loopback address localhost, you might not want to block that. I also want to make sure to count for when the error is an authentication error, 401 in this case.
Once you have a working regex, you can create the filters. I will be using two different jails and filters in this case. One is for failed attempts at the OpenVPN web panel, and the other from the client.
I will create first the OpenVPN Connect filter by running sudo vi /etc/fail2ban/filter.d/openvpnas.conf
and the following content:
[Definition]
failregex = :[0-9]+\sSENT\sCONTROL\s.*?AUTH_FAILED.*
ignoreregex =
The second filter is for the OpenVPN web panel, the same as before, create another filter at /etc/fail2ban/filter.d/openvpnas-https.conf
[Definition]
failregex = ^(.*)\"\"\s\-\s\-.*\"GET.*HTTP.*401\s177.*
ignoreregex = 127\.0\.0\.1
Now proceed to create the jails. I will create two jails inside a single file at /etc/fail2ban/jail.d/openvpnas.conf
[openvpnas]
enabled = true
filter = openvpnas
logpath = /var/log/openvpnas.log
backend = polling
maxretry = 6
bantime = 86400 # 1 day
findtime = 600 # 10 minutes
[openvpnas-https]
enabled = true
filter = openvpnas-https
logpath = /var/log/openvpnas.log
backend = polling
maxretry = 3
bantime = 86400 # 1 day
findtime = 600 # 10 minutes
You can check what these values do by searching up the fail2ban manuals and documentation, but most of these are easy to understand at first sight.
Once these files are in place, restart the fail2ban service by executing sudo systemctl restart fail2ban
If jails are properly configured you should see them by running the command sudo fail2ban-client status
, this is my output:
Status
|- Number of jail: 3
`- Jail list: openvpnas, openvpnas-https, sshd
You can further see if there is any banned IP on each jail by running the same command plus the name of the jail you want to check, for example sudo fail2ban-client status openvpnas-https
, my output is the following:
Status for the jail: openvpnas-https
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /var/log/openvpnas.log
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
With all this, you should have two jails working, one for the OpenVPN Connect client and another for web access. You can try this by doing some failed login attempts, just make sure to do it from a network where you have a dynamic IP and it can be changed easily, otherwise you will be banned by as much time you specified on the bantime settings, which in the example above it is 1 day.