How to Create a Secure 3 Tiered Highly Available Network in AWS: Part Two
Welcome back! In the previous tutorial, we started working to create our own secure and highly available network on AWS. We provisioned all of the infrastructures we’re going to need including the VPC, a bunch of subnets for our different network layers, and the internet and NAT gateways. In this final segment of our two-part series, we’re going to configure all the security to lock these layers down and allow only the traffic we want into our network. Then we’ll deploy a simple WordPress site to make sure everything works. Let’s get started.
Configure Route Tables
As of right now, we have lots of different parts, but no way for them all the interact with each other. Let’s fix that first. Open up your AWS console and go back to the VPC Dashboard. On the left-hand side menu, you’ll see “Route Tables” – navigate there. Immediately you’ll notice there’s an unnamed route table already in existence. When we created our VPC, AWS created a default one for us that allows all of our subnets to communicate to each other regardless of who they are. There is no internet access currently available to our network.
Start by renaming this route table so we can easily identify it later. I went with “foo-default”. After this is done select the route table and you’ll notice a menu appears in the lower half of the screen. The summary tab is pretty self-explanatory, so let’s start with the “Routes” tab. Here we see two entries, one for our VPC CIDR, 10.0.0.0/16, and one for some crazy looking IPv6 CIDR. The destination column says, “any traffic in our VPC” can access any other “local” target. These settings are perfect as they are right now, but we’ll come back to it shortly.
Move over to the “Subnet Associations” tab. You should see two sections. The bottom part is the available subnets; the top is what’s been assigned to this route table. For the default route table, we’re going to associate the NAT subnet we created, so click the edit button and check the box next to “foo-nat.” After a moment everything should finish loading, then return to the “Routes” tab.
Now we want to grant everything routing through this gateway to have access to the internet. Click the edit button and select “Add another route.” For the destination, we want any and all traffic, which in CIDR notation is 0.0.0.0/0. When you click in the “Target” field, you should see two available options, one of them being the Internet Gateway. Select it and click “Save”. What we’ve essentially done here is say, “Take all traffic coming from the associated subnet and route it through the IGW. You’ve just given you NAT access to the internet!
Create Route Tables for the Network Layers
Now it’s time to make three more to handle the traffic in our subnets. At the top of the screen click “Create Route Table.” Give it the name “foo-presentation” and select “foo-network” as the VPC. As mentioned before, our presentation layer should be available to the outside world (the internet), so in the “Routes” tab edit and allow all traffic through the IGW as we did in the previous section. Then on the “Subnet Associations” tab associate both presentation subnets.
Things will be a little different for the next two layers. The only way outside traffic should be able to talk to our application, and core layers are through the NAT or from its parent layer. So create two new Route Tables called “foo-application,” and “foo-core.” In each of them associate their respective subnets. In the “Routes” table though you might be able to guess what’s going to happen. We want to route all traffic through the NAT, so for the destination enter 0.0.0.0/0, and the target should be the NAT.
To continue our castle analogy, what we’ve just done is provide a map to our citizens on how to navigate around. Traffic can now enter and leave the castle however it pleases. This freedom isn’t up to par though; we want to directly control what can move where, so let’s go to the next section.
Configure Access Control Lists
We’re nearly there, all we have left to do is configure the access and security groups for our network. Under the security section on the left click “Network ACLs.” You should see again a single unnamed entry that was created by default by Amazon. An ACL, or Access Control List, allows us to filter where traffic can go inside our network.
The first thing we want to do is repurpose this default ACL for our NAT. The NAT ACL configuration is very straight forward. The Network Address Translation gateway needs unrestricted access to the Internet Gateway so it can handle request from our internal services. Rename the existing ACL to “foo-nat,” then click the item so that the menu appears at the bottom of the screen.
All of the settings under the “Inbound Rules” and “Outbound Rules” we’re going to leave alone. They are set to allow all traffic and out – exactly what we want. Move to the “Subnet Associations” tab. This ACL controls all of the subnets, and we’re unable to change them. The reason for this is that all subnets must have only one ACL at all times. So let’s start making some new ones.
Create more ACLs
Just like many of the other screens so far, click “Create” and supply a name tag like “foo-presentation” and select our VPC. Do this for all three of the layers. By default all of the inbound and outbound rules are open to everything, ignore that for now and associate the appropriate subnets to each ACL.
Now we need to define the rules we’re going to use for each access control list. Let’s start with the outermost layer and work our way down. Select the “foo-presentation” configuration and review the inbound and outbound rules. You can probably guess that the presentation layer is going to be pretty easy. This layer is publicly available and needs complete access to the internet. Click the “Edit” button and create your first rule. Set the rule number to 100, select “ALL Traffic” from the “Type” dropdown and supply the CIDR notation to allow all traffic (0.0.0.0/0).
Right off the bat, let’s assume for this tutorial that all outbound rules are going to be configured to allow all traffic. I’m not particularly concerned about my app sending malicious information out of my network. I’m more concerned about malicious interaction coming into my system. Anybody can leave the castle, but only those with the right permissions can come in. Set all outbound rules to allow all traffic.
In the “Inbound Rules” tab of the “foo-application” ACL lets start making some changes. We’re going to do some forward thinking and open up a few common ports and make some solid assumptions here. Foremost, we only want our other subnets to be able to talk to this layer, with one exception – we’ll get to that later. For now, keep in mind that all of our “Source” CIDRs could be coming from our entire network, 10.0.0.0/16. In general anything below a layer should be able to talk “up,” but only those with access should be able to talk “down.”
You can read these rules like this, “Only TCP traffic on port 80 can come from 10.0.0.0/16.”. Define the below rules in your application ACL.
You’ll notice that rule 400 is a little strange. We created a custom TCP rule to allow a range of ports from any our NAT’s subnet (10.0.0.0/24). We do this because often returned traffic comes through one of these ports. They’re called ephemeral ports and caused me lots of trouble when first starting out on this. We also added an SSH rule, so we access any server deployed into this subnet (from within the network at least).
Now, configure the core ACL.
You’ll notice here that we only allowed inbound traffic from its parent subnets (10.0.10.0/24 and 10.0.11.0/24).
What we’ve essentially done here is to create the “gates” into our castle and posted guards at each of them that interrogate anyone who tries to enter. Take a breather – we’re done with ACLs!
Configure Security Groups
Security groups allow an additional level of control over what traffic can enter a server within a subnet. We’ll use them pretty sparingly, entirely to limit incoming traffic.
Click the “Security Groups” option on the left you’ll be greeted again with the default security group. Rename it like the others “foo-default.” You’ll notice the structure of a security group is similar to an ACL. Ensure the inbound and outbound rules for this standard SG is set to allow all traffic. Now create a new security group for each of the three layers in our network.
In the presentation layer create a rule that allows all traffic from anywhere. In the application layer, create a rule that allows all traffic, but only from the presentation layer. For the core, repeat the process but only allow traffic from the application layer. All traffic should be allowed to leave.
Test out the network
We’re done! You’ve just made a private, secure and highly available network that you can use knowing you’re significantly more safe from outside interference. But how do we test it? In this tutorial, we’re going to do so by deploying a Bitnami WordPress EC2 instance and hitting it from a browser.
Due to the nature of this tutorial, we’re going to move pretty quickly and not touch on the details of deploying an AMI with EC2. Look for future articles to help with that.
Navigate to the EC2 Dashboard in AWS and click “Launch Instance.” On the left side select “AWS Marketplace,” search for “WordPress,” then choose the most recent Bitnami build. In the configuration screen, select “T2.micro” and click “Next,” not “Review and Launch.” On the next screen, we get to configure where we’re going to put this instance. Select the VPC we just built from the dropdown. Then chose the subnet “foo-application” in zone 2a. Leave the rest of the network configurations alone.
Click next a few times until you get to the “Assign Security Groups” page, and chose the existing security group we made for the application layer. Finally, click “Create.”
We just built our application in the “Application” layer, which means we need a way for traffic to get to it. So let’s provision an Elastic Load Balancer which we’ll put in the presentation layer. Adding the load balancer in front is a much more secure way of handling traffic as the recipient of our data will not be directly connecting with our website but to the ELB.
Navigate to “Load Balancer” in the EC2 dashboard and begin configuration of a “Classic Loadbalancer.” On the next page, you’ll be asked to create the ELB inside a VPC. Do so in our network. You’ll then need to select into what subnets you’ll want the ELBs to placed. Select both presentation layers. Click next and also assign the ELB the presentation security group. Ignore the warning about HTTPS for this tutorial. Change the health check to ping TCP with port 80. Then add the WordPress instance we just made in the previous section.
With a bit of luck, a few drawings, and maybe a couple of readthroughs, you’ll be able to view your new WordPress instance from the ELB public URL (found on the “Description” tab of the load balancer).
That’s it! You have successfully created your internal network on Amazons VPC. Your apps will be more secure, your customers happier, and you’ll get more sleep knowing your data is safe.
Thanks for reading and if you need any help be sure to leave a comment below! Happy coding!