Quick Answer
An AWS security group acts as a virtual, stateful firewall that controls inbound and outbound traffic for your Amazon EC2 instances and other supported AWS resources. Each security group operates at the Elastic Network Interface (ENI) level rather than the subnet level, providing granular packet filtering for individual instances. When you launch a virtual machine in the cloud, assigning the correct security group ensures that only authorized traffic can communicate with your workloads.
Understanding how these virtual firewalls process network packets is essential for anyone designing cloud architecture. Unlike Network Access Control Lists (NACLs), which are stateless and apply at the subnet boundary, security groups evaluate traffic dynamically and remember connection states. This design simplifies security management by eliminating the need to explicitly configure return rules for outbound traffic.
Quick Answer
What is an AWS security group? It is a stateful, instance-level virtual firewall provided by Amazon Web Services to filter inbound and outbound network traffic. By default, security groups block all incoming traffic and allow all outgoing traffic. Administrators attach these rules to EC2 instances by specifying allowed ports, protocols, and source IP addresses or other security groups, establishing a robust perimeter for cloud environments.
The service operates transparently behind the scenes, inspecting packets as they reach the network interface of a virtual server. Because security groups are stateful, any packet belonging to an established connection initiated from inside the instance is automatically permitted back through, regardless of inbound restrictions. This makes configuring application architectures much simpler while maintaining strict boundaries against unauthorized external connections.
What Is a Security Group?
Stateful behavior
AWS security groups are inherently stateful, meaning they track the state of active connections. If an EC2 instance sends an outbound request to an external API or database, the security group records that transmission. When the remote server responds, the firewall automatically recognizes the reply as part of the established session and permits it back in, without requiring a matching inbound rule.
Port rules
Traffic filtering relies on defined port rules. Rules specify the protocol (such as TCP, UDP, or ICMP) and a specific port range (like port 443 for HTTPS or port 22 for SSH). When evaluating traffic, the firewall checks incoming or outgoing packets against these protocol and port definitions. If a packet does not match an explicit rule, it is dropped by default.
Source/destination
Every rule requires a designated source (for inbound traffic) or destination (for outbound traffic). These can be defined using IPv4 or IPv6 CIDR blocks (such as 192.0.2.0/24), another security group ID within the same or peered VPC, or AWS Prefix Lists. Referencing another security group is a best practice for microservices, allowing secure communication between application tiers without hardcoding changing IP addresses.
Least privilege
Applying the principle of least privilege means granting only the minimum permissions necessary for an application to function. In cloud networking, this translates to avoiding overly broad CIDR ranges like 0.0.0.0/0. Instead of exposing management ports to the entire internet, engineers restrict access to specific corporate IP ranges, VPN gateways, or bastion hosts.
Inbound Rules
Image Pending
Configuring inbound rules programmatically using the AWS CLI.
Inbound rules dictate which incoming packets are allowed to reach your EC2 instances. When configuring an inbound rule in the AWS Management Console, you specify the traffic type, protocol, port range, and source. For example, to allow secure shell access, you create a rule for TCP port 22 originating from your administrative CIDR block.
Using the AWS CLI, you can programmatically authorize inbound traffic. Consider this example command for adding an HTTP rule:
aws ec2 authorize-security-group-ingress \
--group-id sg-0123456789abcdef0 \
--protocol tcp \
--port 80 \
--cidr 203.0.113.50/32
Always verify your changes immediately after application. You can check applied rules using the describe-security-groups command to confirm that no unintended source ranges were accidentally introduced during deployment.
Outbound Rules
By default, every newly created security group includes a single outbound rule that allows all traffic to leave the instance toward any destination (0.0.0.0/0). While convenient for general workloads, high-security environments often require restricting egress traffic to prevent data exfiltration or unauthorized outbound connections.
To lock down egress traffic, you can delete the default all-traffic rule and replace it with explicit rules. For instance, you might permit outbound HTTPS traffic (port 443) only to specific update repositories or internal database endpoints. Here is how you can modify outbound rules using the AWS CLI:
aws ec2 revoke-security-group-egress \
--group-id sg-0123456789abcdef0 \
--protocol -1 \
--port all \
--cidr 0.0.0.0/0
aws ec2 authorize-security-group-egress \
--group-id sg-0123456789abcdef0 \
--protocol tcp \
--port 443 \
--cidr 10.0.0.0/16
Restricting outbound traffic adds an extra layer of defense, ensuring compromised workloads cannot easily communicate with malicious command-and-control servers.
Common Port Examples
Configuring the right ports is critical for service availability. Below are standard port configurations used across common AWS architectures:
- SSH (Secure Shell): TCP Port 22, restricted to trusted jump boxes or corporate static IPs.
- HTTP: TCP Port 80, typically open to 0.0.0.0/0 for public web servers behind a load balancer.
- HTTPS: TCP Port 443, encrypted web traffic open to the public or internal clients.
- PostgreSQL / MySQL: TCP Ports 5432 and 3306, restricted exclusively to application server security groups.
- Custom App Server: TCP Port 8080 or 3000, accessible only from the Elastic Load Balancer (ELB).
Never expose database ports directly to the internet. Always route database traffic through internal subnets and tie the database security group source to your web or application tier security group IDs.
EC2 and Application Security
Implementing a secure multi-tier application involves chaining multiple security groups together. Imagine a standard three-tier web application consisting of a public Application Load Balancer, a private web/API tier, and an isolated database tier.
The load balancer security group accepts HTTP and HTTPS traffic from the public internet (0.0.0.0/0). The web tier security group accepts traffic solely from the load balancer security group on port 8080, rejecting all direct external connections. Finally, the database security group accepts database protocol traffic exclusively from the web tier security group.
This architecture ensures that even if an attacker compromises the public-facing load balancer, they cannot directly reach the underlying database or backend application nodes.
Least Privilege
Adopting least-privilege networking requires constant vigilance. Common pitfalls include leaving temporary diagnostic rules open indefinitely, using wildcard CIDRs for administrative access, and attaching overly permissive security groups to production instances.
To maintain hygiene, regularly audit your rules using AWS IAM Access Analyzer or custom scripts. Remove unused security groups and ensure that every rule has a descriptive name tag explaining its business purpose and owner. When troubleshooting connection failures, resist the temptation to open port 0.0.0.0/0 as a permanent fix; instead, inspect VPC Flow Logs to identify the exact packet drops.
Troubleshooting
When network traffic fails to reach your EC2 instance, diagnosing the issue requires a methodical checklist. First, verify that the security group inbound rule matches the correct source IP, protocol, and port. Next, check if outbound rules on the client or inbound rules on the destination block the return path.
Remember that security groups work alongside Network ACLs. If your security group rules are correct but traffic still fails, check the subnet NACLs, route tables, and OS-level firewalls (such as iptables or UFW) running inside the EC2 instance. Utilizing AWS VPC Flow Logs will reveal whether packets are being accepted or rejected at the network interface level.