Setting up VPN with AWS— 2/2

Alexandros Maragakis
My Local Farmer Engineering
9 min readMay 19, 2021

A Work from Home solution

Welcome back to our engineering blog. This post is the second in a series on how we enabled our employees to work from home using AWS technologies. In our previous post, we discussed the situation that we faced at the beginning of the pandemic, and the technological challenges that we encountered as a result of the work-from-home legislation. Here we will provide an overview of our solution on AWS, including console setup steps, and AWS Cloud Development Kit (CDK) deployment.

Disclaimer
I Love My Local Farmer is a fictional company inspired by customer interactions with AWS Solutions Architects. Any stories told in this blog are not related to a specific customer. Similarities with any real companies, people, or situations are purely coincidental. Stories in this blog represent the views of the authors and are not endorsed by AWS.

Recap

Our leased Paris data centre hosts our back office applications, such as Jira, as well as our production application’s backend stack. Prior to the pandemic, we accessed our back office applications through connections between the data centre and our offices. Our largest office in Paris benefitted from a direct connection to the data centre via a lease line, whilst our smaller offices communicated over a VPN connection.

Our VPN solution did not have the capacity to handle the incoming connections from all of the individual company laptops when our employees started working from home. After some research, we decided to implement a VPN solution on AWS using AWS Client VPN and AWS Site-to-Site VPN.

Our original back-office communication setup

AWS Infrastructure Overview

This was our first step in our cloud migration journey. It was with the sole intention of allowing our employees to communicate with our existing back office infrastructure through individual VPN connections. As such, we kept our back office infrastructure in our Paris data centre, and reinvented our VPN solution to use scalable AWS-managed services to handle the increased communication burden.

In summary, our AWS on-cloud infrastructure is hosted within an AWS Virtual Private Cloud (VPC), and consists of an Active Directory (AD) Connector, AWS Client VPN, and various other VPC components, such as a VPN Gateway. Between the AWS VPC and the Paris data centre is an AWS Site-to-Site VPN connection.

Our AWS VPN back-office communication solution

The first major component between the remote employee and our back office is AWS Client VPN. AWS Client VPN accepts traffic from an OpenVPN-based VPN client. We use it to forward communications into an AWS VPC, and onto on-premise resources. It is a scalable, managed service, meaning that it can dynamically increase its capacity on demand, and runs on server infrastructure that is maintained by AWS. It also provides a self-service portal that enables VPN users to onboard themselves.

Within our VPC we have an AD Connector. We use this to allow employees to connect to the VPN solution using their corporate credentials, and is connected to our data centre’s Active Directory for authentication.

Between our AWS VPC and our Paris data centre is an AWS Site-to-Site VPN, a VPN that facilitates secured communications between AWS and on-premises environments. In our solution, the Site-to-Site VPN has endpoints at our VPC’s VPN Gateway and our data centre’s VPN device.

Connecting our Data Centre to an AWS VPC

Site-to-Site VPN is an AWS VPN solution that can be used to connect an on-premise environment to an AWS VPC. We decided to provision the Site-to-Site VPN as Infrastructure as Code (IaC). Our IaC framework of choice is the AWS Cloud Development Kit (CDK); it allows you to choose a preferred programming language — in our case, Java — to define your cloud resources.

The CDK deployment of Site-to-Site VPN is quite simple thanks to the existence of CDK constructs; classes in our CDK code, mostly developed by AWS’ CDK team, that will deploy a host of relevant, co-operating services with a few lines of code. In our Site-to-Site VPN scenario, we are able to setup the vast majority of our working solution using the VPC construct. This will create an AWS VPC that is connected to our on-premise environment by a VPN connection.

The VPC construct requires that we provide two pieces of information about our existing environment: the customer gateway device IP address, and our on-premise CIDR Range. ‘Customer gateway device’ is how AWS refers to our existing on-premise VPN device — in our case a VPN device in our Paris data centre. The device has an IP address that we specify here. The on-premise CIDR range is the range of private IP addresses used within the on-premise environment. We also need to provide the construct with a CIDR range for the VPC that will be newly created as part of the deployment.

Extract from our CDK code for creating our AWS VPC

The final step is to set up our on-premise device, and this is done outside of CDK. Luckily AWS provide instructions for setting up customer VPN devices. To get the configuration instructions, we navigated to the VPN gateway page of the AWS VPC console (found in the AWS Management Console). We find our VPN connection from the Site-to-Site VPN page, and choose to download the file, which requires that we provide some information about the model and software of our on-premise device. We followed the instructions in the file, and then applied the additional step of adding a static route in our VPN device for our AWS VPC.

The CDK code can be found in our GitHub repository. It is also possible to perform this deployment manually using the console. A step-by-step guide is presented in the documentation.

Connecting our Employees to our AWS VPC

