AWS security groups act as virtual firewalls that control inbound and outbound network traffic to and from EC2 instances within an Amazon Virtual Private Cloud (VPC). They operate at the instance level, enforcing rules based on protocol, port, and source/destination IP address.
Each security group contains a set of rules defining which traffic is allowed. Rules are stateful: if an inbound rule allows traffic, the response traffic is automatically permitted, regardless of outbound rules. This behavior differs from traditional network ACLs, which are stateless.
Security groups are associated with EC2 instances at launch or later via the console, CLI, or API. They cannot be applied directly to subnets-they apply only to individual instances or load balancers.
When an EC2 instance launches, it is assigned one or more security groups. These groups define what traffic can reach the instance's elastic network interface (ENI).
For example, a web server running on port 80 (HTTP) requires an inbound rule allowing TCP traffic from any IP on port 80. Without such a rule, external requests are dropped silently. Similarly, outbound rules govern what traffic the instance can initiate.
Rules are evaluated in order. A deny rule takes precedence over allow rules. However, AWS processes rules in a single pass: if any rule matches, the packet is accepted or rejected accordingly. There is no priority ranking among rules; they are processed collectively.
There are two primary types of security groups: default and custom.
Security groups support both IPv4 and IPv6 addresses. Rules can reference:
| Rule Type | Protocol | Port Range | Source/Destination |
|---|---|---|---|
| Inbound | TCP | 80 | 0.0.0.0/0 (anywhere) |
| Inbound | HTTPS | 443 | 10.0.1.0/24 (trusted internal subnet) |
| Outbound | ICMP | All | 0.0.0.0/0 |
Using a security group to allow HTTPS traffic only from a specific internal subnet reduces exposure compared to allowing access from anywhere on the internet.
Many users assume that security groups are redundant if they've configured network ACLs. This is incorrect. Network ACLs are stateless and operate at the subnet level, while security groups are stateful and apply at the instance level. Both layers are needed for defense-in-depth.
Another misconception is that security groups can filter traffic between instances in different availability zones. They do not-traffic routing depends on VPC routing tables and subnets. Security groups only affect traffic reaching the instance's ENI.
A less obvious point: you cannot assign multiple security groups to a single ENI. Each ENI can have up to five security groups attached. If you exceed this limit, AWS returns an error during instance launch or modification.
Consider a three-tier web app hosted in a VPC with public and private subnets. The architecture includes:
The following security groups are defined:
This setup helps only authorized components can communicate. External users cannot reach the database directly. Even if an attacker compromises the web server, they cannot access the database unless they also compromise the application server.
Testing this configuration: a curl command from outside the VPC to the database instance fails with "Connection refused." From the application server, the same command succeeds because the security group allows the connection.
Use security groups to enforce least privilege. Only open ports that are necessary. Avoid using 0.0.0.0/0 for sensitive protocols like SSH or database access.
Use security group IDs as references in other resources. For example, when creating an Auto Scaling group, specify the security group ID in the launch template. This ensures consistent access control across scaled instances.
Automate security group management using AWS CloudFormation. Define security groups as resources in a template, enabling version-controlled, repeatable deployments. For example:
Resources:
WebServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: 'Allow HTTP and HTTPS'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
VpcId: vpc-12345678
Deploying this template ensures the same security settings across environments.
Security groups differ from several related features:
| Feature | Scope | Statefulness | Use Case |
|---|---|---|---|
| Security Group | Instance level | Stateful | Per-instance access control |
| Network ACL | Subnet level | Stateless | Subnet-wide filtering; first layer of defense |
| Route Table | Subnet or VPC | N/A | Defines how traffic flows between subnets and to internet gateways |
| Security Group in Transit Gateway | Transit Gateway attachment | Stateful | Controls traffic between VPCs connected via transit gateway |
For example, a network ACL can block all traffic to a subnet except from a known IP range. But if an instance in that subnet initiates outbound traffic, the ACL doesn't filter it-only the security group does.
I once observed a misconfigured environment where a security group allowed SSH access from 0.0.0.0/0. The network ACL blocked all outbound traffic from the subnet. Despite the open SSH port, no one could connect because the network ACL dropped the packets before they reached the instance. This highlighted the layered nature of AWS security.
What are AWS security groups? They are essential components of network security in AWS, acting as stateful firewalls that control traffic to and from EC2 instances. Properly configured, they prevent unauthorized access and reduce attack surface.