Accessing isolated network estate on AWS: Part 4 - AWS Client VPN
No servers, no containers, full network access from localhost inside VPC
As a closing to this series of post related to accessing isolated networks inside AWS, I will cover the approach of using the AWS Client VPN. This is a managed client-based VPN service that enables you to securely access your AWS resources and your on-premises network via a managed VPN link.
The overall advantage of this solution is that it greatly simplifies the network and resources required to achieve the audited and authenticated access to the system.
How it works
This solution leverages a mutual authentication OpenVPN based link using certificates that you provide along with the possibility to setup a self-service certificate vending dashboard for users if you have Active Directory/SAML based auth.
Use Cases
Advantages
Consistent Access: Utilizes a consistent method of access that is public and widely used, regardless of the underlying service. This is in contrast to services like ECS Exec and Instance Connect, which are specific to certain AWS services.
Reduced overhead: The VPN endpoint is AWS managed and only some ENI are placed within your target subnets, removing any management need.
Self-Service Certificates: A management portal can be configured to enable self-service for users to obtain the connection credentials, further removing operational steps.
Scalable: Scales based on number of users and traffic thus reducing situations where corporate VPN is slow or fails due to load.
Security: This uses OpenVPN, which is an industry-standard VPN protocol, that provides a high level of security. EC2 instances in comparison use SSH keys, which can be vulnerable if keys are not managed properly, although Instance Connect mitigates this issue.
Centralized Control: Centrally managed access to your AWS resources from a single access endpoint. This is of similar vein to the ECS Exec and Instance Connect, where you can limit the user via IAM by granting/blocking the core permission for the action. It also allows live monitoring and termination of active connections.
No VPC endpoints: Allows the creation of an isolated network with no Internet Gateway, without requiring VPC endpoints.
Disadvantages
Cost: Client VPN can be more expensive than other solutions, especially for large numbers of users or heavy data usage. This is ideal if you are mainly looking for access for a certain number of users on an ad-hoc basis such as developers / QA accessing the environment for investigations or testing.
Complexity: Setting up Client VPN can be complex, especially if you're not familiar with VPNs or networking. But hopefully this will cover the basics of it ;)
Limited Protocol Support: Client VPN only supports the OpenVPN protocol. If you need to use a different protocol, you'll need to look at other solutions.
Example
As the VPN does not require any further resources to be functional and is completely self-contained with just the VPC and VPN constructs, these are the only ones showcased below. As once the VPN connection is established, all resources contained within the private network that have a reachable route defined in the route tables of the subnets where the VPN endpoints are placed, are reachable from the local PC.
Step 1: Initialize the CDK App
First, we need to initialize a new CDK app in your preferred language, which for me is currently TypeScript. Let’s open up a terminal and run the following commands to get started:
mkdir -p accessing-isolated-network/bastion-vpn
cd accessing-isolated-network-access/bastion-vpn
npx cdk init app --language=typescript
This will create a new CDK app in TypeScript with the following structure
Step 2: Define the VPC Stack
Next, we define the VPC stack where the Client VPN Elastic Network Interface will be deployed.
Open up the lib
folder and create a new file called vpc-stack.ts
. We will only need private isolated subnets.
Step 3: Define the VPN Stack
We now create the VPN setup for the service. Open up the lib
folder and create a new file called vpn-stack.ts
.
As we are taking the mutual authentication path, we need to generate a base pair of certificates for the server and the client. This process is not as hands-off as the Active Directory / federated path with self-service portal, but it achieves the same target goal. The steps to generate the certificate pair is eloquently described here. Once you have completed the linked steps, you will have a pair of certificates in ACM that we need to pass the id’s of here under `vpcCert
`.
They can be found in ACM here, assuming you followed the pattern of vpn.<domain>.com for server certificate and <user>.vpn.<domain>.com for client certificate.
Step 4: Define the App Stack
Deploying this stack is done via the main of:
Step 5: Deploy app
The cleanest way to pass the newly created certificates is via the CDK context construct directly from the terminal.
> npx cdk deploy --profile=<profile> --all -c serverCert=<cert_id> -c clientCert=<cert_id>
This will take a few minutes as the deployment of the VPN endpoints and the authorizations are not instantaneous.
Once deployment is complete, you need to download the client configuration for the VPN application, which can be found in AWS Console > VPC > Client VPN endpoints.
Once that is downloaded, and you have installed the VPN client, you can open the application,
File > Manage Profiles > Add Profile
Select the downloaded file, give it a name, confirm, confirm.
Now you are ready to click on Connect
and be welcomed by this view:
Step 6: Cleanup
Now that we have created all the needed resources and have gained access within the estate, time to delete all the resources to avoid accruing unwanted charges to our account:
> npx cdk destroy --all
Conclusion
The strategic implementation of a managed VPN solution, with dynamic scaling based on usage, self-service capabilities is an invaluable asset in our technological toolkit that paves the way for a fully automated, secure and audited access pattern into cloud and on-premises networks.
This solution, characterized by its ability to maintain complete isolation from the internet while retaining global accessibility to all of the resources present within the private network that have a reachable route from the subnet where the VPN endpoints are placed, represents a significant advancement in our infrastructure capabilities.
In conjunction with the AWS SSM Session Manager, especially that of ECS Exec, offer a comprehensive approach to managing scenarios where both ad-hoc and continuous access to components of applications running on AWS is required.
As always, I invite you to explore the complete codebase for the aforementioned example, available in my GitHub repository, linked here.
I hope this 4 part series has proved useful and helped you in making a decision regarding the route you want to take in accessing your isolated networks on AWS. If you know of any other practical or esoteric and interesting solutions to achieve the goal of connecting to isolated networks, do comment or send me a message on it, I am keen to learn !