Skip to content

Security groups - VPCs

Created: 2016-02-17 11:23:52 -0800 Modified: 2018-12-07 14:32:58 -0800

  • A “private” subnet is only private by virtue of not having an Internet gateway attached.
  • If you don’t configure inbound rules at all (i.e. they’re totally empty), then no traffic is allowed in. Likewise, with outbound rules, if you don’t have any rules (i.e. not even the default that allows outbound traffic to everything), no traffic is allowed out, even to other AWS instances in the same subnet.
  • If you need egress-only Internet traffic from an endpoint (i.e. traffic can go out to the Internet but not receive connections from the Internet), then there are a couple of solutions:
    • An egress-only Internet gateway (reference)
    • A “normal” Internet gateway combined with security groups to limit inbound traffic only to particular other security groups or IP addresses.
    • By having private subnets as opposed to security groups, that means that any two internal endpoints on private subnets that need to communicate with one another would have to use internal networks. This means that traffic can’t get routed outside of the cloud. This probably means lower latency, but it definitely means that you won’t be charged for egress traffic since there will be no egress traffic.
  • Traffic on the same subnet will have layer-2 adjacency, meaning it will communicate faster than if the traffic had to go through a device that would change the packet (reference).
  • If your security groups are configured correctly, then there’s nothing stopping traffic across subnets, even private → public or vice versa. If traffic couldn’t travel across subnets, then none of the Internet would work.
  • For deciding between public vs. private subnets and endpoints, this resource may be helpful.

In general, there are multiple layers of security/firewalls on AWS:

These are set up via the VPC dashboard. They work like how Azure worked: you set up rules that have various priorities (which are called “rule numbers” on AWS). Rules are processed from lowest to highest priority, which means you should leave some gaps between the rules when you’re creating them.

Default rules:

  • Every ACL will have a DENY-ALL catch-all at the end, but it’s only hit if no other rules were matched. Also, you can’t delete this DENY-ALL, nor should you want to.
  • Every ACL will have an ALLOW-ALL rule with the priority of 100, meaning all traffic is allowed by default.

A VPC is created with an ACL; you can’t change this association, but you can change the ACL itself.

Subnets also have a default ACL, but you can change the association for these (as opposed to being forced to modify the ACL that you were given).

If you want to IP-ban someone as a temporary measure, you can do it with the network ACL, just make sure the DENY rule that you add comes before any ALLOW rules. Also, to mask a single IP address, use “/32” at the end. For example, if I want to ban, I’d add “”.

When creating a new subnet, if you want instance IPs (as opposed to no IP or an elastic IP), then you should right-click your subnet and choose “Modify Auto-Assign Public IP”. I think that if you do this after you’ve already provisioned an EC2 instance that you’ll have to restart the instance (<citation needed>).

If you delete your default VPC, the only way to get it back is to contact AWS support. However, you shouldn’t ever need the default VPC again. You shouldn’t need the default anything really (subnets, route tables, etc.).

First of all, something worth noting is that when choosing a source IP, you have three options: Anywhere, My IP, and Custom IP. “Custom IP” will autocomplete with a whole bunch of useful options that aren’t necessarily IP addresses, e.g. other security groups that you’ve configured.

To edit your security groups, go to AWS Console —> EC2 —> Network & Security —> Security Groups.

If I want to restrict traffic only to a particular VPC, then I can make a new security group and set inbound traffic on it using the Source of another security group (remember: choose “Custom IP” and then start typing “sg-” to see your security groups).

For example, if I want to give a new VM access to the database, I would make a security group called “Access to DB” with no inbound or outbound rules (so that it’s essentially just used as a tag). Then, I would make another security group called “Allow MySQL traffic” that opens port 3306 only to members of the first security group.

Once you have a security group that refers to itself, you can apply it to various endpoints:

  • RDS
    • From RDS Dashboard, click Instance Actions —> Modify. Then you’ll find your security group. Choose the right one. Scroll to the bottom and choose “Apply immediately” so that this doesn’t have to wait until your next maintenance window.
    • Note: you can choose multiple security groups from the box by ctrl+clicking.
  • EC2
    • From EC2 Dashboard, right-click an instance, go to Networking —> Change Security Groups. Check any applicable boxes for your security groups.

This section contains some of the security groups that I think are good for testing things out. Make sure to read the warnings below.

Inbound rules

NameTypeProtocolPort RangeSourceDescription
SSH AccessSSHTCP22<just your IP>Useful for VMs you set up that you want to SSH into. You may want to set the IP to only your IP address.
MySQL AccessMYSQL/AuroraTCP3306<your ‘Access to DB’ group>Only open the DB up to your ‘Access to DB’ group.
Access to DBN/AN/AN/AN/AThis is just used as a group to tag which endpoints have access to your DB.

Warnings: the above rules are just for testing. Here are some things to correct from above:

  • Real-world endpoints likely shouldn’t have SSH open on them.
  • Outbound rules should be made stricter. If someone got access to a game server, let’s say, then they couldn’t just export data to any random machine on the Internet.
  • ”Tag” groups like “Access to DB” should be made more specific. For example, if you want your REST server to have access to the database, then make a security group for the REST server that is fully configured, then specify that as your source in the “MySQL Access” group.