This post and project has been a long, long time in the making and I am super excited to share module and project work!

Terraform and OpenVPN - a free, ephemeral vpn option

Background

This project came about after using the Hola Chrome extension for quite a few number of years, but recently they had started instrumenting limits on free tier usage. Basically, sometimes I could use the extension for a couple of hours without issue, other times, it would give a dreaded “you must wait 8 hours before next use” message.

I don’t use VPN for much of my regular Internet activity; the primary reason was to watch YouTube videos without country restrictions - specifically Last Week Tonight and SNL videos 😄

Recently, I have also been investing some very, very small amounts in Crytocurrency and a good practice is to transact only over a secure VPN where possible. After looking into some options, I quickly deducted that I didn’t want to spend $X amount of money per month for a VPN service that I would use at max 10 times in a month. That’s 20 extra days that I may not use the VPN, so why pay for it!

Further, while I respect the work these VPN companies do, I also didn’t want to spend $X per month for a service that may become embroiled in a data leak (especially when this is becoming more and more common) and there’s no guarantee that these services will always be available when I them to be - due to maintenance or businesses shutting down etc

OpenVPN, Terraform and AWS

Looking for a free, open source VPN service, OpenVPN seems to fit the bill and use-case nicely. Further, angristan wrote up a great installer which I saw referenced in a lot of other blogs during my research. I figured I could utilize the installer along with Terraform to setup an infrastructure to setup an OpenVPN EC2 Service that I could use on-demand when need be.

I spent a bit of time testing locally how to best use Terraform to spin up the infrastructure, and went through a revision where instead of having an EC2 instance with ssh open to my public IP, I could lock this down to just AWS SSM Manager access only. This is becoming a security best practice these days, and the less port 22 is used for EC2, the better 🙂

Another revision was made after noticing that in order to save the tls_private_key pem key that Terraform creates, the value needs to be echoed out to the command line. This isn’t great security-wise, and variable values can only be marked as sensitive in Terraform 14+ (per this). So, in order to suppress this pem key from the command line, a dummy sensitive = true variable exists in variables.tf and this has the intended effect!

No command line logging of keys here!

What ties all of this together in this module is actually the local-exec provisioners, specifically the null_resource obtain_ovpn_file provisioner. During initial testing, I was previously using a sleep command with 30 seconds to wait for the openvpn service to register successfully, but the startup time was ranging between 30 seconds to 1 minute, so it was hard to actually gauge what that sleep value command should be set to. Using a until with a do loop helps to speed up the overall time and avoids using a sleep command that may error out if the openvpn service needs more time than say 30 seconds.

The module in all its glory is here (and here) and by using this setup, I have been able to use a VPN tunnel to various countries within a matter of minutes, and all for the low, low price of $0 (yay free tier!), also without having to sign up my email to any service.

MacOS

As a MacOS user, there are also a couple of cool additions that help make the VPN experience nicer. Firstly, using an alias with zshrc that runs open for the openvpn.ovpn file that is downloaded means that after typing in the alias command to start up the terraform logic, the OpenVPN Connect app opens the profile for import right when it is completed.

Further, a neat trick is also that you can AirDrop the openvpn.ovpn file between iOS devices like an iPhone or iPad, so you can use the VPN service from those devices too!

Unfortunately, I don’t yet have support for other OS’s, but Pull Requests are welcomed to the module!

YouTube USA via VPN!

So what does all this work eventually provide in the end? Well, let’s take a look!

Here is a typical view of SNL’s YouTube channel from Canada:
Canada's view of SNL on YouTube

Here’s the standing up of the OpenVPN service in us-east-1:
Successful Terraform Apply
Connected via OpenVPN Connect

Here’s the view of SNL’s YouTube channel from the USA:
Way more videos on SNL USA YouTube

When watching a video, if I disconnect the VPN and refresh the page, I receive the following as expected:
Video not allowed outside of USA

The future

Thinking constantly about how to make the service more efficient and faster, I may eventually dabble in trying to hook up a simple webpage to a Terraform Cloud workspace. I’m envisioning a user would log in using their Terraform Cloud credentials, then choose a region where they want to stand up the OpenVPN server in, and the openvpn.ovpn file downloads via the browser for the user to use with their client. When the user is done using the VPN, they would click a “shutdown” button and the infrastructure would then be deleted. Time will tell if I ever get around to making this a reality 😄

Happy watching!

Recap

  • OpenVPN on an EC2 instance in your own AWS account is a reasonable alternative than paying for a VPN service every month
  • Terraform module can be used to make this VPN startup/shutdown super easy
  • I don’t understand why there are blocked videos per country, but the Terraform module gets me around this quickly and cheaply 😎