DevOps Hero Part 3: Add AWS VPN

Terris Linenbach
3 min readMay 11, 2024

In the previous installments of this series, we created the AWS infrastructure for a typical web application using CloudFormation. Then we used GitHub Actions to build and publish a Docker container to ECS.

Next, we will improve the DX by providing VPN access to the VPC so developers can, for example, connect to the RDS Postgres server from their laptops.

See also Getting Started with AWS VPN.

Recommendation: Do not leave VPN connections idle for longer than an hour! AWS VPN is not free.

1. Create and Upload a Certificate

  1. Install aws-cli
  2. Use aws configure sso or however you prefer to authenticate with the aws cli
  3. Replace {aws-account} and {domain} below with any values you prefer
git clone https://github.com/OpenVPN/easy-rsa.git
cd easy-rsa/easyrsa3
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa --san=DNS:{aws-account} build-server-full server nopass
./easyrsa build-client-full {domain} nopass
cd pki
aws acm import-certificate --certificate fileb://issued/server.crt \
--private-key fileb://private/server.key \
--certificate-chain fileb://ca.crt

The above shell commands:

  • Use the easy-rsa utility to create a certificate
  • Upload the server certificate only. The client certificate is not needed.

2. Add a VPN Endpoint via the AWS Console

  • Log in to the AWS console
  • Select a region in the upper right corner, for example: us-east-1
  • Go to VPC
  • Click Client VPN endpoints
  • Click Create client VPN endpoint
  • Name: {Product} VPN
  • Client IPv4 CIDR: 10.0.0.0/16
  • Server certificate ARN: Select the certificate uploaded above
  • Select mutual authentication
  • Client certificate ARN: Select the certificate uploaded above
  • VPC ID: {Product} VPC
  • Security group ids: Select the default security group
  • Session timeout hours: 8
  • Click Create client VPN endpoint
  • Click the bulletpoint next to the newly created client VPN endpoint
  • Click the tab Target network associations
  • Click Associate target network
  • VPC: {Product} VPC
  • Choose a subnet to associate: {Product} Private Subnet (AZ1)
  • Click Associate target network
  • Click the bullet point next to the newly created client VPN endpoint
  • Click the tab Authorization rules
  • Click Add authorization rule
  • Destination network to enable access: 10.0.0.0/16
  • Click Allow access to all users
  • Click Add authorization rule
  • Click the bullet point next to the newly created client VPN endpoint (again)
  • Click the tab Authorization rules (again)
  • Click Add authorization rule
  • Destination network to enable access: 0.0.0.0/0
  • Click Allow access to all users
  • Description: Internet Access
  • Click Add authorization rule
  • Click the bulletpoint next to the newly created client VPN endpoint
  • Click the Route table tab
  • Click Create route
  • Route destination: 0.0.0.0/0
  • Subnet ID: Select the first item besides local
  • Description: Internet Access
  • Click Create route
  • Click the bulletpoint next to the newly created client VPN endpoint
  • Click Download client configuration

3. Create the OVPN Profile

  • Rename the file downloaded in the previous section as {aws-account}.ovpn
  • Open the file in a text editor
  • Append <cert>
  • Append the contents of easy-rsa/easyrsa3/pki/issued/{domain}.crt between and including BEGIN CERTIFICATE and END CERTIFICATE
  • Append </cert>
  • Append <key>
  • Append the contents of easy-rsa/easyrsa3/pki/private/{domain}.key
  • Append </key>
  • For example, the bottom of the file should look like:
<ca>
-----BEGIN CERTIFICATE-----
MIIDQ...
-----END CERTIFICATE-----
</ca>
reneg-sec 0

verify-x509-name {aws-account-name} name

<cert>
-----BEGIN CERTIFICATE-----
MIIDT...
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
MIIEv...
-----END PRIVATE KEY-----
</key>

4. Connect to AWS VPN

  • Install the AWS VPN Client
  • Add a profile using the OVPN file created in the previous section
  • Connect to the VPN profile
  • As a test, use the psql command to connect to the RDS Postgres Database or its Proxy

--

--