Skip to main content

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​

PortServiceWhen to open it
22SSHAdmin access (restrict to your IP)
80HTTPPublic websites
443HTTPSSecure websites
3306MySQLDatabase (internal only)
5432PostgreSQLDatabase (internal only)
3389RDPWindows Remote Desktop
8080HTTP AltApplications, Tomcat
27017MongoDBDatabase (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​

ConceptDescription
Security GroupInstance-level firewall
StatefulResponses automatically allowed
InboundBlocked by default
OutboundAllowed by default
ALLOW onlyNo DENY rules
SG ReferenceUse an SG as a source

Validation Quiz​

  1. What does "stateful" mean for a Security Group?
  2. What is the default policy for inbound traffic?
  3. Can you block a specific IP with a Security Group?
  4. What does 0.0.0.0/0 as a source mean?
  5. Why reference an SG rather than an IP?
  6. What is the default port for SSH?

Next section: Lab: EC2 Architecture