To put it simply, a VPC (or Virtual Private Cloud) is like having your own virtual data center. You can think of it as a logical/virtual data center in the cloud.
One of the benefits of using a VPC is that you have complete control over your virtual networking environment. This includes assigning custom IP address ranges, creating of subnets, configure route tables between subnets, have much better security control over your AWS resources and more.
For security purposes, some AWS services like RDS or Elasticache can only be accessed through a VPC or EC2 instance.
We will be using Amazon's Virtual Private Cloud service (Amazon VPC) to create a VPC infrastructure similar to the diagram below.
First, head over to your AWS VPC console (Networking & Content Delivery -> VPC) and click "Your VPCs" on the left menu. Then click the "Create VPC" button to begin the setup process.
Give your VPC a name (in our case, we named it my-demo-vpc).
IP addresses enable resources in your VPC to communicate with each other, and with resources over the internet.
When you create a VPC, you must assign it an IPv4 CIDR block (a range of private IPv4 addresses).
By assigning an IPv4 CIDR block of 10.0.0.0/16, we have 65,536 IP addresses available to use.
A good tool to visualise CIDR ranges is https://cidr.xyz/.
AWS Reserved IPs
You may have noticed that even though we have 65,536 available IP addresses, there were only 65,531 available for our VPC.
Amazon reserves the first four IP addresses and the last IP address in each subnet CIDR block for its own use.
* xxx.x.x.0: Network address.
* xxx.x.x.1: VPC router.
* xxx.x.x.2: The IP address of the DNS server.
* xxx.x.x.3: Reserved by AWS for future use.
* xxx.x.x.255: Network broadcast address.
Head back to your VPC console and click "Subnets" on the left menu. Click on the "Create subnet" button.
We are going to create both public and private subnets.
What is the difference between a public and private subnet?
If a subnet's traffic is routed to an internet gateway, the subnet is known as a public subnet.
If a subnet doesn't have a route to the internet gateway, the subnet is known as a private subnet.
Select the VPC ID that we created earlier and specify a name for the public subnet. (my-public-subnet)
We must specify a CIDR block (10.1.0.0/24) when we create a subnet. This CIDR block is a subset of our VPC CIDR block.
Repeat the same process for our private subnet. Specify a name to differentiate it from the public subnet (my-private-subnet) and assign a CIDR block of 10.2.0.0/24 to it.
Why do we need a public and private subnet?
A common use case for having a public and private subnet is network security. You can segregate a multi-tier website to have the web servers in a public subnet and the database servers in a private subnet.
E.g., you have a public-facing web application that pulls data from a public API through an API Gateway from Lambda but stores data in a private RDS DB instance.
The web application lives in a public subnet while the Lambda function runs in a private subnet.
For the Lambda function to access the internet, the private subnet uses a network address translation (NAT) gateway to connect to the RDS DS instance but prevents the internet from establishing a connection to it.
In this step, we will create an Internet Gateway and attach it to our VPC so that it can communicate with the internet.
Since an Internet Gateway is a highly available VPC component, only one is attachable to a custom VPC.
Head back to your VPC console and click "Internet Gateways" on the left menu. Click on the "Create internet gateway" button.
Specify a name for the Internet Gateway (my-internet-gateway) and click create.
Go back to the landing page and select the newly create Internet Gateway. Then go to Actions -> Attach to VPC.
Select our VPC and attach the Internet Gateway to it.
A NAT Gateway is used to provide internet traffic to EC2 instances in a private subnet.
From the main VPC console, click "NAT Gateways" on the left menu and click on "Create NAT gateway".
Specify a name (my-nat-gateway) and select our public subnet to create the NAT Gateway.
You must also specify an Elastic IP address to associate with the NAT. Click on the "Allocate Elastic IP" button if there are none.
Click on "Create NAT gateway" once that is done.
We are going to create a public and private route table and associate it with the relevant subnets.
A route table specifies how packets are forwarded between the subnets within your VPC, the internet, and your VPN connection.
How it does this is via a set of rules, called routes, that are used to determine where network traffic from your subnet or gateway is directed.
Think of it as a router to direct network traffic.
From the VPC console, click "Route Tables" on the left menu followed by "Create route table".
Give a name for the public route table (my-public-route-table) and select our VPC.
Repeat the process once more to create another private route table.
Next, we need to specify route and subnet associations for our route tables.
Head back to the landing page and select the public route table (my-public-route-table). Then go to Routes -> Edit routes.
Add a new route and specify a CIDR block of 0.0.0.0/0 as the Destination and select the Internet Gateway created earlier as the target.
This ensures that all internet traffic can pass through the public route table via the Internet Gateway.
Repeat the same process for the private route table but specify the NAT Gateway as the target.
Each subnet in your VPC must be associated with a route table.
In our case, we will associate the public subnet with the public route table and the private subnet with the private route table.
From the landing page, select the public route table (my-public-route-table) followed by Subnet Associates -> Edit subnet associations.
Select the public subnet to associate and click save.
Repeat the same process for the private subnet by associating the private subnet to the private route table.
To further harden our AWS setup, we can create a security group for the VPC.
A security group acts as a virtual firewall for your instance to control inbound and outbound traffic.
When you create a security group, the default configuration includes an outbound rule that allows all outbound traffic.
We can remove the rule and add outbound rules that allow specific outbound traffic only. If the security group has no outbound rules, no outbound traffic originating from your instance is allowed.
Security groups control access at the instance level only. If our setup requires an additional layer of security, we can create a network access control list (NACLs) that acts on the subnet level.
From your VPC console, click "Security Groups on the left menu and click on "Create security group".
Specify a name for the security group (my-security-group) and select the VPC that we created earlier on.
Select the security group that we created from the landing page and click on Inbound rules -> Edit inbound rules.
We can add rules to allow specific inbound or outbound traffic for the security group.
In this example, we added an inbound rule that allows traffic from TCP port 6379 only.
With our VPC set up, we can begin to launch EC2 instances or connect other AWS services into our subnets.
A common use case is to connect a web application in a public subnet, which interfaces with a Lambda instance that has access to an RDS MySQL database engine instance in a private subnet.
A good resource to learn more about Amazon Virtual Private Cloud is none other than Amazon's VPC documentation.
If you are feeling adventurous, you can try to create a VPC using the AWS CLI.