Creating My Own VPN With OpenVPN On AWS

Now I have always thought about getting a VPN subscription for some time. Already researched a bit about it several times before. I always somehow keep on having second thoughts about getting one for several reasons that I won’t mention here.

I’ve already implemented a VPN back when I was still in Singapore, using OpenVPN. It wasn’t so hard. Just a simple one. Stable. It was used to secure or isolate my source code somewhere. The idea was that the code was to sit on a repository on a Linux server running on an EC2 instance, and it can only be accessed within the company’s private network. Kallithea, a source code management system, was used that time. The idea was sort of a “success” that it was promoted to something official. All company software code were migrated there eventually. The whole software development team started using it soon after. Later on partner companies were also given access to the VPN to publish and pull software source code to that repository as it is easier to collaborate like that. It also helped since a number of these partners were not always in Singapore (e.g. Some were in Philippines, Vietnam, Malaysia, etc.). Anyway, that’s that. Don’t ask me why the company did not opt for something like BitBucket or GitHub.

Last night, I thought about making my own VPN on AWS. It should be able to provide my devices access to the Internet, and once connected it should be as if I were somewhere else. (That’s the whole point of getting a VPN anyway, right?). I installed one on an Ubuntu 20.04 LTS server. Took only an hour or a half to get everything going.

It already works. Had some hiccups along the way. I was able to connect to the VPN but I could not “browse” anything. So I was just in a virtual private loop which made it pretty useless. But I was able to fix it of course. The only other thing left for me to do is to move this, or rather re-implement the OpenVPN server setup, on another AWS region. Right now it’s located in the SEA area and I’d prefer if it were somewhere further up north on the other side of the world.

Server Side

To install and configure, I have these 2 options.

Option #1 (Recommended)

This saves time a lot. It is a Linux shell script to install OpenVPN taken from here: https://github.com/Nyr/openvpn-install. I’m most familiar with Ubuntu, so I chose to spin up an EC2 instance of it on AWS. The minimum version for this script to work on Ubuntu is 18.04.

If you want to do the same and you’re not familiar enough, follow this guide too: https://linuxhint.com/vpn_amazon_ec2_setup. It assumes you don’t have an AWS account yet, or know anything about starting a Linux/EC2 instance on it.

Note: Make sure your AWS Security Group for this instance allows for the necessary port. The default port is 1194. Also, check that the OpenVPN services listed below are running after you complete all of the installation steps. For some reason after the 1st install on my SEA server instance, those were in a stopped state. Took me several minutes to realize why it appeared like I was connecting to a black hole. Lastly, I set the ports to accept connections from my IP address only.

:~$ service openvpn-server@server status
:~$ service openvpn-iptables status

Option #2

Link to the how-to: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-16-04.

Started reading up on this option to refresh my memory, but settled for a faster approach. So I ended up using Option #1 instead. Read through it and at least be familiar on what that shell script is essentially doing. Would be a good way to learn something in the process too. This is more hands on with the installation process. It is a very thorough tutorial for Ubuntu 16.04 Xenial Xerus. I’m still a fan of Xenial, but they have a how-to page for other Ubuntu LTS versions as well. Just Google for it.

Client Side

It is time to take it for a spin. The following command will connect me to the VPN server.

:~$ sudo openvpn --config <name of file>.ovpn

The angle brackets above is replaced with the name of the client configuration file.

Oh, this is done on my desktop now. We are on the client-side of things here.

It is connected when the messages stop and it says at the end:

Initialization Sequence Completed

Plus pointing my browser somewhere to check if I can still browse the Internet. My IP address also coincides with the AWS EC2 instance’s assigned IP. ipchicken.com is an easy way to know if it is.

I used the shell script above because I’m lazy. Now what?

That was what I did. Being lazy and all, wanting to use shortcuts. It did not work at first. I could not even connect to the OpenVPN server. It kept on timing out. The error was that it could not recognize some options in the client configuration. If you are getting this, you’re probably using an older OpenVPN version. Upgrade to at least 2.4.* version. The latest stable version as of this writing is 2.5.*, so perhaps use that first then fall back one version lower if you’re having issues on your OS.

On Ubuntu 16.04, the stock OpenVPN is 2.3 something. That won’t cut it. I had to install the latest. Luckily I did not have to compile from source.

Upgrade/Install Latest OpenVPN

I got the latest version here – https://openvpn.net/community-downloads – and scrolling down, is a link to the official Ubuntu/Debian apt repositories. Non-Ubuntu/Debian such as RPM based distros or Windows installers are also found on this given link.

Updated again once the repository details have been added, then proceeded to install the latest stable version. Doing “sudo apt install openvpn” ought to do it.

No Internet Connection?

The client configuration file created with Option #1 works right out of the box. I’ve tried it that way. The certificates and keys needed to connect are all there “in-lined” in the same file. Open the .ovpn file in a text editor. You’ll notice blocks of unreadable text there enclosed in what looks like mark-up tags such as <ca>, <cert>, etc.

However, if you are like me who like those values in its own file and buried somewhere in the filesystem, you can still do so. But make sure you also include the tls-crypt option. This connection depends on such, or else the server-client authentication will fail. This was one of the mistakes I made, getting a “TLS Error: TLS handshake failed” screaming at me every time I tried to connect.

I made the fatal mistake of not defining tls-crypt, and instead went with tls-auth option because I did not read the tags carefully.

At the very bottom of the file is a <tls-crypt> tag enclosing another key which is further enclosed in BEGIN/END OpenVPN Static Key V1 text.

The client configuration file will finally look like this:

client
dev tun
proto udp
remote <IP address> <port>
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA512

#cipher AES-256-CBC
data-ciphers AES-128-GCM
data-ciphers-fallback AES-256-GCM

ignore-unknown-option block-outside-dns
block-outside-dns
verb 3
ca /path/to/ca/file
cert /path/to/cert/file
key /path/to/key/file
tls-crypt /path/to/tls-crypt/file

Where those /path/to/<*>/file lines are replaced with the actual local path of those separate files on my desktop.

Update

DEPRECATED OPTION: --cipher set to 'AES-256-CBC' but missing in --data-ciphers (AES-256-GCM:AES-128-GCM). Future OpenVPN version will ignore --cipher for cipher negotiations. Add 'AES-256-CBC' to --data-ciphers or change --cipher 'AES-256-CBC' to --data-ciphers-fallback 'AES-256-CBC' to silence this warning.

In the client connection logs, OpenVPN will warn that the –cipher option is deprecated like the above log messages. And to use AES-256-CBC as a fallback. I’ve changed it to the following instead:

data-ciphers AES-128-GCM
data-ciphers-fallback AES-256-GCM

AES-128-GCM is supposed to be faster than AES-256-GCM. Also changed server to use the former and added option –ncp-ciphers to use the same too.

Similar Posts: