Security Groups
What is a Security Group?
A Security Group (SG) is a virtual firewall that controls the inbound and outbound traffic of your EC2 instances. It is the first line of defense to secure your AWS resources.
┌─────────────────────────────────────────────────────────────┐
│ SECURITY GROUP │
├─────────────────────────────────────────────────────────────┤
│ │
│ Internet │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ SECURITY GROUP │ │
│ │ (Instance-level firewall) │ │
│ │ │ │
│ │ INBOUND RULES │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Port 22 (SSH) ← Admin only │ │ │
│ │ │ Port 80 (HTTP) ← Everyone │ │ │
│ │ │ Port 443 (HTTPS) ← Everyone │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ │ │
│ │ OUTBOUND RULES │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ All traffic → Allowed by default │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ EC2 Instance │ │
│ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Key Features
1. Stateful
┌─────────────────────────────────────────────────────────────┐
│ STATEFUL │
├─────────────────────────────────────────────────────────────┤
│ │
│ If an INBOUND connection is allowed, │
│ the OUTBOUND response is automatically allowed. │
│ │
│ Example: │
│ ┌─────────┐ ┌─────────────┐ │
│ │ Client │ ──── HTTP Request ────► │ EC2 │ │
│ │ │ (Port 80) │ (SG) │ │
│ │ │ ◄─── Response ──────── │ │ │
│ └─────────┘ (Automatic) └─────────────┘ │
│ │
│ You do NOT need to create an outbound rule │
│ for the response! │
│ │
└─────────────────────────────────────────────────────────────┘
2. Deny by Default (Inbound)
By default:
• INBOUND : Everything is BLOCKED ❌
• OUTBOUND : Everything is ALLOWED ✅
You must explicitly allow inbound traffic.
3. ALLOW Rules Only
Security Groups = ALLOW rules only
✅ You CAN: Allow SSH from 10.0.0.0/8
❌ You CANNOT: Block a specific IP
To block IPs → Use NACLs (VPC level)
Rule Structure
┌─────────────────────────────────────────────────────────────┐
│ RULE STRUCTURE │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┬───────────┬─────────────┬───────────────┐ │
│ │ Type │ Protocol │ Port │ Source │ │
│ ├────────────┼───────────┼─────────────┼───────────────┤ │
│ │ SSH │ TCP │ 22 │ 203.0.113.0/24│ │
│ │ HTTP │ TCP │ 80 │ 0.0.0.0/0 │ │
│ │ HTTPS │ TCP │ 443 │ 0.0.0.0/0 │ │
│ │ Custom │ TCP │ 3306 │ sg-xxxxx │ │
│ │ All ICMP │ ICMP │ All │ 10.0.0.0/16 │ │
│ └────────────┴───────────┴─────────────┴───────────────┘ │
│ │
│ Source can be: │
│ • CIDR : 0.0.0.0/0 (all), 10.0.0.0/8 (private) │
│ • Security Group : sg-xxxxxxxx │
│ • Prefix List : pl-xxxxxxxx │
│ │
└─────────────────────────────────────────────────────────────┘
Common Sources
CIDR Notation
┌─────────────────────────────────────────────────────────────┐
│ CIDR NOTATION │
├─────────────────────────────────────────────────────────────┤
│ │
│ 0.0.0.0/0 = Entire Internet (CAUTION!) │
│ ::/0 = All IPv6 │
│ │
│ 10.0.0.0/8 = Private network class A │
│ 172.16.0.0/12 = Private network class B │
│ 192.168.0.0/16 = Private network class C │
│ │
│ 203.0.113.25/32 = A single IP (your office) │
│ 10.0.1.0/24 = 256 addresses (a subnet) │
│ │
│ The /XX indicates how many bits are fixed: │
│ /32 = 1 IP, /24 = 256 IPs, /16 = 65536 IPs, /0 = all │
│ │
└─────────────────────────────────────────────────────────────┘
Referencing Another Security Group
┌─────────────────────────────────────────────────────────────┐
│ SECURITY GROUP REFERENCE │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ sg-web │ │ sg-database │ │
│ │ │ │ │ │
│ │ Inbound: │ │ Inbound: │ │
│ │ HTTP 80 0.0.0.0/0 │ MySQL 3306 │ │
│ │ │ │ Source: sg-web │◄─────┐ │
│ │ │ │ │ │ │
│ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │
│ │ │ Web App │──┼─────────┼─►│ MySQL │ │ │ │
│ │ └──────────┘ │ │ └──────────┘ │ │ │
│ │ │ │ │ │ │
│ └─────────────────┘ └─────────────────┘ │ │
│ │ │
│ Only instances in sg-web can access ─────┘ │
│ MySQL. No need to manage IPs! │
│ │
└─────────────────────────────────────────────────────────────┘
Best Practice
Reference Security Groups rather than IPs when possible. It's more dynamic and secure!
Common Ports
| Port | Service | When to open it |
|---|---|---|
| 22 | SSH | Admin access (restrict to your IP) |
| 80 | HTTP | Public websites |
| 443 | HTTPS | Secure websites |
| 3306 | MySQL | Database (internal only) |
| 5432 | PostgreSQL | Database (internal only) |
| 3389 | RDP | Windows Remote Desktop |
| 8080 | HTTP Alt | Applications, Tomcat |
| 27017 | MongoDB | Database (internal only) |
Configuration Examples
Public Web Server
┌─────────────────────────────────────────────────────────────┐
│ SG : sg-webserver-public │
├─────────────────────────────────────────────────────────────┤
│ │
│ INBOUND RULES : │
│ ┌──────────┬──────────┬──────────┬─────────────────────┐ │
│ │ Type │ Protocol │ Port │ Source │ │
│ ├──────────┼──────────┼──────────┼─────────────────────┤ │
│ │ HTTP │ TCP │ 80 │ 0.0.0.0/0 │ │
│ │ HTTPS │ TCP │ 443 │ 0.0.0.0/0 │ │
│ │ SSH │ TCP │ 22 │ 203.0.113.50/32 │ │
│ └──────────┴──────────┴──────────┴─────────────────────┘ │
│ │
│ OUTBOUND RULES : │
│ ┌──────────┬──────────┬──────────┬─────────────────────┐ │
│ │ All │ All │ All │ 0.0.0.0/0 │ │
│ └──────────┴──────────┴──────────┴─────────────────────┘ │
│ │
│ ⚠️ SSH restricted to office IP (203.0.113.50) │
│ │
└─────────────────────────────────────────────────────────────┘
Database (Internal)
┌─────────────────────────────────────────────────────────────┐
│ SG : sg-database-private │
├─────────────────────────────────────────────────────────────┤
│ │
│ INBOUND RULES : │
│ ┌──────────┬──────────┬──────────┬─────────────────────┐ │
│ │ Type │ Protocol │ Port │ Source │ │
│ ├──────────┼──────────┼──────────┼─────────────────────┤ │
│ │ MySQL │ TCP │ 3306 │ sg-webserver │ │
│ └──────────┴──────────┴──────────┴─────────────────────┘ │
│ │
│ OUTBOUND RULES : │
│ ┌──────────┬──────────┬──────────┬─────────────────────┐ │
│ │ All │ All │ All │ 0.0.0.0/0 │ │
│ └──────────┴──────────┴──────────┴─────────────────────┘ │
│ │
│ ✅ Only accessible from the web servers' SG │
│ ❌ No direct access from the Internet │
│ │
└─────────────────────────────────────────────────────────────┘
Common Errors
1. SSH Open to Everyone ❌
BAD:
SSH (22) - Source: 0.0.0.0/0
↓
⚠️ Anyone can attempt to connect!
Guaranteed brute-force attacks.
GOOD:
SSH (22) - Source: 203.0.113.50/32 (your IP)
or
SSH (22) - Source: 10.0.0.0/8 (private network + VPN)
2. Exposed Database ❌
BAD:
MySQL (3306) - Source: 0.0.0.0/0
↓
⚠️ Database publicly accessible!
Major security risk.
GOOD:
MySQL (3306) - Source: sg-application
↓
✅ Only accessible from application servers
3. Too Many Rules ❌
BAD:
A SG with 50 different rules
↓
⚠️ Difficult to audit and maintain
Risk of errors
GOOD:
Multiple SGs with clear roles:
- sg-web-public (HTTP/HTTPS)
- sg-admin (SSH/RDP)
- sg-database (internal MySQL)
Best Practices
1. Principle of Least Privilege
Allow ONLY what is necessary.
✅ Good : Port 443 from 0.0.0.0/0 (public HTTPS required)
❌ Bad : All ports from 0.0.0.0/0
2. Use Descriptive Names
Recommended names:
• sg-web-public-prod
• sg-database-internal-prod
• sg-admin-ssh-restricted
• sg-loadbalancer-public
3. Document Your Rules
Add descriptions to each rule:
Port 443 - "Public HTTPS for website"
Port 22 - "Admin SSH from Paris office only"
Port 3306 - "MySQL for backend only"
4. Audit Regularly
Questions to ask:
• Are there unnecessary rules with 0.0.0.0/0?
• Are any DB ports publicly exposed?
• Are SSH rules too permissive?
• Are there obsolete rules?
Security Group vs NACL
┌─────────────────────────────────────────────────────────────┐
│ SECURITY GROUP vs NACL │
├─────────────────────────────────────────────────────────────┤
│ │
│ Criteria Security Group NACL │
│ ────────────────────────────────────────────────────── │
│ Level Instance Subnet │
│ State Stateful Stateless │
│ Rules ALLOW only ALLOW and DENY │
│ Evaluation All rules Priority order │
│ Default Deny inbound Allow all │
│ Change Immediate Immediate │
│ │
│ Use SG for: Fine-grained instance control │
│ Use NACL for: Blocking IPs, defense in depth │
│ │
└─────────────────────────────────────────────────────────────┘
Summary
| Concept | Description |
|---|---|
| Security Group | Instance-level firewall |
| Stateful | Responses automatically allowed |
| Inbound | Blocked by default |
| Outbound | Allowed by default |
| ALLOW only | No DENY rules |
| SG Reference | Use an SG as a source |
Validation Quiz
- What does "stateful" mean for a Security Group?
- What is the default policy for inbound traffic?
- Can you block a specific IP with a Security Group?
- What does 0.0.0.0/0 as a source mean?
- Why reference an SG rather than an IP?
- What is the default port for SSH?
Next section: Lab: EC2 Architecture