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

Setting up AWS

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.

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.

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.

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.

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

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.

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.

  • 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
  • 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/*
  • 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
  • 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.
  • 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.
  • Next, we’ll generate a Diffie-Hellman key, which provides perfect forward secrecy:
  • sudo ./easyrsa gen-dh
  • 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
  • Hit Enter to leave the common name as server. Once the key pair is generated, sign the certificate:
  • sudo ./easyrsa sign-req server server
  • Type yes to confirm and enter your CA password if you set one earlier.
  • 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
  • Hit Enter to leave the common name as client. Now sign it:
  • sudo ./easyrsa sign-req client client
  • Type yes to confirm and enter your CA password if you set one.
  • 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
  • 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
  • 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
  • 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 yum install easy-rsa -y –enablerepo=epel

sudo yum install easy-rsa -y –enablerepo=epel

  • sudo mkdir /etc/openvpn/easy-rsa
  • cd /etc/openvpn/easy-rsa
  • sudo cp -Rv /usr/share/easy-rsa/3.0.3/*

sudo mkdir /etc/openvpn/easy-rsa cd /etc/openvpn/easy-rsa sudo cp -Rv /usr/share/easy-rsa/3.0.3/*

  • sudo ./easyrsa init-pki
  • sudo ./easyrsa build-ca

sudo ./easyrsa init-pki sudo ./easyrsa build-ca

  • sudo ./easyrsa gen-dh

sudo ./easyrsa gen-dh

  • sudo ./easyrsa gen-req server nopass

sudo ./easyrsa gen-req server nopass

  • sudo ./easyrsa sign-req server server

sudo ./easyrsa sign-req server server

  • ./easyrsa gen-req client nopass

./easyrsa gen-req client nopass

  • sudo ./easyrsa sign-req client client

sudo ./easyrsa sign-req client client

  • cd /etc/openvpn
  • openvpn –genkey –secret pfs.key

cd /etc/openvpn openvpn –genkey –secret pfs.key

  • cd /etc/openvpn
  • sudo nano server.conf

cd /etc/openvpn sudo nano server.conf

  • 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

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

  • sudo service openvpn start

sudo service openvpn start

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.

  • To access some of these files, we’ll need to be root user. To do that, type:
  • sudo su
  • 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 *
  • 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.
  • Select myvpn (or whatever you named yours) and hit the Edit button. Type in ec2-user under user name. Click on Login.
  • 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.
  • 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.
  • In the right pane, navigate to the directory containing your key files, in this case /etc/openvpn/keys
  • Highlight the six files you’ll need: client.crt, client.key, ca.crt, dh.pem, pfs.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.
  • 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.
  • 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
  • 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 *
  • 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.
  • 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
  • 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\config
  • 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.

  • sudo su

sudo su

  • 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 *

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 *

  • sudo rm /etc/openvpn/easy-rsa/pki/private/ca.key
  • sudo rm /etc/openvpn/keys/ca.key

sudo rm /etc/openvpn/easy-rsa/pki/private/ca.key sudo rm /etc/openvpn/keys/ca.key

  • cd /etc/openvpn/keys
  • sudo chmod 600 *

cd /etc/openvpn/keys sudo chmod 600 *

  • 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

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

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.

 

  • cd /etc/openvpn
  • sudo openvpn –genkey –secret ovpn.key

cd /etc/openvpn sudo openvpn –genkey –secret ovpn.key

  • sudo nano openvpn.conf

sudo nano openvpn.conf

  • 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

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

  • sudo chmod 777 ovpn.key

sudo chmod 777 ovpn.key

  • cd /etc/openvpn

cd /etc/openvpn

  • sudo chmod 600 ovpn.key

sudo chmod 600 ovpn.key

  • proto tcp-client
  • remote
  • port 1194
  • dev tun
  • secret “C:\Program Files\OpenVPN\config\ovpn.key”
  • redirect-gateway def1
  • ifconfig 10.4.0.2 10.4.0.1

proto tcp-client remote port 1194 dev tun secret “C:\Program Files\OpenVPN\config\ovpn.key” redirect-gateway def1 ifconfig 10.4.0.2 10.4.0.1

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.

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.