AWS Client VPN - A way to access VPC resources as developer?
Internal enterprise applications are often hosted on private subnets. This article shows you how to access these resources as a developer using AWS Client VPN.
1
2
3
4
aws ssm start-session \
--target i-07575de8a3540b971 \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["https://internal-url"],"portNumber":["80"], "localPortNumber":["8080"]}'
- mutual authentication using client certificates
- user-based authentication using Active Directory or SAML
1
2
3
4
5
6
7
8
9
const vpc = new ec2.Vpc(this, 'Vpc', {
subnetConfiguration: [
{
cidrMask: 24,
name: 'PrivateIsolated',
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
],
});
1
2
3
4
5
6
7
8
9
10
11
12
13
const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', {
vpc,
internetFacing: false,
});
const websiteHandler = new nodejs.NodejsFunction(this, 'website', {
entry: path.join(__dirname, 'website.handler.ts'),
});
const listener = lb.addListener('Listener', { port: 80 });
listener.addTargets('Targets', {
targets: [new targets.LambdaTarget(websiteHandler)],
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { ALBEvent, ALBResult } from "aws-lambda";
export async function handler(event: ALBEvent): Promise<ALBResult> {
const body = "<html>\n<body>\n\n<h1>It works!</h1>\n\n" +
"<p>It works!</p>\n\n</body>\n</html>";
body
return {
statusCode: 200,
headers: {
'Content-Type': 'text/html; charset=utf-8',
},
body,
}
}
1
2
3
4
5
6
7
8
9
10
const hostedZone = new route53.PrivateHostedZone(this, 'MyPrivateHostedZone', {
zoneName: 'my-app.julian',
vpc,
});
new route53.ARecord(this, 'Alias', {
zone: hostedZone,
target: route53.RecordTarget.fromAlias(new route53Targets.LoadBalancerTarget(lb)),
recordName: 'test',
});
ClientVpnEndpoint
for deploying the AWS Client VPN. Add the VPC cidr
and dnsServers
. The DNS server is the .2
address in the VPC, for example 10.0.0.2
in a VPC with CIDR 10.0.0.0/8
. A split tunnel VPN is configured using the splitTunnel
property. Only traffic to the previously specified CIDR will be routed through this VPN tunnel. For serverCertificateArn
and serverCertificateArn
, use the certificate ARNs you previously created in AWS Certificate Manager.1
2
3
4
5
6
7
8
9
10
11
const vpn = new ec2.ClientVpnEndpoint(this, 'ClientVpnEndpoint', {
vpc,
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
cidr: '10.100.0.0/16',
dnsServers: ['10.0.0.2'],
splitTunnel: true,
serverCertificateArn: 'arn:aws:acm:eu-west-1:012345678901:certificate/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
clientCertificateArn: 'arn:aws:acm:eu-west-1:012345678901:certificate/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY',
});

downloaded-client-config.ovpn
to the folder that contains the certificates and keys (called custom_folder
in the documentation). Open the file in a text editor and add the following lines at the end of the file to reference the client certificate and the client key.1
2
cert client1.domain.tld.crt
key client1.domain.tld.key
downloaded-client-config.ovpn
into OpenVPN. The connection will start automatically.
http://test.my-app.julian
can be opened in a web browser.