Providing Internet Access to a Private AWS Subnet

When you create a VPC in AWS, and then a subnet within the VPC, it is private by default. By private I mean that nothing hosted in the subnet has internet access, and nothing from the internet is capable of making a connection to anything within the subnet. To make the subnet public, i.e. allow it to access the internet and in turn allow external sources to make a connection to endpoints hosted in the subnet, you must create an Internet Gateway and associate it with the subnet.

An Internet Gateway is exactly what it sounds like. It provides a gateway for internet traffic in and out of the subnet(s) it is associated with. You can only have a single Internet Gateway per VPC and it can be used by multiple subnets by routing internet bound traffic to the Internet Gateway in the Route Table associated with the subnet(s). How you choose to set up your route tables is up to you. You can have a single Route Table per subnet, or you can use a single route table for multiple subnets.

routing table with internet gateway Route Table routing internet bound traffic to an Internet Gateway.

Internet Gateways provide access to and from the internet, but for private subnets we want to eliminate the possibility of internet traffic initiating a connection with endpoints hosted in the subnet. There are several options for doing this. The preferred method is to create a NAT Gateway and route internet traffic to that instead of an Internet Gateway. VPC Endpoints also provide private access to AWS services without the need for an Internet Gateway or NAT Gateway. Other options involve keeping an association with an Internet Gateway, but blocking inbound connections by configuring inbound rules in the Network Access Control List associated with the subnet and inbound Security Group rules associated with individual resources in the subnet.

The preferred method of using a NAT gateway provides the associated subnet(s) with outbound internet access while disallowing the inbound internet connections that are usually desired for security reasons. This process involves creating a NAT Gateway in a subnet that is associated with an Internet Gateway that provides that subnet with internet access. Internet bound traffic is then routed to the NAT Gatway in the Route table that is associated with the private subnet. The associated Network Access Control Lists cn then be updated to control inbound and outbound traffic by whitelisting and blacklisting sources and destinations. Resource Security Groups can also be configured to whitelist only desired outbound destinations.

routing table with internet gateway Route Table routing internet bound traffic to a NAT Gateway.

Because the NAT Gateway doesn’t allow connections to be made from the internet to endpoints within the private subnet, it isn’t neccessary to maintain complex inbound rules in the associated Network Access Control List. Even if all inbound traffic is allowed by rule, no internet connection can be made resources inside the private subnet. Keep in mind that if you do modify the inbound rules to exclude inbound traffic, you may block the reply from an outbound roundtrip internet call. See AWS VPC Network ACLs for more information.

NACL allowing all inbound traffic NACL allowing all inbound traffic.

The downside to using a NAT Gateway is that it costs money and for a truely highly available network, you will want one for each availability zone that you are using. You could share a single NAT Gateway for ll of your private subnets, but if each subnet is in a different availability zone and the availability zone that your NAT Gateway is running in goes down, then the remaining availability zones will left without internet access. Allowing internet connectivity by using an Internet Gateway for all of your subnets will be a cheaper option, but some consider it to be less secure.

While allowing the possibility of internet connectivity seems insecure, this is the basic pattern used by Azure. In Azure subnets have internet connectivity by default, but it is definitely not insecure. In both Azure and AWS, in order for inbound connections from the internet to be established, they must be allowed. In AWS and Azure, inbound traffic can be controled by an access control list where traffic is whitelisted and blacklisted. In AWS this is a Network Access Control List and in Azure it is called a Network Security Group. In Azure Network Security Groups can also be applied to resources running within a subnet. This is where AWS differs. In AWS individual resources are associated with Security Groups. These are different that NACLs in that they blacklist all traffic by default and you only whitelist traffic. In both cases, it is a explicit act of configuring the NACLs and Security Groups to allow internet connections to be made to resources in a public or private subnet.

In addition to these traffic rules, in order for an internet connection to be made to a resource, that resource must have a public IP address. When you create a subnet, you specify whether or not public IP addresses are assigned to resources automatically. This feature should be disabled for private subnets. Doing this will make it an explicit act to associate a public IP address to a resource in a private subnet. Proving to your security team that resources are private or not with this setup would not be as easy as it would be if a NAT Gateway were used instead.

The last option I’ll discuss is not as capable as the first two. AWS has resources called VPC Endpoints which can be associated with subnets and they provide private connectivity to AWS services without traversing the internet. These endpoints however do not provide internet connectivity and calls made through these endpoints never leave the AWS network. Use of these endpints may however be required even if a NAT Gateway is used. One scenario where this may be the case is when you want a private API hosted in AWS API Gateway. There are two categories of VPC Endpoints and several different types, the details of which I may discuss in a seperate post.

Making a subnet private and providing internet access to it can be done in several ways. When choosing an approach consider security, cost, and requirements. Maybe you don’t need general internet access, and just need access to AWS services like CloudWatch for logging. I recommend starting with only what you need because this is something that can easily be changed later with simple modifications to your Route Tables, NACLs.