How to make your own free VPN with Amazon Web Services

Internet users are spoiled for choice when it comes to VPN services, but they either require a monthly subscription, aren’t secure, or are just plain slow. Thankfully, alternatives do exist. They require a bit more technical know-how, but if you want something done right, you have to do it yourself.

To learn how to make your own VPN, you can watch the video or read the article. Note that the article contains some useful commands and configuration text that you can copy and paste for your convenience. Update: the video uses an old version of easy-rsa that is no longer available. When you get to the 8-minute mark, please refer to this article for easy-rsa 3 configuration.

Getting started

Amazon Web Services offers one year of free virtual server space, provided you use less than predetermined amounts of bandwidth, time, and space. Even if you go over that limit, the cost of running a server image on Amazon’s Elastic Compute Cloud is probably less than you would pay for a VPN subscription.

Here we’ll explain two different ways to use Amazon’s Elastic Cloud service, also called EC2, to divert your connection through a private location of your choice: SSH Tunneling and OpenVPN. Each has advantages and disadvantages, so use the one you find more suited to your needs. No matter which you choose, you’ll require the following:

  • An Amazon Web Services account. This requires a credit card, but you’ll only be charged for what you use, which will likely be nothing if you’re prudent about what you’re doing.
  • PuTTy, if you’re on Windows. OpenSSH via Cygwin is another option, but I found it to be a pain. Linux and Mac computers already have SSH prompts built into their boxes and terminals. You’ll also need PuTTy’s sister key generation program, PuttyGen. You could also use a PuTTY alternative, some of which also incorporate SCP and FTP.
  • WinSCP, or an equivalent FTP client to move files between your local computer and your EC2 instance.
  • A basic working knowledge of Unix commands and how servers work with clients will be massively helpful in troubleshooting should something not go exactly as planned.
  • OpenVPN GUI, installed in the default location and with the default settings on your PC

Setting up AWS

Once you’ve signed up for an Amazon Web Services account, here’s how to launch the server that we’ll use for our VPN::

  1. Log into your Amazon Web Service account and head to the EC2 dashboard.
    aws vpn update 1
  2. On the top right, you can choose the location where we’ll be setting up your VPN. Click Launch Instance.ec2 vpn 1
  3. Choose whatever Linux AMI is listed as “free tier eligible.” At the time of writing this article, that’s the Amazon Linux AMI. Go on to the next step.ec2 vpn 2
  4. Here choose a t2.micro instance that’s also free tier eligible. Click “Review and Launch.”ec2 vpn 3
  5. On the next page, click Edit Security Groups.edit security pages
  6. You’ll need to edit the security group to only allow traffic from your computer to access the VPN or proxy. You should have one rule already in place for connecting to your server via SSH, which we’ll use later. We’ll need to add another to allow OpenVPN connections, which use port 1194 by default. For simplicity’s sake, under the Inbound tab, click the Add rule button. Set the Type to Custom UDP, the Port Range to 1194, and the Source to Anywhere.EC2 add security group rule button
  7. Hit Save.EC2 security group anywhere to port 1194
  8. Click “review and launch,” then “launch” on the next page.
  9. Now you’ll want to create a key pair, which sort of works like a password that you’ll use to connect to the virtual server you’re creating. Select “create a new key pair” from the dropdown menu and name it whatever you like. Click the button to download the key pair. Store it somewhere safe.ec2 vpn 5
  10. The next page should alert you that the instance is launching. Scroll to the bottom and hit “View instances.” Here you’ll see a list of any instances you’ve launched, which if this is your first time using EC2 will just be one.

Connect to the server with PuTTy

We can connect to our EC2 instance with PuTTy, but first we’ll need a proper key file to get connected. When you installed PuTTy, you should have also installed PuTTygen. Go ahead and run it now. PuTTy and PuTTygen both run right out of the box as .exe files with no need to install.ec2 vpn 7

  1. Open PuTTygen, click Load.
  2. Navigate to the .pem key pair file you downloaded before and load it into Puttygen. You’ll have to select the option to show all file types for the .pem key to show up. Hit “Save Private Key.” The file name must be identical to the .pem key. You can create a passphrase for the private key if you want.ec2 vpn 6
  3. Now close out of PuTTygen and open PuTTy. Copy your instance’s public IP from the EC2 console into PuTTy. Type in a name for your session and hit save.ec2 vpn 8
  4. In the left pane, navigate to “Auth” under SSH. Click the browse button at the bottom and navigate to the private key you just generated.
  5. Back on the main Session page, name and save your session profile so you can quickly connect the next time you use PuTTy. Then Click Open.
  6. A prompt will appear asking you for a username. This differs based on what type of server you set up at the beginning. For the Amazon Linux AMI, it’s “ec2-user”.

SSH Tunneling (optional)

To begin with, we’re just going to reroute web traffic through the instance we created using SSH tunneling and a proxy. This is a quick and dirty way to get around a firewall or geographic lockout. It’s not quite a VPN–it’s best for light web traffic and won’t work with everything–but it’s much more simple to set up. However, setting up SSH tunneling is entirely optional, so feel free to skip to the next section.

ec2 vpn 9

Open PuTTy and navigate to Tunnels in the left pain. Add port 8080 with Auto and Dynamic selected. Go back to the Session page and hit Save again so you don’t have to do all this over again. Then click Open.

ec2 vpn 10

Now you’re connected to your server, but you still need to route your web browser’s traffic through it. If you use Firefox, this can be done in your browser settings. If you use Chrome, download the Proxy Switchy extension. If you prefer to create a fully functioning VPN rather than just a proxy for your browser, skip to the next section now.

In Firefox:

  • Go to Tools > Options > Advanced > Network > Connection > Settings > Manual proxy configuration
  • Set SOCKS Host as 127.0.0.1 and the port as 8080 (or whatever you set the tunnel port to on PuTTy).
  • Click OK to save

