In a previous post, I reviewed what a public subnet and Internet Gateway (IGW) are and that they allowed outbound and inbound connectivity to instances (ie, virtual machines) running in the AWS cloud.

If you're the least bit security conscious, your reaction might be, "No way! I can't have my instances sitting right on the Internet without any protection".

Fear not, reader. This post will explain the mechanisms that the Amazon Virtual Private Cloud (VPC) affords you to protect your instances.

Security Groups

In a nutshell: security groups (SGs) define what traffic is allowed to reach an instance.

"Security group" is a bit of a weird name for what is essentially a firewall that sits in front of an instance, however if you think about it in terms of all servers at a particular tier in an N-tier application (eg, all the web servers) or all the servers that have a common function (eg, all PostgreSQL servers) and how each group would have its own security requirements when it comes to allowed ports, protocols, and IP addresses, then it makes a bit more sense: the security rules appropriate for a group of servers are all put together within the security group construct.

Some more facts about SGs:

  • Each instance you launch must have at least one SG associated with it (the use of SGs is enforced, and that's a good thing)
  • SGs adopt a default deny policy; you as the admin only define what traffic is allowed
  • You cannot explicitly deny traffic with an SG; you're only able to create "permit" rules
  • SGs can manage traffic inbound and outbound to/from an instance
  • SGs are stateful; you do not need to write a rule that allows traffic in the opposite direction

An SG operates on traffic as it's arriving at or leaving an instance. The traffic is evaluated against that instance's SG or SG_s_ and the resulting action—permit or deny—is taken. Because SGs operate at an instance level, this means they're not only inspected for traffic between an instance and the Internet, but also between instances as well. SGs can be used to implement a microsegmentation policy where instances in the same VPC and even in the same subnet cannot communicate with each other. For example, you may decide that there's no reason for the web servers in your web tier to talk with each other.

A very flexible feature of SGs is the ability to reference other SGs in an SG rule. For example, in order to enforce a policy where the PostgreSQL servers only accept connections from the instances in the web tier, it's possible to write rules that enumerate each web server IP address, however that proves fragile when the web tier scales up or a web instance fails and a new one is launched to replace it. A more flexible approach is to reference the security group that the web servers belong to in the database security group. Any members of the web group will then automatically be permitted to connect to the database; no managing of IP addresses necessary.

AWS VPC security group inheritance

Network Access Control Lists

In a nutshell, Network Access Control Lists (NACLs) are dumb packet filters that operate at the subnet level.

NACLs differ from SGs in three primary ways:

  • They sit at the subnet level, not the instance level
  • They are stateless meaning you do have to write rules that allow traffic in both directions
  • They support "deny" rules

NACLs are great for protecting an entire subnet from certain traffic or certan sources coming in from the Internet or for blocking certain ports/protocols outbound from a subnet. For example if you've identified a particular IP address that is hammering your web tier with malicious requests or you know it doesn't make sense for your web tier to connect outbound on TCP port 22 (SSH), you can enforce either of those policies using an NACL.

AWS VPC Network ACL example

Default NACLs have a "permit all" ruleset for in and outbound traffic. When you modify a default NACL, those "permit all" rules will be removed so remember to add them back as appropriate for your needs. Newly created NACLs have a "deny all" ruleset.


Keep in mind that like all things in AWS, SGs and NACLs can be managed via API and/or SDK. When using the CLI SDK, keep these subcommands in mind:

Disclaimer: The opinions and information expressed in this blog article are my own and not necessarily those of Amazon Web Services or Amazon, Inc.