intermediate~2h

EC2 Security Groups & Networking

How traffic to and from an EC2 instance is controlled — Security Groups, public vs private IPs, and the VPC context an instance lives in.

Want a visual for this topic?

Generate a diagram tailored to EC2 Security Groups & Networking — the AI picks whichever visual (architecture, flowchart, ER diagram, etc.) best fits this specific AWS concept.

Sign in to generate a visual →
2
Subtopics

🎓 Learning objectives

  • Explain how Security Groups differ from a traditional firewall (stateful vs stateless)
  • Configure a Security Group that follows least-privilege networking
  • Explain the difference between a public IP, private IP, and Elastic IP
  • Explain why placing a database in a private subnet, not a public one, matters

What is it?

EC2 networking security centers on Security Groups — virtual firewalls attached to instances (or more precisely, to their network interfaces) that control what inbound and outbound traffic is allowed, combined with the VPC networking context (public vs private subnets, IP addressing) an instance is launched into.

Why it exists

An internet-reachable server with no traffic restrictions is trivially discoverable and attackable within minutes of being launched — automated internet-wide scanners probe every public IP constantly. Security Groups exist to enforce least-privilege network access: by default, a new Security Group denies all inbound traffic, and you explicitly allow only the specific ports and sources actually needed, dramatically shrinking the attack surface compared to a default-open posture.

Problem it solves

It solves the default-exposure problem (deny-by-default means a misconfiguration is far more likely to accidentally block legitimate traffic — annoying but safe — than to accidentally expose something), the shared-responsibility network security problem (AWS secures the physical network; you're responsible for configuring which traffic your instances accept), and the blast-radius problem (a database instance that only accepts connections from your application tier's Security Group, not from the whole internet, limits what an attacker who compromises something else can reach).

Intuition

A Security Group is like a guest list at a private event's door: by default nobody gets in (deny-by-default), and you add specific names (or specific traffic rules — source IP/Security Group, port, protocol) to the list. It's fundamentally different from a traditional network firewall's typical stateless rule list, because a Security Group is stateful: if you let a request in, the response is automatically allowed back out, without needing a matching outbound rule — like a guest list that also automatically lets a guest leave without a separate 'exit' authorization.

Analogy

