I wanted an OpenVPN server so I could create a public-private network where I could access my local development machine without having to fully expose it to the wide open internet and mess with my home network connection. This was the EC2 VPN solution I came up with.
When I say public-private network, I mean a private network only accessable by me, but accessable from anywhere.
OpenVPN Server Setup Instructions
SSH into any cloud or publically accessable server with OpenVPN and EasyRSA3 installed, and change to the root user of the machine using sudo -i
.Why sudo -i
you ask?
Easy RSA can be found on the server in
/etc/openvpn/easy-rsa/3.0.3
or /usr/share/easyrsa/3.0.3
after being installed. This location is important based on where you run the ./easyrsa
commands.
For easyrsa3, commands start with ./easyrsa
. I was looking at easyrsa2 documentation and easyrsa2 had a directory with all the commands which threw me off. EasyRSA3 commands start with the ./easyrsa
and the arguments are subcommands and options.
For this easy and simple setup, I didn’t configure a dedicated CA server, so I used the OpenVPN Server tools provided for setting up a CA and public key infrastructure (pki). These were the commands I used for an insecure test ca & vpn server. Please note this is in no way a production server and was only used in a demo.
# Creates a pki folder in the current directory
/easyrsa init-pki
# Builds the Certificate Authority
./easyrsa build-ca nopass
# Generates a Diffie-Helllman Key
./easyrsa gen-dh
# Generates the Server Keys
./easyrsa build-server-full ovpntest0 nopass
# Generates a client's keys
./easyrsa build-client-full client1 nopass
# Moving all the files to their locations for easier access for the OpenVPN Server
cp pki/ca.crt /etc/openvpn/ca.crt
cp pki/dh.pem /etc/openvpn/dh.pem
cp pki/issued/vpn-server.crt /etc/openvpn/server.crt
cp pki/private/vpn-server.key /etc/openvpn/server.key
cp pki/ta.key /etc/openvpn/ta.key
cp pki/crl.pem /etc/openvpn/crl.pem
Of note in this set of commands, I did not generate a revokation list and the server is pretty barebones.
The dh.pem
and ca.crt
files end up in the root of the ./pki
directory, and the public issued *.crt
files are in the ./pki/issued
folder and the private keys *.key
are in the ./pki/private
folder. When these files are generated, usually an output location is provided (I just made sure the keys were created, I didn’t look where they went).
Configuration Files
Change the necessary openvpn configuration files to match the locations of the public and private keys.
Server Configuration
example-server-config.conf
proto tcp
port 1194
dev tun
server 10.200.0.0 255.255.255.0
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh.pem
persist-key
persist-tun
keepalive 10 60
push "route 10.198.0.0 255.255.0.0"
topology subnet
user nobody
group nobody
sudo openvpn --config example-client-config.conf
will get you up and running from the server machine.
For security reasons, the OpenVPN process switches to user and group nobody after running the root commands and finishing them. Even if a remote attacker was able to compromise the OpenVPN process, the security breach would be contained to the user nobody instead of the user root.1
Running export OVPN_ADDR=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
will get you the public IP of the cloud instance, and this ip will be used in the client configuration. Note what is being run is native to most cloud platforms and is a tool that will provide information about the machine. In this case it is grabbing the public ipv4, but I am only putting the IP for the blog post to prevent abuse and spam of the IP address. In my prod server I replaced the script with the hardcoded ipv4 address.
I also decided tcp because I would be SSH’ing into machines and needed the extra ACK packet.. If this VPN were for streaming or torrenting, I would have used UDP. Google and the mailing list do a decent job explaining the differences between tcp and udp…, but I also plan to read this book on TCP
With systemd on the aws-linux, I ran sudo mv ~/example-server-config.conf /etc/openvpn/server.conf
and then ran sudo systemctl start openvpn@server
moving the config to the openvpn folder, and then OpenVPN ran as it’s own systemd service with the server.conf
configurations. I made sure it was running with sudo systemctl status openvpn@server
, and this checked everything was up.1
Client Configuration
scp
down the ca.crt
, client1.crt
and client1.key
files into a location where you can easily find them. I used mkdir -p ~/Documents/ovpn/test
and sercure copied everything down to that folder. The SCP command looked like:
scp -i ~/loc/ssh/key.pem nobody@192.168.70.15:/home/ec2-user/client1.crt ~/Documents/ovpn/test
Obviously I have changed some of the values, but this was the gist of the command.
Enable Client Forwarding with sudo sysctl -w net.inet.ip.forwarding=1
on mac and sudo systctl -w net.ipv4.ip_forward=1
on ubuntu to allow them to connect to one another. It is unreccommended to forward ports except from a router as port forwarding essentially turns a computer into a router.
example-client-config.conf
client
proto tcp
remote $OVPN_ADDR
port 1194
dev tun
nobind
ca /home/jack/Documents/ovpn/test/ca.crt
cert /home/jack/Documents/ovpn/test/client1.crt
key /home/jack/Documents/ovpn/test/client1.key
Note $OVPN_ADDR in the remote
line won’t read from the environment so you will need to hardcode the IP address in to the client config file. You will also need to change the ca
, cert
and key
lines to point at the correct files.
sudo openvpn --config example-client-config.conf
will get you up and running from a client machine.
Testing Speed
Using iperf I was able to test the network speed over the VPN. For this I installed iperf on my mac with brew install iperf
and on ubuntu with sudo apt install iperf
.
I then ran the server with iperf -s
on the machine with the ip of 10.200.0.2
and iperf -c 10.200.0.2
from the machine with the IP of 10.200.0.3
. This then gave the speed test.1
More
Everything else I am doing or would like to do.
Networking
In the future I would like to get a Site-to-Site configuration set up, as well as routing from something like pfsense to the internal VPN network for services.
I know pfsense offers an openvpn extension and I looked into this as the first solution, but AWS does some weird NAT to the internal network VPC address and I was looking for more a basic Proof of Concept with this setup, not a behemoth ultracuztomized router-VPN setup. I will look into something like this when I move to a hybrid cloud.
Uptime
I want the non-vpn “server” to automatically connect to the vpn server and I also need to daemonize the vpn application.. This will amount to better availability.