Virtual Private Cloud (VPC) is a pretty important topic for the AWS Solutions Architect cert. Here, I attempt to quickly summarize the different parts of a properly architected VPC.

A typical system has web servers and database servers. Your web servers sit on the demilitarized zone (DMZ), while your database servers are protected in a private network. In a VPC, you’d create two subnets: a public one, and a private one. The public one is where your web server EC2 instances are created, while the private one is where your database server EC2 instances would be created. The public subnet will have auto-assign public ip address configured, because we want servers in this subnet to be resolvable. This will be disabled for the private subnet, as we want our instances in this subnet to be hidden.

Your VPC needs to communicate with the internet. So you create an internet gateway (IGW) that serves as a bridge between your VPC and the web.

You need your EC2 instances on the public subnet to somehow reach out to the IGW, then to the internet. You’ll need to create a network access control list (NACL) to specify traffic rules for every EC2 instance created in any of its associated subnets. In this case, you’ll want to create a NACL for your public subnet, with inbound and outbound rules to allow (the CIDR catch-all for ipv4 addresses) for ports 80 (http), 443 (https), and 22 (ssh).

Your EC2 instances on your public subnet are now allowed to make requests for ipv4 addresses using the http and https ports. You now need to actually direct these requests to the IGW. AWS has a router in your VPC, for which you’ll need to create route tables; one for each of your subnets.

In your public subnet’s route table, add a rule that directs traffic bound for to the IGW that you created earlier. Your private subnet’s route table will have to wait; there’s still another piece that you need in your VPC.

Because your private subnet doesn’t assign public ip addresses, we can’t have traffic between EC2 instances within this subnet and the internet directly. To resolve this, create a NAT Gateway (NGW) on the public subnet. Then, add a rule to the private subnet’s route table that directs traffic bound for to the NGW. Because the NGW sits on the public subnet, traffic bound for from the private instance will be directed to the IGW, then to the internet, and vice-versa.

Lastly, you’ll need to manage instances in your private subnet somehow. But you can’t ssh into it directly because it doesn’t have a public ip. You can probably multi-hop ssh thru an instance on the public subnet, but we can handle this a better way. Instead, you’ll create a bastion host; essentially, a barebones linux server that has sole access to the private subnet via ssh. You can then put the rest of your EC2 instances on the public subnet in a security group that bars traffic on port 22 with respect to the private subnet (remember that security groups are stateful, in that creating an outbound rule also results in a corresponding inbound rule). And in order to administer your instances on the private subnet, just multi-hop the bastion into the former.

In conclusion, we have our basic VPC:

  • a public subnet that auto-assigns ip addresses
  • a private subnet that does not auto-assign ip addresses
  • an IGW bridging the VPC and the internet
  • a NACL for allowing traffic at on the standard ports
  • a route table for the public subnet, directing traffic to/from the IGW
  • a NGW on the public subnet
  • a route table for the private subnet, directing traffic to/from the NGW
  • a bastion host for multi-hop ssh into instances on the private subnet