VPN connectivity in AWS CDK EC2 provides secure network connections between your VPC and on-premises networks, including site-to-site VPN connections, client VPN endpoints, and VPN gateways.
Site-to-site VPN connection management:
class VpnConnection extends Resource implements IVpnConnection {
constructor(scope: Construct, id: string, props: VpnConnectionProps);
readonly vpnId: string;
readonly customerGatewayId: string;
readonly customerGatewayIp: string;
readonly customerGatewayAsn: number;
// CloudWatch metrics
metric(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric;
metricState(props?: cloudwatch.MetricOptions): cloudwatch.Metric;
metricTunnelIpAddress(props?: cloudwatch.MetricOptions): cloudwatch.Metric;
}
interface IVpnConnection extends IResource {
readonly vpnId: string;
readonly customerGatewayId: string;
readonly customerGatewayIp: string;
readonly customerGatewayAsn: number;
}
interface VpnConnectionProps {
readonly vpc: IVpc;
readonly ip: string;
readonly asn?: number;
readonly staticRoutes?: string[];
readonly tunnelOptions?: VpnTunnelOption[];
}Virtual private gateway for VPN connections:
class VpnGateway extends Resource implements IVpnGateway {
constructor(scope: Construct, id: string, props: VpnGatewayProps);
readonly gatewayId: string;
}
interface IVpnGateway extends IResource {
readonly gatewayId: string;
}
interface VpnGatewayProps {
readonly type: VpnConnectionType;
readonly amazonSideAsn?: number;
}
enum VpnConnectionType {
IPSEC_1 = 'ipsec.1'
}Client VPN endpoint for remote user access:
class ClientVpnEndpoint extends Resource {
constructor(scope: Construct, id: string, props: ClientVpnEndpointProps);
readonly endpointId: string;
readonly dnsName: string;
readonly connections: Connections;
addAuthorizationRule(id: string, props: ClientVpnAuthorizationRuleProps): ClientVpnAuthorizationRule;
addRoute(id: string, props: ClientVpnRouteProps): ClientVpnRoute;
}
interface ClientVpnEndpointProps {
readonly vpc: IVpc;
readonly cidr: string;
readonly serverCertificateArn: string;
readonly clientCertificateArn?: string;
readonly clientConnectionHandler?: IClientVpnConnectionHandler;
readonly authorizeAllUsersToVpcCidr?: boolean;
readonly description?: string;
readonly dnsServers?: string[];
readonly logging?: boolean;
readonly logGroup?: logs.ILogGroup;
readonly logStream?: logs.ILogStream;
readonly port?: VpnPort;
readonly securityGroups?: ISecurityGroup[];
readonly selfServicePortal?: boolean;
readonly sessionTimeoutHours?: number;
readonly splitTunnel?: boolean;
readonly transportProtocol?: TransportProtocol;
readonly userBasedAuthentication?: ClientVpnUserBasedAuthentication;
}Classes for managing client VPN access and routing:
class ClientVpnAuthorizationRule extends Resource {
constructor(scope: Construct, id: string, props: ClientVpnAuthorizationRuleProps);
}
interface ClientVpnAuthorizationRuleProps {
readonly clientVpnEndpoint: ClientVpnEndpoint;
readonly cidr: string;
readonly groupId?: string;
readonly description?: string;
}
class ClientVpnRoute extends Resource {
constructor(scope: Construct, id: string, props: ClientVpnRouteProps);
}
interface ClientVpnRouteProps {
readonly clientVpnEndpoint: ClientVpnEndpoint;
readonly cidr: string;
readonly target: ClientVpnRouteTarget;
readonly description?: string;
}
abstract class ClientVpnRouteTarget {
static subnet(subnet: ISubnet): ClientVpnRouteTarget;
}Supporting interfaces and enums for VPN configuration:
interface VpnTunnelOption {
readonly preSharedKey?: string;
readonly tunnelInsideCidr?: string;
}
enum VpnPort {
HTTPS = 443,
OPENVPN = 1194
}
enum TransportProtocol {
TCP = 'tcp',
UDP = 'udp'
}
interface ClientVpnUserBasedAuthentication {
readonly type: ClientVpnUserBasedAuthenticationType;
readonly activeDirectory?: ClientVpnActiveDirectoryAuthentication;
readonly federatedAuthentication?: ClientVpnFederatedAuthentication;
readonly mutualAuthentication?: ClientVpnMutualAuthentication;
}
enum ClientVpnUserBasedAuthenticationType {
CERTIFICATE_AUTHENTICATION = 'certificate-authentication',
DIRECTORY_SERVICE_AUTHENTICATION = 'directory-service-authentication',
FEDERATED_AUTHENTICATION = 'federated-authentication'
}VPC methods for adding VPN connectivity:
// These methods are part of the IVpc interface
interface IVpc {
addVpnConnection(id: string, options: VpnConnectionOptions): VpnConnection;
addClientVpnEndpoint(id: string, options: ClientVpnEndpointOptions): ClientVpnEndpoint;
enableVpnGateway(options: EnableVpnGatewayOptions): void;
}
interface VpnConnectionOptions {
readonly ip: string;
readonly asn?: number;
readonly staticRoutes?: string[];
readonly tunnelOptions?: VpnTunnelOption[];
}
interface ClientVpnEndpointOptions {
readonly cidr: string;
readonly serverCertificateArn: string;
readonly clientCertificateArn?: string;
readonly authorizeAllUsersToVpcCidr?: boolean;
readonly description?: string;
readonly dnsServers?: string[];
readonly logging?: boolean;
readonly logGroup?: logs.ILogGroup;
readonly port?: VpnPort;
readonly securityGroups?: ISecurityGroup[];
readonly selfServicePortal?: boolean;
readonly sessionTimeoutHours?: number;
readonly splitTunnel?: boolean;
readonly transportProtocol?: TransportProtocol;
readonly userBasedAuthentication?: ClientVpnUserBasedAuthentication;
}
interface EnableVpnGatewayOptions {
readonly vpnRoutePropagation?: SubnetSelection[];
readonly asn?: number;
}import * as ec2 from "@aws-cdk/aws-ec2";
import * as cdk from "@aws-cdk/core";
const vpc = new ec2.Vpc(this, "MyVpc", {
cidr: "10.0.0.0/16",
maxAzs: 2
});
// Add VPN connection using VPC method
const vpnConnection = vpc.addVpnConnection("OnPremisesVPN", {
ip: "203.0.113.100", // Customer gateway public IP
asn: 65000, // Customer gateway BGP ASN
staticRoutes: ["192.168.0.0/16"] // On-premises network CIDR
});
// Enable VPN gateway with route propagation
vpc.enableVpnGateway({
vpnRoutePropagation: [
{ subnetType: ec2.SubnetType.PRIVATE_WITH_NAT },
{ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }
]
});const advancedVpn = vpc.addVpnConnection("AdvancedVPN", {
ip: "203.0.113.200",
asn: 65001,
staticRoutes: [
"192.168.0.0/16",
"172.16.0.0/12"
],
tunnelOptions: [
{
preSharedKey: "mySecurePreSharedKey1",
tunnelInsideCidr: "169.254.12.0/30"
},
{
preSharedKey: "mySecurePreSharedKey2",
tunnelInsideCidr: "169.254.13.0/30"
}
]
});// Create VPN gateway separately
const vpnGateway = new ec2.VpnGateway(this, "VpnGateway", {
type: ec2.VpnConnectionType.IPSEC_1,
amazonSideAsn: 64512
});
// Create VPN connection
const vpnConnection = new ec2.VpnConnection(this, "VpnConnection", {
vpc,
ip: "203.0.113.150",
asn: 65002,
staticRoutes: ["10.1.0.0/16"]
});import * as acm from "@aws-cdk/aws-certificatemanager";
import * as logs from "@aws-cdk/aws-logs";
// Import existing certificates (these should be created beforehand)
const serverCertificate = acm.Certificate.fromCertificateArn(
this,
"ServerCert",
"arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012"
);
const clientCertificate = acm.Certificate.fromCertificateArn(
this,
"ClientCert",
"arn:aws:acm:us-east-1:123456789012:certificate/87654321-4321-4321-4321-210987654321"
);
// Create log group for client VPN logs
const logGroup = new logs.LogGroup(this, "ClientVpnLogs", {
retention: logs.RetentionDays.ONE_WEEK
});
// Create client VPN endpoint
const clientVpn = vpc.addClientVpnEndpoint("ClientVPN", {
cidr: "172.31.0.0/16", // Client IP pool
serverCertificateArn: serverCertificate.certificateArn,
clientCertificateArn: clientCertificate.certificateArn,
// Connection settings
port: ec2.VpnPort.OPENVPN,
transportProtocol: ec2.TransportProtocol.UDP,
splitTunnel: true,
sessionTimeoutHours: 8,
// Logging
logging: true,
logGroup,
// DNS settings
dnsServers: ["8.8.8.8", "8.8.4.4"],
description: "Client VPN for remote workers"
});const adClientVpn = vpc.addClientVpnEndpoint("ADClientVPN", {
cidr: "172.32.0.0/16",
serverCertificateArn: serverCertificate.certificateArn,
userBasedAuthentication: {
type: ec2.ClientVpnUserBasedAuthenticationType.DIRECTORY_SERVICE_AUTHENTICATION,
activeDirectory: {
directoryId: "d-12345678901234567"
}
},
authorizeAllUsersToVpcCidr: true,
splitTunnel: false,
selfServicePortal: true
});const clientVpn = vpc.addClientVpnEndpoint("ClientVPN", {
cidr: "172.31.0.0/16",
serverCertificateArn: serverCertificate.certificateArn,
clientCertificateArn: clientCertificate.certificateArn
});
// Authorization rule for VPC access
clientVpn.addAuthorizationRule("VpcAccess", {
cidr: vpc.vpcCidrBlock,
description: "Allow access to VPC resources"
});
// Authorization rule for internet access
clientVpn.addAuthorizationRule("InternetAccess", {
cidr: "0.0.0.0/0",
description: "Allow internet access through VPN"
});
// Route to VPC through private subnet
const privateSubnet = vpc.privateSubnets[0];
clientVpn.addRoute("VpcRoute", {
cidr: vpc.vpcCidrBlock,
target: ec2.ClientVpnRouteTarget.subnet(privateSubnet),
description: "Route to VPC through private subnet"
});
// Route for internet access through public subnet
const publicSubnet = vpc.publicSubnets[0];
clientVpn.addRoute("InternetRoute", {
cidr: "0.0.0.0/0",
target: ec2.ClientVpnRouteTarget.subnet(publicSubnet),
description: "Route to internet through public subnet"
});const primaryVpc = new ec2.Vpc(this, "PrimaryVpc", {
cidr: "10.0.0.0/16"
});
const secondaryVpc = new ec2.Vpc(this, "SecondaryVpc", {
cidr: "10.1.0.0/16"
});
// VPN connection to primary data center
const primaryVpn = primaryVpc.addVpnConnection("PrimaryDCVPN", {
ip: "203.0.113.100",
asn: 65000,
staticRoutes: ["192.168.0.0/16"]
});
// VPN connection to secondary data center
const secondaryVpn = secondaryVpc.addVpnConnection("SecondaryDCVPN", {
ip: "203.0.113.200",
asn: 65001,
staticRoutes: ["172.16.0.0/12"]
});
// Enable VPN gateways
primaryVpc.enableVpnGateway({
vpnRoutePropagation: [
{ subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }
]
});
secondaryVpc.enableVpnGateway({
vpnRoutePropagation: [
{ subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }
]
});// Create security group for Client VPN
const clientVpnSg = new ec2.SecurityGroup(this, "ClientVpnSG", {
vpc,
description: "Security group for Client VPN endpoint"
});
// Allow VPN clients to access web services
clientVpnSg.addEgressRule(
ec2.Peer.ipv4(vpc.vpcCidrBlock),
ec2.Port.tcp(80),
"Allow HTTP to VPC"
);
clientVpnSg.addEgressRule(
ec2.Peer.ipv4(vpc.vpcCidrBlock),
ec2.Port.tcp(443),
"Allow HTTPS to VPC"
);
const clientVpn = vpc.addClientVpnEndpoint("SecureClientVPN", {
cidr: "172.31.0.0/16",
serverCertificateArn: serverCertificate.certificateArn,
clientCertificateArn: clientCertificate.certificateArn,
securityGroups: [clientVpnSg],
splitTunnel: true
});const haVpc = new ec2.Vpc(this, "HAVpc", {
cidr: "10.0.0.0/16",
maxAzs: 3
});
// Primary VPN connection
const primaryVpn = haVpc.addVpnConnection("PrimaryVPN", {
ip: "203.0.113.100", // Primary customer gateway
asn: 65000,
staticRoutes: ["192.168.0.0/16"]
});
// Secondary VPN connection for redundancy
const secondaryVpn = haVpc.addVpnConnection("SecondaryVPN", {
ip: "203.0.113.101", // Secondary customer gateway
asn: 65000,
staticRoutes: ["192.168.0.0/16"]
});
// Enable VPN gateway with route propagation
haVpc.enableVpnGateway({
vpnRoutePropagation: [
{ subnetType: ec2.SubnetType.PRIVATE_WITH_NAT },
{ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }
]
});import * as cloudwatch from "@aws-cdk/aws-cloudwatch";
import * as sns from "@aws-cdk/aws-sns";
const vpn = vpc.addVpnConnection("MonitoredVPN", {
ip: "203.0.113.100",
asn: 65000,
staticRoutes: ["192.168.0.0/16"]
});
// Create SNS topic for alerts
const alertTopic = new sns.Topic(this, "VpnAlerts");
// Monitor VPN state
const vpnStateAlarm = new cloudwatch.Alarm(this, "VpnStateAlarm", {
metric: vpn.metricState(),
threshold: 1,
comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
evaluationPeriods: 2,
treatMissingData: cloudwatch.TreatMissingData.BREACHING
});
vpnStateAlarm.addAlarmAction(
new cloudwatch_actions.SnsAction(alertTopic)
);
// Monitor tunnel state
const tunnelMetric = new cloudwatch.Metric({
namespace: "AWS/VPN",
metricName: "TunnelState",
dimensionsMap: {
VpnId: vpn.vpnId
}
});
const tunnelAlarm = new cloudwatch.Alarm(this, "TunnelAlarm", {
metric: tunnelMetric,
threshold: 1,
comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
evaluationPeriods: 3
});const dnsClientVpn = vpc.addClientVpnEndpoint("DNSClientVPN", {
cidr: "172.31.0.0/16",
serverCertificateArn: serverCertificate.certificateArn,
clientCertificateArn: clientCertificate.certificateArn,
// Use corporate DNS servers
dnsServers: [
"192.168.1.10", // Primary corporate DNS
"192.168.1.11" // Secondary corporate DNS
],
splitTunnel: false, // Force all traffic through VPN
sessionTimeoutHours: 12
});// Note: This example assumes Transit Gateway is available in your CDK version
// For CDK v1, you might need to use lower-level constructs
const transitGateway = new ec2.CfnTransitGateway(this, "TransitGateway", {
amazonSideAsn: 64512,
description: "Transit Gateway for VPN connectivity"
});
// Attach VPC to Transit Gateway
const tgwAttachment = new ec2.CfnTransitGatewayVpcAttachment(this, "TGWAttachment", {
transitGatewayId: transitGateway.ref,
vpcId: vpc.vpcId,
subnetIds: vpc.privateSubnets.map(subnet => subnet.subnetId)
});
// Create VPN attachment to Transit Gateway
const vpnAttachment = new ec2.CfnVpnConnection(this, "TGWVpnConnection", {
type: "ipsec.1",
customerGatewayId: "cgw-12345678", // Reference to existing customer gateway
transitGatewayId: transitGateway.ref,
staticRoutesOnly: true
});interface VpnStackProps extends cdk.StackProps {
environment: string;
customerGatewayIp: string;
onPremisesCidr: string;
}
class VpnStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: VpnStackProps) {
super(scope, id, props);
const vpc = new ec2.Vpc(this, "VPC");
// Environment-specific VPN configuration
const vpnConfig: Record<string, any> = {
production: {
asn: 65000,
tunnelOptions: [
{
preSharedKey: "prodTunnel1Key",
tunnelInsideCidr: "169.254.10.0/30"
},
{
preSharedKey: "prodTunnel2Key",
tunnelInsideCidr: "169.254.11.0/30"
}
]
},
staging: {
asn: 65001,
tunnelOptions: [
{
preSharedKey: "stageTunnel1Key",
tunnelInsideCidr: "169.254.20.0/30"
}
]
},
development: {
asn: 65002
// No tunnel options for dev - use defaults
}
};
const config = vpnConfig[props.environment];
const vpn = vpc.addVpnConnection("EnvironmentVPN", {
ip: props.customerGatewayIp,
asn: config.asn,
staticRoutes: [props.onPremisesCidr],
tunnelOptions: config.tunnelOptions
});
vpc.enableVpnGateway({
vpnRoutePropagation: [
{ subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }
]
});
}
}