AWS Client VPN Setup Guide with Mutual Authentication

Introduction

Securely connecting remote users or services to your private AWS resources is a critical task for any cloud infrastructure. AWS Client VPN offers a managed, scalable solution to bridge this gap, but ensuring that only authorized clients can connect is paramount. This guide will walk you through setting up a robust and secure VPN using one of the strongest authentication methods available: mutual authentication (mTLS).

Unlike simpler authentication schemes, mutual authentication requires both the server (the AWS VPN endpoint) and the client (your remote machine) to cryptographically prove their identities to each other using digital certificates. This creates a zero-trust security posture where trust is never assumed, ensuring that only devices possessing a valid, unrevoked certificate can even initiate a connection. It eliminates the risks of compromised passwords and provides granular, certificate-based control over access.

In this step-by-step guide, we will cover the entire process, from generating your own Certificate Authority (CA) to connecting a Linux client. We will:

  1. Use Easy-RSA on a secure local machine to create the necessary certificates.
  2. Import the server certificate into AWS Certificate Manager (ACM).
  3. Configure the Client VPN endpoint, including network associations, routes, and authorization rules.
  4. Set up an OpenVPN client on a Linux VPS to establish the secure tunnel.

By the end, you will have a fully functional and secure VPN, allowing your remote systems to privately access resources within your VPC without exposing them to the public internet. Let’s get started.

Prerequisites

Security Notes:

Step 1: Generate Certificates Locally

Use Easy-RSA to create a CA, server cert, and client cert. This is done on your admin machine.

  1. Clone and set up Easy-RSA:
    git clone https://github.com/OpenVPN/easy-rsa.git
    cd easy-rsa/easyrsa3
    
  2. Initialize PKI and build CA (add a passphrase in production with ./easyrsa build-ca):
    ./easyrsa init-pki
    ./easyrsa build-ca nopass
    
  3. Generate server certificate (include SAN for ‘server’):
    ./easyrsa --subject-alt-name=DNS:server build-server-full server nopass
    
  4. Generate client certificate for your VPS (repeat for multiple clients):
    ./easyrsa build-client-full vps1 nopass
    

Output files:

Securely back up the CA key—it’s needed for future certs or revocations.

Step 2: Import Server Certificate to ACM

Import only the server cert and CA chain to ACM in the same region as your Client VPN endpoint. The client cert stays local.

Option A: AWS Console

  1. Go to AWS Console > Certificate Manager > Import a certificate.
  2. Paste:
  3. Import and note the ARN.

From the directory with the files:

aws acm import-certificate --certificate fileb://server.crt --private-key fileb://server.key --certificate-chain fileb://ca.crt

Copy the returned ARN.

Optional: If using separate CAs or for explicit client auth, import the client cert similarly and note its ARN. For shared CA, reuse the server ARN for client auth.

Step 3: Create the Client VPN Endpoint

  1. Go to AWS Console > VPC > Client VPN endpoints > Create endpoint.
  2. Settings:
  3. Create the endpoint (state: pending-associate).

Associate Subnets and Add Routes/Authorization

  1. Select the endpoint > Target network associations > Associate: Choose your VPC and private subnet(s).
  2. Routes: Add routes to your VPC CIDR (e.g., 172.31.0.0/16 targeting associated subnet). For internet access, add 0.0.0.0/0.
  3. Authorization rules: Add rules for destinations:
  4. Security groups: Attach a SG allowing outbound UDP/TCP 53 (DNS) and other needed traffic. Defaults often allow all egress.

State changes to available after first association.

Step 4: Configure and Connect from Your VPS

Use OpenVPN on Linux (AWS also provides a native client, but OpenVPN is standard).

  1. Install OpenVPN:
    sudo apt update && sudo apt install -y openvpn
    
  2. Download the .ovpn config from AWS Console > Client VPN endpoint > Download client configuration.

  3. Securely copy files to VPS (e.g., via SCP):
  4. Edit client.ovpn to reference files:
    ca /etc/openvpn/client/ca.crt
    cert /etc/openvpn/client/vps1.crt
    key /etc/openvpn/client/vps1.key
    
  5. Start OpenVPN:
    sudo openvpn --config /etc/openvpn/client/client.ovpn --daemon
    
  6. Install as a systemd service for persistence:
    sudo mv /etc/openvpn/client/client.ovpn /etc/openvpn/client.conf
    sudo systemctl enable --now openvpn@client
    sudo systemctl status openvpn@client
    

    (Routes to VPC are automatically pushed; Docker containers on the host use host routing.)

For multiple clients, generate unique certs per VPS/user. This setup ensures secure, private access without public endpoints. Test thoroughly before production.