Failing to plan is planning to fail.
While this could apply to all things infosec, it especially does to virtual private cloud security. That's because, while AWS has security baked into Amazon VPC, it is not enough to rely on this design alone. Administrators must meticulously configure and maintain the Amazon VPC to keep hosted applications, servers and resources secure.
In his book AWS Security, author and Google software engineer Dylan Shields presents an actionable reference for other software and security engineers who are tasked with building and securing AWS applications.
Security incidents, such as denial-of-service attacks and brute-force SSH attacks, can be prevented if organizations conduct due diligence when it comes to network security. The best way to avoid these attacks, Shields said, is by creating secure VPCs, subnets and security groups.
In his previous work as a first engineer on the AWS Security Hub team, Shields became well acquainted with various AWS security tools but noticed that this information was not commonly known among cloud administrators.
The following excerpt from Chapter 4 of AWS Security published by Manning Publications serves as a cookbook for implementing Amazon VPC security best practices.
In the last two chapters, we talked about how to securely configure logical access to your AWS resources through IAM. In this chapter, we're going to move on to controlling network access, primarily through a virtual private cloud, or VPC, and its associated networking resources. Many of the concepts in IAM and VPC are similar. We want to create rules that determine who has what kind of access to our AWS resources. In IAM the rules are policies, which specify actions that can be performed in the API or the console, and these rules are applied to IAM entities (users, groups, and so on) who are authenticated using AWS credentials. In the networking sphere, the rules are concerned with what kind of traffic is permitted into your network, and further to specific resources within your network. For example, a rule might only permit HTTPS traffic into your network, and only on port 443. Rather than being applied to authenticated entities, these rules are instead applied based on the source of the traffic. As an example, you might apply the previous HTTPS traffic rule to any traffic originating outside your network but allow any kind of traffic originating inside your network. While the concepts are similar, the mechanisms for creating and configuring these access rules are completely different. In this chapter, we'll go over the primary VPC networking resources and how to set them up.
Before we dive in, we should talk about why securing your network is important. While many different kinds of attacks exist against network-accessible resources, we'll look at three of the most common. These are attacks that can be easily prevented by applying the basic principles outlined later in this chapter.
The first type of attack involves an attacker finding and exfiltrating information from a publicly accessible database. Why are these databases left vulnerable? One reason is that setting up secure networks can involve creating many resources, and this isn't always done correctly. For example, if you create a web server and a database, and don't create your own security groups, they will both be in the default security group. When you allow public network access to the web server, you'll expose your database as well. Later in this chapter, we'll walk through solving this problem by creating secure network rules with security groups and network ACLs.
Another common attack is denial of service. You might have heard of it as DoS, or DDoS (distributed denial of service). The usual form of a denial of service attack is flooding your application with tons of fake requests to overload your system and prevent you from fulfilling the real requests. We'll show in this chapter how you can use AWS networking resources to mitigate certain kinds of denial of service attacks. In the following chapter, we'll look at how to prevent more sophisticated denial of service attacks using Web-App and Next-Gen firewalls.
A third attack covered in this chapter is getting SSH access to a web server. When you run a website, you generally open up traffic to the public internet on purpose. But when you do so, you want to make sure that you haven't exposed anything private that might be running on the same server. Many times, an EC2 instance is running a web server, and the operator opens up all network traffic to the instance. This allows everyone to view the website, but it also allows everyone to send other kinds of traffic as well, such as SSH connections. If you run SSH on the default port, use a default user for the operating system, and use a password for authentication rather than an SSH key, then it's only a matter of time before an attacker gains access to the server. In this chapter, we'll see how you can easily create rules that allow public access to your website, but not allow other kinds of traffic such as SSH.
4.1 Working with a virtual private cloud
The rules that we create for controlling network access in AWS apply to various networking resources. To understand how those rules work, we first need to understand the primary networking resources available to us. At the highest level, we have the VPC. A VPC represents an isolated network. Within a VPC we have subnets, or individual sub-networks. Most networked resources, such as EC2 instances, are attached to a subnet. These subnets can be either public or private, which refers to whether or not resources within the subnet are accessible over the public internet. Traffic between resources within a VPC will be routed through the VPC. The traffic doesn't leave the VPC and isn't vulnerable to the same kinds of snooping and man-in-the-middle attacks as if it had gone over the public internet. For this reason, it's generally better to keep traffic within a VPC when possible and not route traffic over the public internet. This is such an important concept that several networking resources exist for specifically this purpose, such as VPC peering, PrivateLink, and TransitGateways, which we'll cover in this and the following chapter.
In addition to VPCs and Subnets, you should also be familiar with these other networking primitives:
- Elastic Network Interface (ENI): A virtual equivalent of a network card.
- Elastic IPs (EIP): A public IPv4 address assigned to your account.
- Internet Gateway (IGW): A resource that allows your network to communicate with the public internet.
- NAT Gateway: A resource that allows initiating connections to the public internet from within your network, but not the other way around.
- Egress-Only Internet Gateway: The IPv6 equivalent of a NAT Gateway.
In this section, we'll dive deeper into each of these resources and create a network in our AWS account that looks like figure 4.1. In the following section we'll expand on that diagram, filling in the faded resources in the diagram, the rules that dictate how traffic flows through the network.
Let's start with VPCs. As we've said, a VPC is a virtual network. If you want to create any networked resources in AWS, you're going to first have to create a VPC. This is a relatively easy task, because a VPC has only a couple of options. The main one is the CIDR block. This is the range of IP addresses that will be available for use in your network. CIDR stands for Classless Inter-Domain Routing and for our purposes, we're interested in CIDR blocks, which are a compact notation for describing a range of sequential IP addresses. Here are several example CIDR blocks:
CIDR blocks consist of an IP address followed by a slash and a number between 0 and 32. The IP address refers to the smallest IP in the block, and the number after the slash refers to the size of the network. The size of the network is IP addresses, where is the number after the slash. Note that larger numbers correspond to smaller network sizes. A CIDR block ending in /32 would result in only 1 IP address, and a block ending in /24 would result in 256 addresses. Table 4.1 contains the ranges of IP addresses that correspond to the previous sample CIDR blocks.
Note that the table describes CIDR blocks in terms of IPv4 addresses, but IPv6 addresses can also be used. The difference is that the number after the slash is between 0 and 128, rather than 0 and 32.
There are two important things to consider when choosing a CIDR block for your VPC. The first is that each networked resource that you put into your VPC will be assigned its own private IP address within the CIDR block of the VPC. If you create a VPC with a /24 CIDR block, which has 256 addresses, you can't put more than 256 resources into that VPC. In fact, AWS reserves five IP addresses within each subnet, so if even if you only had one subnet you could only put 251 resources into a VPC of size /24. While there's a way to associate an additional CIDR block to your VPC, you should choose a network size large enough to support all of the resources that you plan to put in the VPC. The second point to consider is that overlapping IP ranges create routing issues. For example, Google uses the IP addresses in the block 22.214.171.124/24. If you create a VPC with that same block, then you will end up with hosts that have the same IP address as the Google servers. This makes it difficult to determine where traffic should be routed. For this reason, you should stick to the ranges that have been reserved for private networks, like 10.0.0.0/8 (10.0.0.0—10.255.255.255), and 172.16.0.0/12 (172.16.0.0—172.31.255.255). In addition, you shouldn't use overlapping ranges for any two VPCs if you plan to route traffic between them.
AWS automatically creates a VPC for you in your account, called the default VPC. This VPC is configured with the CIDR range: 172.31.0.0/16. It's initialized with public subnets and an internet gateway. This makes it easy to get started with many AWS services such as EC2, because you can launch an instance and access it, without worrying about setting up these network resources. However, the configuration of the default VPC is likely not the most secure for whatever you're doing. We won't use the default VPC and will instead create all of the resources ourselves.
Let's create our VPC now. We'll use the AWS CLI create-vpc command:
$ aws ec2 create-vpc \ --cidr-block 10.0.0.0/24
That command creates our VPC. Right now, there's nothing in it, and our network is only a container with a range of IP addresses. The next thing to do is to put subnets inside our VPC.
- Network access controls in VPC are similar to the logical access controls of IAM, but they're configured in completely different ways.
- Using VPCs and other networking resources allows you to control network access to and from your AWS resources.
- Configuring built-in virtual firewalls such as Security Groups and Network ACLs lets you lock down your network and protect against unauthorized access to your resources.
- Putting resources into separate VPCs isolates them from each other and prevents a compromised resource from accessing other resources.
- Setting up a peering connection between VPCs allows you to isolate resources in separate VPCs while still allowing for private connections between them.
- Using VPC Peering, Site-to-Site VPN, or Direct Connect allows you to connect to a resource without residing in the same VPC, and also avoids the risks associated with sending traffic over the public internet.
About the author
Dylan Shields is a software engineer working on quantum computing at AWS. Previously, Shields was the first engineer on the AWS Security Hub team. He has also worked at Google Cloud, focusing on the security and reliability of its serverless data warehouse, BigQuery.