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 you ask?
Easy RSA can be found on the server in
/usr/share/easyrsa/3.0.3 after being installed. This location is important based on where you run the
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.
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).
Change the necessary openvpn configuration files to match the locations of the public and private keys.
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
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
scp down the
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 firstname.lastname@example.org:/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.
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
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.
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
iperf -c 10.200.0.2 from the machine with the IP of
10.200.0.3. This then gave the speed test.1
Everything else I am doing or would like to do.
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.
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.