In Chrome Proxy Switchy

  • A setup page should appear as soon as you install the extension, or click the icon in the top right of Chrome and click Options.
  • Name the profile whatever you like. Under Manual Configuration, set the SOCKS host to 127.0.0.1 and the port to 8080 (or whatever you set the tunnel port to in PuTTy. Leave everything else blank.
  • Hit Save, then click the icon again to select your proxy profile.

ec2 vpn 11

Voila! Your browser traffic is now being funneled through your EC2 instance. This will work fine for basic browsing, but some websites might run into problems and apps other than your web browser will still use the direct connection. To create a full-on VPN that reroutes all your internet traffic, read on.

Set up OpenVPN on the server and client

OpenVPN is a free open source tool that will let you run a full-on VPN through your Amazon EC2 instance. That means all your internet traffic goes through it, not just your web browser traffic like the proxy above. Desktop programs such as Steam or Spotify work better with this approach.

ec2 vpn 12

Connect to your EC2 instance using PuTTy according to the instructions above. You should have a command prompt in front of you that says Amazon Linux AMI. Run the following commands (type or copy/paste them and press enter):

sudo yum install -y openvpn
sudo modprobe iptable_nat
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo iptables -t nat -A POSTROUTING -s 10.4.0.1/2 -o eth0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

Just a quick note here. You might have noticed in the screenshot that I incorrectly tried to download and install OpenVPN using the “apt-get” command instead of “yum”. Some other versions of Linux still use apt-get, so if yum doesn’t work for you, try this command instead:

sudo apt-get install -y openvpn

A bunch of text will flash on the command prompt while it installs OpenVPN. The other three commands set up IP forwarding, which is necessary for the VPN to work.

Method #1: Setting up PKI authentication with easy-rsa (recommended)

In the original version of this tutorial, we set up OpenVPN with static encryption and a .ovpn file. While that works, it only allows one device to be connected at a time, and the fact that you only ever use one key means it’s less secure. We now recommend readers use easy-rsa to set up authentication, which is more secure and allows for any number of devices to be simultaneously connected. However, if you want the old version with static encryption, skip to it by clicking here.

May 2018 update: This article has been updated for use with easy-rsa 3.

OpenVPN and easyrsa server setup

Ideally, you would generate all the keys and certificates you need on a separate device from the VPN server for maximum security. This can be quite tedious, however, so we’re just going to generate both client and server credentials on the server, then move the files where we need them from there.

  1. Easy-rsa is not available in the default yum package list, so we’ll need to enable the EPEL repo to install it. Type the following into the PuTTy terminal and hit Enter:
    • sudo yum install easy-rsa -y --enablerepo=epel
  2. Make an easy-rsa directory in your OpenVPN install directory. Copy the files from your easy-rsa installation (latest version is 3.0.3 as of time of writing) to the new directory:
    • sudo mkdir /etc/openvpn/easy-rsa
      cd /etc/openvpn/easy-rsa
      sudo cp -Rv /usr/share/easy-rsa/3.0.3/*
  3. Now we’re ready to set up our certificate authority. Start by initializing a new PKI (public key infrastructure) directory, then build a certificate authority keypair.
    • sudo ./easyrsa init-pki
      sudo ./easyrsa build-ca
  4. Enter a PEM passphrase. This is not required but recommended. If someone gets a hold of your CA somehow, they will not be able to create keys or sign certificates without the password.
  5. You’ll be prompted to enter a common name. Call it whatever you want or just hit Enter to leave it as the default value.
  6. Next, we’ll generate a Diffie-Hellman key, which provides perfect forward secrecy:
    • sudo ./easyrsa gen-dh
  7. This command can take awhile. It will generate a file called dh.pem. Once finished, we move on to the server credentials. For convenience, we won’t password protect these, but you’re certainly welcome to do so if you want even harder security.
    • sudo ./easyrsa gen-req server nopass
  8. Hit Enter to leave the common name as server. Once the key pair is generated, sign the certificate:
    • sudo ./easyrsa sign-req server server
  9. Type yes to confirm and enter your CA password if you set one earlier.
  10. Now we’ll set up the client. Again, we won’t set a password on this but you are welcome to. Note that if you want to configure automated VPN startup, it’s best not to set a password.
    • ./easyrsa gen-req client nopass
  11. Hit Enter to leave the common name as client. Now sign it:
    • sudo ./easyrsa sign-req client client
  12. Type yes to confirm and enter your CA password if you set one.
  13. Next, we’ll generate a TLS key for perfect forward secrecy in OpenVPN, which ensures past session data cannot be decrypted even if an attacker gets hold of our private key.
    • cd /etc/openvpn
      openvpn --genkey --secret pfs.key
  14. We’ve now generated all of the credential files we need. Next, we’ll create an OpenVPN server configuration file. We’ve already got one written up for you below, so all you need to do is copy and paste if you’ve followed along from the beginning. Start by navigating to the OpenVPN directory and creating a new file:
    • cd /etc/openvpn
      sudo nano server.conf
  15. You are now in the nano text editor. Copy and paste the following config, then hit CTRL+O to save, Enter to confirm, and CTRL+X to exit. (Hint: you can paste text from your clipboard into PuTTy just by right-clicking)
    • port 1194
      proto udp
      dev tun
      ca /etc/openvpn/easy-rsa/pki/ca.crt
      cert /etc/openvpn/easy-rsa/pki/issued/server.crt
      key /etc/openvpn/easy-rsa/pki/private/server.key
      dh /etc/openvpn/easy-rsa/pki/dh.pem
      cipher AES-256-CBC
      auth SHA512
      server 10.8.0.0 255.255.255.0
      push "redirect-gateway def1 bypass-dhcp"
      push "dhcp-option DNS 8.8.8.8"
      push "dhcp-option DNS 8.8.4.4"
      ifconfig-pool-persist ipp.txt
      keepalive 10 120
      comp-lzo
      persist-key
      persist-tun
      status openvpn-status.log
      log-append openvpn.log
      verb 3
      tls-server
      tls-auth /etc/openvpn/pfs.key
  16. The server is now configured. We just need to start up OpenVPN. We’ll start it as a service so that even after you close PuTTy, it will continue to run until the server is either shut down or you manually end the service.
    • sudo service openvpn start

Edit: Some readers have pointed out that their VPN servers stop working after a server reboot or maintenance. This happens occasionally with micro tier EC2 instances. To prevent this, we’ll use a command and bash script courtesy of Matt Doyle in the comments section. Start with this command:

sudo chkconfig openvpn on

While you’re still in etc/openvpn, use nano server.sh to create a new text file and paste the following into it:

#!/bin/sh
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo iptables -t nat -A POSTROUTING -s 10.4.0.1/2 -o eth0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

Use CTRL+O to save and CTRL+X to exit.

The command will ensure OpenVPN starts when the server boots, and the script will ensure the necessary routes are set up in iptables to allow OpenVPN traffic.

OpenVPN and easyrsa client setup

Now that the server is configured, we need to set up the client. To do that, we’ll have to move the necessary certificate and key files from our server to our client device. With PuTTy still open and running as root, we first need to change the permissions on these files so that we can access them. We’ll also put them all in one place to make things a bit easier.

  1. To access some of these files, we’ll need to be root user. To do that, type:
    • sudo su
  2. This will make you the root user and grant administrative privileges. Now enter the following commands. The last command lowers the required permissions to access these files. Note that it’s important to change them back when finished.
    • cd /etc/openvpn
      mkdir keys
      cp pfs.key keys
      cp /etc/openvpn/easy-rsa/pki/dh.pem keys
      cp /etc/openvpn/easy-rsa/pki/ca.crt keys
      cp /etc/openvpn/easy-rsa/pki/private/ca.key keys
      cp /etc/openvpn/easy-rsa/pki/private/client.key keys
      cp /etc/openvpn/easy-rsa/pki/issued/client.crt keys
      chmod 777 *
  3. To get the files off of our server and onto our PC, we’ll use a free program called WinSCP. Just use the default installation options. Once that’s done, a window should pop up prompting you to import your server authentication details from PuTTy. Select the one we made above and continue.ec2 vpn 14
  4. Select myvpn (or whatever you named yours) and hit the Edit button. Type in ec2-user under user name. Click on Login.
  5. If this isn’t your first time using WinSCP, you can set the .ppk file you used in PuTTy by clicking Edit and Advanced. Go to SSH > Authentication > Private key file and navigate to your PPK file.
  6. In the host name field on the main page, you can enter either the IP address or domain of your EC2 instance. Be sure to save your settings, then hit Login.easyrsa 6
  7. In the right pane, navigate to the directory containing your key files, in this case /etc/openvpn/keyseasyrsa 7
  8. Highlight the six files you’ll need: client.crt, client.key, ca.crt, dh.pempfs.key, and ca.key (not shown due to article update). Hit the green Download button. It doesn’t really matter where they go on the left pane so long as you don’t need admin privileges to access it. We put the files on our desktop for simplicity’s sake. However, you’ll want to store the ca.key file somewhere safe, such as a USB drive.
  9. The last loose end we need to do tie up is removing the ca.key file from the server. The CA, or certificate authority, is used to sign client certificates, and, if it is ever compromised, you can never trust certificates issued by that CA again. While this isn’t necessary for the VPN to work, we strongly recommend doing it, especially if you didn’t set up a password for the CA. Make sure you’ve all the keys and certificates for every device you want to connect before removing the file. If you want to add more at a later time, you will have to move the ca.key file back onto the server.
  10. Once you have the CA key safely stored somewhere other than the server, go into PuTTy and remove both the original ca.key and the copy we made from the server:
    • sudo rm /etc/openvpn/easy-rsa/pki/private/ca.key
      sudo rm /etc/openvpn/keys/ca.key
  11. Once the files have downloaded, we need to restore their stricter permissions on the server so not just anyone can access them. Back in PuTTy:
    • cd /etc/openvpn/keys
      sudo chmod 600 *
  12. On your PC, cut and paste those five files from wherever you downloaded them into your OpenVPN config folder. In this case that’s C://Program Files//OpenVPN//config.
  13. Lastly, we need to create a client configuration file. Open your favorite plaintext editor (Notepad works fine) by right clicking and selecting Run as administrator and paste the following config, replacing YOUR.EC2.INSTANCE.IP with the IP address of your EC2 instance:
    • client
      dev tun
      proto udp
      remote YOUR.EC2.INSTANCE.IP 1194
      ca ca.crt
      cert client.crt
      key client.key
      tls-version-min 1.2
      tls-cipher TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256
      cipher AES-256-CBC
      auth SHA512
      resolv-retry infinite
      auth-retry none
      nobind
      persist-key
      persist-tun
      ns-cert-type server
      comp-lzo
      verb 3
      tls-client
      tls-auth pfs.key
  14. This is a Windows config file for the OpenVPN GUI, so we’ll save it as client.ovpn. Other OpenVPN clients might use the .conf extension instead. Whatever the case, make sure your text editor doesn’t add the .txt extension after saving. Save it into the same location as your key and certification files: C:\\Program Files\\OpenVPN\\configeasyrsa 8
  15. Now run the OpenVPN GUI in administrator mode by right clicking it and selecting Run as administrator. Right click the icon in your system tray and connect with the client configuration we just set up. A status screen with loads of text will flash across the screen, and then the icon will turn green.

Congratulations! You are now connected to your homemade VPN.

Method #2: Static encryption (easier, but not recommended)

In this method, we’ll create a shared key for authentication. It’s sort of like a file that acts as a password. It’s easier to set up but only allows a single device to be connected to the VPN at any one time, and is less secure than the easy-rsa method above.

  1. In PuTTy Type in the following commands and hit enter:
    • cd /etc/openvpn
      sudo openvpn --genkey --secret ovpn.key
  2. Now we’re going to create a server config file for our VPN. Type the following command to create a blank text file in a very basic text editor inside the terminal:
    • sudo nano openvpn.conf
  3. Type in the following configuration. You can find more options on the OpenVPN website if you want to play around with this later, but make sure you know what you’re doing first.ec2 vpn 13
    • port 1194
      proto tcp-server dev tun1
      ifconfig 10.4.0.1 10.4.0.2
      status server-tcp.log
      verb 3
      secret  ovpn.key 
  4. Now hit CTRL+O (that’s the letter ‘O’ not zero) and hit enter to save the file. Then hit CTRL+X to exit the text editor. Back at the command prompt, it’s time to fire up OpenVPN:
    • sudo service openvpn start
  5. Next we need to get the shared key from the server to your local computer. First we need to change the permissions on that file so we can access it using the following command:
    • sudo chmod 777 ovpn.key
  6. If at any point you accidentally close PuTTy or it just craps out, you can navigate back to your open VPN installation directory after reconnecting using this command:
    • cd /etc/openvpn
  7. To make this as easy as possible, download and install this free application, WinSCP (Mac users will have to find another FTP client. Don’t worry, there are lots of them). Just use the default installation options. Once that’s done, a Window should pop up prompting you to import your server authentication details from PuTTy. Select the one we made above and continue.ec2 vpn 14
  8. Select myvpn (or whatever you named yours) and hit the Edit button. Type in “ec2-user” under user name. Click on Login.ec2 vpn 15
  9. Now you can move files between your EC2 instance server and your local computer. On the right hand panel, navigate up as far as you can, then go to etc/openvpn. Here you’ll find the ovpn.key file that we need. Click and drag it into the folder of your choice, but remember where you put it as we’ll want to move it later.ec2 vpn 16
  10. Now that you have the key, we need to re-apply the old permissions so not just anyone can grab it. Back in your PuTTy terminal, enter:
    • sudo chmod 600 ovpn.key
  11. It’s time to download the OpenVPN client and GUI for your local computer. Go to the OpenVPN downloads page and choose the appropriate version for your operating system. Install it with the default settings.
  12. Launch OpenVPN and it should appear as an icon in your system tray. Open up a file explorer and navigate to where you installed OpenVPN, probably in your Program Files folder. Move the opvn.key file we downloaded from the server to the config folder found here (C:/Program Files/OpenVPN/config … if you used the default installation directory on Windows).
  13. Next, we need to create a config file for the local machine to match the one we made on our server. Open up Notepad and paste the following, replacing the IP address after “remote” with the IP of your EC2 instance (if you’ve forgotten it, find it in your AWS Console under EC2 Instances). Also, double check that the full file path pointing to your key is correct.
    • proto tcp-client
      remote <your EC2 IP here>   
      port 1194   
      dev tun    
      secret "C:\\Program Files\\OpenVPN\\config\\ovpn.key"   
      redirect-gateway def1    
      ifconfig 10.4.0.2 10.4.0.1
  14. Save it as myconfig.ovpn (make sure your text editor doesn’t append it as myconfig.ovpn.txt by mistake) in the config folder of your OpenVPN installation, the same place as your opvn.key file.ec2 vpn 17
  15. Right click on the OpenVPN icon in your system tray and click Exit to quit. Now start it up again–either from the desktop shortcut or from the Program Files folder–but this time use right click and hit “Run as administrator”. If you don’t run OpenVPN as administrator on Windows, it probably won’t work.ec2 vpn 18
  16. Right click the system tray icon and click Connect. The OpenVPN GUI should pop up showing you the connection status. Assuming it worked, the system tray icon will turn green. Go to Google and type in “What’s my IP?”, and it should return the IP address of your Amazon EC2 Instance.ec2 vpn 19

 

Congratulations, you just made your own VPN!

Additional notes

If you want to protect your VPN from deep packet inspection, a technique used by censorship regimes in places like China and Syria to block OpenVPN connections, check out our tutorial on setting up Obfsproxy. Note this tutorial was written as a sort of sequel to the older Method #2 in this article, so if you used easy-rsa, it will require some additional configuration.

Remember to keep your bandwidth within Amazon’s free tier limits. The easiest way to do this is to right click on your instance in the AWS Console and click on the “Add/Edit Alarms” link. You can set your server to stop or even terminate after a few hours of inactivity. The free tier allows for 750 hours per month (which covers the whole month), so you shouldn’t need to do this. Those users past their initial free year of service or doing more with their server, however, can prevent unnecessary charges for unused server time.

Somewhere in this tutorial, something will probably go wrong for you. If you really want a VPN but aren’t willing to do your fair share of troubleshooting, it’s probably best to opt for a paid VPN service. They also allow you to channel your internet traffic through multiple geographic locations, whereas an EC2 instance is limited to just one. Check out our VPN reviews here!

Hardcoding DNS servers into your VPN

If you need to set specific DNS servers to use with your VPN, there are a couple of options.

To “push” the DNS server to the client, add this line to the server config. This will affect all of the devices that connect to your VPN (quotes included):

push "dhcp-option DNS 45.56.117.118"

Alternatively, you can set the DNS in an individual client config using:

dhcp-option DNS 45.56.117.118

In these examples, I used an OpenNIC public DNS server with anonymous logging located in the US. You can find a OpenNIC server in the country of your choice and filter by features like anonymous logging and DNSCrypt here.

Special thanks to Dctr Watson’s blog, which I leaned on as a resource when writing this article.

Jon Watson (no relation, I think) contributed to this article.