A hotel key-card system for a specific floor: guests (traffic) need a card programmed for that floor (an inbound rule matching their source and the port they're trying to reach) to even get off the elevator; once inside their room, they can freely use the in-room phone to call outside (outbound is typically allowed by default) without needing a separate card swipe for that.

Technical explanation

Security Groups are stateful and operate at the instance/ENI (Elastic Network Interface) level: you can reference another Security Group as the 'source' of an inbound rule (instead of an IP range), which is the recommended pattern for internal service-to-service traffic — e.g. a database's Security Group allows inbound port 5432 only from the application tier's Security Group, so it doesn't matter how many application instances there are or what their IPs are, since Security Group membership (not IP) is what's being checked. This differs from Network ACLs (NACLs), a second, coarser layer of VPC network control operating at the subnet level, which are stateless (you must explicitly allow both inbound and outbound directions) and evaluated in numbered rule order with explicit Allow/Deny — most teams leave NACLs at their permissive default and do the real access control at the Security Group layer, reserving NACLs for broad subnet-level blocking (e.g. blocking a known-malicious IP range).

Architecture

A typical three-tier setup: a Load Balancer's Security Group allows inbound 443 from 0.0.0.0/0 (the public internet); the application tier's Security Group allows inbound on its app port only from the Load Balancer's Security Group (not from the raw internet); the database tier's Security Group allows inbound on its DB port only from the application tier's Security Group. The database also typically lives in a private subnet with no route to an internet gateway at all, so even a Security Group misconfiguration wouldn't make it internet-reachable — defense in depth across both the routing layer (subnet) and the firewall layer (Security Group).

Workflow

  1. Identify what traffic actually needs to reach this instance and from where (a specific IP, a load balancer, another tier's Security Group). 2) Create a Security Group with only those inbound rules — never start from 'allow everything and lock it down later.' 3) Reference other Security Groups as sources for internal service-to-service traffic instead of hardcoding IP ranges. 4) Place instances that don't need direct internet exposure (databases, internal services) in private subnets with no route to an internet gateway. 5) Periodically audit Security Group rules for overly broad entries (0.0.0.0/0 on a sensitive port) using AWS Config or manual review.

Example

A web application's database instance has a Security Group allowing inbound port 5432 only from the 'app-tier-sg' Security Group, and lives in a private subnet with no internet gateway route. Even if an attacker compromises a public-facing web server that lives in the public subnet, they cannot directly reach the database over the network unless they've also compromised something inside the app tier's Security Group — the network topology itself, not just application-level auth, limits the blast radius.

Real-world usage

AWS's own reference architectures for virtually every workload type show this exact pattern — public-facing tier open to the internet, application tier reachable only from the public tier, data tier reachable only from the application tier — and it's one of the most heavily tested scenario patterns on the SAA-C03 exam, usually phrased as 'how would you secure network access to a database that should only be reachable by the application servers.'

Trade-offs

Tighter Security Group rules (specific sources, specific ports, Security-Group-based sources instead of IP ranges) are more secure but require more upfront thought and occasionally more maintenance as architecture changes; broad rules (0.0.0.0/0 on many ports) are faster to set up during development but leave a much larger attack surface in production. The standard practice is to be permissive during early local/dev iteration if genuinely needed, but tighten to least-privilege before anything touches real user data or goes to production.

Visual explanation

Picture an EC2 instance as a house. The Security Group is the set of rules for its front door: 'Allow port 22 (SSH) only from 203.0.113.5 (my home IP)', 'Allow port 443 (HTTPS) from anywhere (0.0.0.0/0)', 'Allow port 3306 (MySQL) only from the Application-Tier Security Group, not from any raw IP at all.' Traffic that doesn't match an explicit Allow rule is rejected, silently, with no response sent back — which is why a misconfigured Security Group typically causes a connection to hang/time out rather than an explicit 'connection refused.'

Advantages

  • Deny-by-default posture means accidental exposure requires an explicit misconfiguration, not just an omission

  • Referencing Security Groups (not IP ranges) as traffic sources scales cleanly as instances are added/removed/replaced by Auto Scaling

  • Stateful behavior (return traffic auto-allowed) means simpler rule sets than a fully stateless firewall would require

  • Free — Security Groups carry no additional cost beyond the instance itself

Disadvantages

  • Easy to accumulate overly broad rules over time (0.0.0.0/0 added 'temporarily' and never removed) without auditing

  • A large number of Security Groups and rules across a big account can become hard to reason about without tooling/documentation

  • Security Groups alone don't provide intrusion detection or traffic inspection — they only allow/deny based on IP/port/protocol, not payload content

  • Debugging 'why can't service A reach service B' requires checking Security Groups, NACLs, subnet routing, and the application itself — network connectivity issues can have several possible causes

Common mistakes

  • Allowing SSH (port 22) or RDP (port 3389) from 0.0.0.0/0 instead of a specific known IP range or a bastion host — one of the most common real-world EC2 misconfigurations found by automated security scanners

  • Using IP-range-based rules for internal service-to-service traffic instead of referencing the other tier's Security Group, which breaks or requires manual updates whenever instances are replaced

  • Putting a database in a public subnet 'because it was easier to connect to for debugging' and never moving it to a private subnet before launch

  • Confusing Security Groups (stateful, instance-level) with NACLs (stateless, subnet-level) and expecting NACL-like explicit outbound rules to be necessary on a Security Group

In the AWS Console

  1. 1

    AWS Console → EC2 → Security Groups → Create security group

    Name it clearly by tier (e.g. 'app-tier-sg'), and add inbound rules one at a time, choosing 'Custom' source and referencing another Security Group where the traffic comes from an internal tier rather than typing an IP.

    Naming Security Groups by their role (not a generic 'sg-1') makes later audits dramatically easier.

  2. 2

    EC2 → Security Groups → [your SG] → Inbound rules → Edit inbound rules

    For SSH access, set Source to 'My IP' (auto-detects your current public IP) rather than Anywhere-IPv4.

    Revisit this if your IP changes (e.g. different network) — a common source of 'I can't SSH in anymore' confusion after a Security Group was scoped to a specific IP.

  3. 3

    VPC → Subnets → [your subnet] → Route table tab

    Verify a private subnet's route table has no route to an Internet Gateway (0.0.0.0/0 → igw-xxxx) — only a route to a NAT Gateway if outbound internet access is still needed.

    This is the routing-layer check that confirms a subnet is genuinely private, independent of whatever Security Group rules say.

🎤 Interview questions

What's the difference between a Security Group and a Network ACL? (Listen for: Security Group = stateful, instance-level, only Allow rules; NACL = stateless, subnet-level, explicit Allow and Deny rules evaluated in order.)

Why would you reference another Security Group as a rule's source instead of an IP range? (Listen for: scales automatically as instances in that tier change — no manual IP updates needed, and it's tied to identity/role, not a potentially spoofable IP.)

How would you secure a database so only your application servers can reach it? (Listen for: Security Group inbound rule allowing the DB port only from the app tier's Security Group, plus placing the database in a private subnet with no internet gateway route.)

A new EC2 instance can't be reached on port 443 from the internet — what would you check? (Listen for: Security Group inbound rule for 443, NACL rules on the subnet, whether the subnet has a route to an Internet Gateway, whether the instance has a public IP, and the application actually listening on that port.)

📂 Subtopics

💬 Deep Dive with AI

Related concepts

ec2-fundamentalsiam-fundamentalsauto-scaling-load-balancing

Next Step

Continue to Auto Scaling & Elastic Load Balancing