If you want to run a server in a private subnet, you’ll need to use a VPN to connect to it. AWS VPN is a managed OpenVPN service that can handle this for you, and allow you to lock down public access to your protected instances.
Client VPN vs. Site-to-Site VPN
AWS has two different kinds of VPN available for you to use. The first, and simplest, is the Client VPN. This is a fully managed elastic VPN service based on OpenVPN. Combined with an OpenVPN enabled client device, this allows users to access your AWS infrastructure from anywhere as if they were in the network itself.
This allows your employees to connect directly to servers in private subnets, such as database servers you’d rather not leave web-facing. You can also choose to block SSH on public servers from anywhere that’s not on the local subnet, which will only allow administration from users connected to the VPN.
This is pretty great, and works quite well for large corporate workloads, but if you’ve only got a few people needing to connect, as it can be quite expensive. Client VPN has two charges—a flat fee for each VPN associated with a subnet, and a fee per hour for each client connected to it. The flat fee is $75 per month, and the charge per user is $0.05 per hour. With moderate usage from a few people, you could easily rack up over $100 in total charges for Client VPN. And, of course, you will incur all the standard data transfer charges for moving data around in AWS and out to the internet.
All Client VPN really is is a managed OpenVPN server, which is open source. If you have a bit of time, you can set up your own OpenVPN server on an EC2 instance, which will cost significantly less. It’s fairly lightweight, so if the $75 per month fee seems like a lot to you, you can probably run it on a
t2.micro instance for a fraction of the price of Client VPN.
The second VPN that AWS offers is a Site-to-Site VPN. Rather than connecting multiple remote clients, the Site-to-Site VPN connects your AWS VPC directly to your on-premises network through a secure tunnel.
This enables you to move on-site applications to the cloud and connect them directly to your preexisting network, using the same corporate firewall you have in place, and without changing the way your users access your applications. In a way, Site-to-Site VPN simply securely extends your on-premises network into the cloud, allowing you to access EC2 instances in the chosen VPC as if they were on your network.
Site-to-Site VPN is highly elastic, and even supports redundant failover connections if the primary one loses connection for any reason. It’s also priced a bit different—you’re only charged $36 per month, per connection, but you’ll be charged $0.09 per GB of data transferred out, on top of standard AWS data charges.
Setting Up a Client VPN
We’ll show how to set up a Client VPN here, as it is the most versatile and useful to people without on-premises hardware.
Before you get started, you’ll have to create certificates for the server and each client to use. You could generate these with ACM, but it requires setting up a private certificate authority, which costs $400 per month. If you don’t feel like paying that cost, you can generate them using
OpenVPN. Download and initialize a new CA:
git clone https://github.com/OpenVPN/easy-rsa.git cd easy-rsa/easyrsa3 ./easyrsa init-pki ./easyrsa build-ca nopass ./easyrsa build-server-full server nopass
Now, generate a client certificate, replacing “
client1.domain.tld” with the client name and
./easyrsa build-client-full client1.domain.tld nopass
Now, we’ll need to upload the certificates to ACM so they’re usable with Client VPN. They’re all located in the
pki folder, so
cd over there:
and upload the server cert using this rather clunky command, making sure your CLI region is set to the same region you’re creating the Client VPN in:
aws acm import-certificate --certificate file://issued/server.crt --private-key file://private/server.key --certificate-chain file://ca.crt
You can also use the “Import Certificate” button in ACM, which will have you paste in the contents of each file, but it’s easier to copy and paste. Import the client certificate in the same way:
aws acm import-certificate --certificate file://issued/client1.domain.tld.crt --private-key file://private/client1.domain.tld.key --certificate-chain file://ca.crt
Now, you can set up Client VPN. From the VPC Management Console, click on “Client VPN Endpoints” under the “Network (VPN)” section in the sidebar, and create a new endpoint.
First, you’ll need to give the VPN a CIDR block that isn’t being used by your current VPC. You can find your VPC’s block under the “Your VPCs” tab. For example, if you’re using the default block of
172.31.0.0/16, you can set Client VPN to
172.16.0.0/16, which doesn’t overlap.
Next, paste in the ARN for your primary server certificate (you can find this in the ACM Console), check “Use Mutual Authentication,” and paste in the ARN for the client certificates. You’ll can use this client cert for multiple users, but if you’d like a better way to manage access, you can instead use Active Directory authentication with AWS Directory Service.
That’s all that is required, so go ahead and click create. You will be billed as soon as it’s created.
You’ll have to associate this VPN with a particular VPC and subnet. From the “Associations” tab, click “Associate,” and then select the VPC and subnet you wish to use.
If you are using the defaults, you’ll have one VPC available and multiple subnets for each availability zone. Select the availability zone subnet you’re currently using.
Under “Authorization,” you’ll want to add an ingress rule allowing access to the subnet you associated the VPN with. This can be a more specific CIDR block or the entire subnet. If you’re using AD, you can also limit access to a particular group.
From the VPC console, click “Download Client Configuration.” This will download an
.ovpn file that you can use in any OpenVPN client to connect to the VPN. However, this file only comes from AWS with the server CA certificate, so you’ll need to open it up and paste in the
/issued/client1.domain.tld.crt cert in a
block, and the
/private/client1.domain.tld.key keyfile in a
.ovpn file will look something like the following:
client dev tun proto udp remote asdfa.cvpn-endpoint-0dbc42be17e0f2c68.prod.clientvpn.us-east-1.amazonaws.com 443 remote-random-hostname resolv-retry infinite nobind persist-key persist-tun remote-cert-tls server cipher AES-256-GCM verb 3
-----BEGIN CERTIFICATE----- CA KEY -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- CLIENT CRT FILE -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- CLIENT KEY FILE -----END PRIVATE KEY-----reneg-sec 0
You’ll also want to append a random string to the “
remote cvpn-endpoint-xxxxxx” line, like so: