/openvpn-cfn

Roll your own Amazon Linux 2 OpenVPN with AWS CloudFormation (w/ Dynamically Discovered Latest AMI Id via Parameter Store)

MIT LicenseMIT

"OpenVPN"

Deploy OpenVPN to AWS via CloudFormation and Amazon Linux 2

This is a new and improved version of a CFN template blogged about by Linux Academy.

To read a detailed blog post on how it was setup, checkout: Deploy an OpenVPN Instance to AWS with CloudFormation

NOTE: This worked much more like a personal learning tool, and I'd rather recommend something like AlgoVPN when it comes to deploying and managing your own VPN in AWS due to the community and expertise around the project.

If you want to see the original OpenVPN CFN template that I worked on fixing/expanding, taking note that it is out-dated and no longer functional, you can take a look at it here:

The following blog articles walkthrough how the base CFN template was initially created, along with full descriptions as to why each resource is used:

Updates in This New CFN Template

  • Updated for Amazon Linux 2
  • Added parameter for specifying OpenVPN version. Default: version 2.4.7 (latest available, tested version from EPEL as of November, 2019)
  • Updated to export single OVPN instead of .zip of client configuration
  • Replaced AMI Mappings sections with LatestAmiId parameter dynamically referencing AWS Systems Manager Parameter Store for latest Amazon Linux 2 AMI ID in relative region (by default)
  • CustomResource AWS Lambda migrated over to python3.7 runtime due to nodejs6.10 no longer being supported and the nodejs8.10 runtime approaching EOL: AWS Lambda: Node.js v8.10 Runtime Approaching End of Life (EOL)
  • Updated for Easy-RSA v3.x
  • Parameterized OpenVPN port and protocol
  • Parameterized EASYRSA_ALGO (Default: rsa, but can also be ec) and EASYRSA_REQ_CN (Default: ChangeMe) Easy-RSA vars
  • Updated OpenVPN client and server config values
    • Replaced ns-cert-type server with remote-cert-tls server in client config
      • Due to ns-cert-type slated for full deprecation by v2.5.x of OpenVPN, and due to mobile clients (Android / iOS) currently erroring out if present
    • Removed comp-lzo from server and client configs

Step-by-Step Deployment

This can be done via the GUI by uploading the cfn-openvpn.yaml while creating a stack, in the AWS Console, or it can be done via the CLI. If going through the GUI, an SSH key pair needs to be made first via the EC2 service.

Otherwise, keep following for a CLI approach to the deployment that sets up a Python virtualenv, creates an SSH key pair, and deploys the CFN stack.

Prerequisites

  • Python 3 (tested on Python 3.6 and 3.7)

awscli Setup

Checkout awscli if needed. An optional approach to configuring awscli can be seen below.

awscli Setup: Python VirtualEnv
python3 -m venv venv
source venv/bin/activate
pip install -U pip setuptools
pip install awscli
awscli Setup: Configure AWS CLI Profile
# Target aws profile to create
AWS_VPN_PROFILE='testprofile'

# Configure Access Keys
aws configure --profile $AWS_VPN_PROFILE

Create EC2 SSH Key Pair

# Target aws profile to use
AWS_VPN_PROFILE='testprofile'

# Generate SSH Key Pair; set file permissions (Linux/MacOS)
SSHKEYPAIR='openvpn'
aws ec2 create-key-pair \
  --key-name $SSHKEYPAIR \
  --output text \
  --profile $AWS_VPN_PROFILE \
  --query 'KeyMaterial' > $SSHKEYPAIR.pem
chmod 400 $SSHKEYPAIR.pem

Create OpenVPN via CFN

aws cloudformation deploy \
    --template-file cfn-openvpn.yaml \
    --stack-name openvpn-personal \
    --profile $AWS_VPN_PROFILE \
    --parameter-overrides SSHKeyName=$SSHKEYPAIR \
    --capabilities  CAPABILITY_IAM

[Optional] Access OpenVPN EC2 Instance

OPENVPNIP=`aws cloudformation describe-stacks \
  --stack-name openvpn-personal \
  --profile $AWS_VPN_PROFILE \
  --output text \
    | grep OpenVPNEIP \
    | sed s/^.*EIP// \
    | tr -d '[:blank:]'`
ssh -i $SSHKEYPAIR.pem ec2-user@$OPENVPNIP