January 8, 2019

AWS Client VPN Mutual Authentication

A few people asked me about Mutual Authentication, and I also wanted to see if I could get Internet access working.

I’m starting with a VPC that has 3 subnets in 3 AZs (for 9 subnets in total). 3 of the subnets are marked “public” and have the default route via the IGW. In these 3 public subnets lives 3 NAT Gateways. The other 6 subnets (named app and db) have default routes via the NAT Gateways.

Create the client and server certificates

Similar to what we did before, but I’m going to create 2 users and use a different name for the server certificate:

cd /tmp
git clone https://github.com/OpenVPN/easy-rsa.git
cd easy-rsa/easyrsa3
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa build-server-full awesome-vpn nopass
./easyrsa build-client-full gergnz.gmail.com nopass
./easyrsa build-client-full gregc nopass
rm -rf /tmp/foo
mkdir -p /tmp/foo
cp pki/ca.crt /tmp/foo/
cp pki/issued/awesome-vpn.crt /tmp/foo/
cp pki/private/awesome-vpn.key /tmp/foo/
cp pki/issued/gergnz.gmail.com.crt /tmp/foo
cp pki/private/gergnz.gmail.com.key /tmp/foo/
cp pki/issued/gregc.crt /tmp/foo
cp pki/private/gregc.key /tmp/foo/
cd /tmp/foo/
aws acm import-certificate --certificate file://awesome-vpn.crt --private-key file://awesome-vpn.key --certificate-chain file://ca.crt --region us-west-2

Note, unlike the instructions supplied in the AWS Documentation, I do NOT upload the client certificates and keys. There is technically no need.

Create the Client VPN Endpoint

This time only select mutual authentication, and leave Active Directory authentication unticked.

The same certificate that you use for the Server certificate ARN can be used for the Client certificate ARN.

VPN Client Associations

Now to make the VPN able to access the Internet you need to do the following:

  • Associate the Client VPN with each of the app Subnets. (do not use the public subnets)
  • Add a route to each subnet in the Client VPN Route table
  • Add as an ingress authorization

Your Client VPN configuration should look somehting like this:

Client VPN Summary Client VPN Associations Client VPN Authorizations Client VPN Route Table

Client Side setup

If you remember ealier I created 2 users:

  • gergnz.gmail.com
  • gregc

As before down the configuration file and make 2 copies of it, one called gergnz.ovpn and one called gregc.ovpn.

As per the name suggests edit the files and put their respective certs and keys at the buttom:


cert /gregc.crt
key /gregc.key


cert /gergnz.gmail.com.crt
key /gergnz.gmail.com.key

Also change the remote value prefixing an asterix dot as follows:

server *.cvpn-endpoint-...

Now you can import these into your favourite client. I used Viscosity this time.

Both connected and worked able to route to the Internet.

Certificate (User) Revocation

You can also generate CRL (Certificate Revocation Lists) and import them into the Client VPN.

The documentation is here.

Assuming you haven’t deleted your easyrsa git clone:

cd /tmp/easy-rsa/easyrsa3
./easyrsa revoke gregc
./easyrsa gen-crl
aws ec2 import-client-vpn-client-certificate-revocation-list --certificate-revocation-list file:///tmp/easy-rsa/easyrsa3/pki/crl.pem --client-vpn-endpoint-id cvpn-endpoint-005c551e4b00a6d14 --region us-west-2

Now the user gregc is unable to connect.

Important final information

Keep your /tmp/easyrsa3/pki/ directory somewhere safe!

© Greg Cockburn

Powered by Hugo & Kiss.