With our VPN connection successfully set up between our AWS VPC and our on-premise environment, we needed to set up the connection between our employees’ remote laptops and our AWS VPC. In our case, this would require both an AWS Client VPN and an AD Connector. The Client VPN manages the VPN connection between the employee and the VPC, whilst the AD Connector allows Active Directory requests to be passed between the remote computer, the VPC, and the on-premise Active Directory.

Client VPN authenticates client-server connections by means of certificates. It is necessary that we upload a server certificate to AWS Certificate Manager (ACM) prior to setting up Client VPN itself. We can create a certificate using OpenVPN’s easy-rsa, and upload it to ACM using the CLI. In our case, we only uploaded a server certificate, not any client certificates, as we used a common Certificate Authority. The specific terminal commands for this process are outlined in the ‘Mutual Authentication’ section of the documentation.

With a server certificate uploaded, we moved on to the development of a CDK app to deploy the Client VPN and AD Connector. This CDK app relies on the Site-to-Site VPN that we created previously, which is hence a prerequisite. The app, when deployed, provisions an AD Connector within the VPC that we already created with the Site-to-Site VPN, and an AWS Client VPN endpoint that uses Active Directory for authentication.

AD Connector Custom Resource
The CDK code that we used to create the Client VPC and AD Connector stack is more complex than what was used in the Site-to-Site VPN app. This is partly because we had to make use of CDK Custom Resources to create the AD Connector, which itself does not have a pre-created CDK construct.

A custom resource could be thought of as a CDK construct that is defined by the user. Custom resources provision AWS infrastructure by making AWS API calls from user-defined AWS Lambda functions. For our AD Connector custom resource we specify both an On Event and an Is Complete Lambda handler. The On Event handler creates resources, whilst the Is Complete handler checks if the asynchronous resource creation processes have completed.

Execution diagram for our AD Connector custom resource

The On Event handler requires access to the Active Directory admin password, which is best provided by AWS Secrets Manager. For simplicity, this secret is manually stored in Secrets Manager through the AWS Management Console. Storing the password separately from the CDK app allows us to easily rotate the password without interrupting the other services deployed as part of the stack. With the admin password retrieved, the On Event handler goes on to attempt to connect to the on-premise Active Directory using the AWS Directory Service.

The Is Complete handler requests a directory listing from the Directory Service, and returns as completed if there exists a directory that’s stage is Active — i.e. that it is an AD directory. The Custom Resource construct will call the Is Complete handler on a loop under-the-hood until the creation is complete or a problem occurs.

Client VPN
The creation of the AWS Client VPN service itself is more straightforward thanks to methods that exist on the CDK VPC construct. We want to add a Client VPN to the VPC that was created in our Site-to-Site VPN app, but this VPC was created in a separate codebase. We resolve this by passing the ID of the VPC in to our Client VPN app as an input argument. We can then initialise a VPC object using a static lookup on the VPC ID. The Client VPN can then be created within the VPC using the addClientVpnEndpoint method on the VPC object, setting the userBaseAuthentication appropriately such that it is associated with our AD Connector.

Extract from our CDK code for creating our Client VPN

Our first attempt at the deployment had some problems connecting to our on-premise environment through the Client VPN; we were only able to reach the AWS VPC. Troubleshooting networking and connectivity issues can be difficult when relying solely on the tables presented in the AWS console. Fortunately, AWS provides the VPC Reachability Analyzer, a tool that aims to diagnose the cause of failed connections within and between VPCs. We ran the analyzer on our setup to successfully validate our security groups and route tables. Unfortunately, it was unable to give much insight into the correctness of our Client VPN setup, since Client VPN is not yet integrated into the analyzer checks.

After some research, we realised that Client VPN, only allows you to access the VPC in which it was created, by default. We thus added a line of code in our CDK app to add an ‘onPremise’ authorization rule, with the CIDR block set to our on-premise CIDR.

Extract from our CDK code for adding an on-premise authorization rule to our Client VPN

The CDK code can be found in our GitHub repository. For more information on how to create an AWS Client VPN using CDK, check out its CDK documentation.

Usage

With all of the AWS infrastructure in place, it is time to connect our employees to our on-premise environment via our AWS VPC. This part requires that each company laptop has a configured, OpenVPN-based VPN client installed on them. AWS Client VPN provides a self-service portal that allows you to download the latest version of the AWS Client VPN app, AWS’ own OpenVPN client, and the configuration file required to connect it to your Client VPN. Employees can access the portal using their AD credentials.

To clarify, AWS Client VPN is the AWS service endpoint that receives traffic from remote VPN clients, and the AWS Client VPN app is the software application downloaded on to employee laptops that they use to make connections with the AWS Client VPN service.

The Client VPN Self-Service portal

With the AWS Client VPN app configured, the user can access AWS VPC resources, and hence on-premise resources, by signing in to the VPN using their AD credentials.

This concludes our series on Working From Home, and how we set up VPN communications between our remote employees and our data centre via an AWS environment. We hope you enjoyed it!

Useful Links

--

--