Course outline

3.5

Security Groups vs NACLs and Ephemeral Ports

Stateful vs stateless filtering, rule order, ephemeral ports, a three-tier rule set, and timeout vs connection refused.

34 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain the two firewall layers of a VPC and where each one sits.
  • Write security group rules, including rules that reference other security groups.
  • Write network ACL rules, apply “first match wins”, and avoid the custom-NACL and rule-order traps.
  • Explain stateful vs stateless filtering and add the ephemeral-port rules that stateless filtering needs.
  • Build a complete rule set for a web tier and a database tier, and debug “timeout” vs “connection refused”.

#Two layers of firewall

Every packet that enters or leaves an instance in a VPC can be filtered twice:

  • A network ACL (NACL) at the subnet boundary. It checks every packet entering or leaving the subnet.
  • A security group (SG) around each instance (strictly, around each network interface). It checks packets entering or leaving that one instance.

Traffic from the internet to a web server passes the subnet’s network ACL first, then the instance’s security group. The reply leaves through the security group and then the network ACL.

#Security groups

A security group is a set of allow rules. Each rule names a protocol, a port range and a source (for inbound) or destination (for outbound). The source can be:

  • a CIDR block, for example 0.0.0.0/0 (anyone) or 203.0.113.25/32 (one address);
  • another security group, meaning “any network interface that has that security group attached”;
  • a managed prefix list (a named list of CIDR blocks).

How security groups behave:

BehaviourDetail
Allow rules onlyThere is no “deny” rule. Anything not allowed is dropped.
StatefulIf a request is allowed in, its reply is allowed out automatically, and vice versa. Outbound rules are not even consulted for replies.
All rules evaluatedNo order, no numbers: if any rule allows the traffic, it is allowed.
Defaults for a new groupNo inbound rules (all inbound blocked) and one outbound rule allowing all traffic.
Attached to network interfacesAn instance can have several security groups (5 per interface by default); their rules are combined. One group can be attached to many instances.
ScopeA security group belongs to one VPC in one Region.
Changes are immediateEditing a rule affects existing instances right away; no restart.
Quotas60 inbound and 60 outbound rules per group by default (adjustable).

Security groups operate outside the instance: blocked traffic never reaches the operating system, so the instance cannot see it or log it.

#Referencing other security groups

The most powerful feature is using a security group as the source of a rule. Instead of “allow port 3306 from 10.0.1.0/24”, you write “allow port 3306 from sg-web”. Then:

  • any instance with sg-web attached can connect, wherever it is in the VPC;
  • new web servers launched by an Auto Scaling group are allowed automatically;
  • nothing else in the same subnet is allowed, even with a neighbouring address.

This is how tiers are chained: load balancer → web servers → database, each group allowing only the group in front of it. It works within a VPC, and across peered VPCs in the same Region.

#Ports you must recognise

PortProtocolUsed for
22SSHLog in to a Linux instance; also SFTP (file transfer over SSH)
21FTPUnencrypted file transfer
80HTTPUnencrypted websites
443HTTPSEncrypted websites and APIs
3389RDPRemote Desktop to a Windows instance
3306MySQL / MariaDB / Aurora MySQLDatabase connections
5432PostgreSQL / Aurora PostgreSQLDatabase connections

A real example: a WordPress site on one EC2 instance. Everyone must see the site, so the security group allows HTTP (80) and HTTPS (443) from 0.0.0.0/0. You also need SSH (22) to maintain the server, but only from your own home or office address, for example 203.0.113.25/32, never from 0.0.0.0/0. On the exam, port 22 open to 0.0.0.0/0 is always the “bad practice” option.

#Network ACLs

A network ACL is a numbered list of allow and deny rules applied at the subnet boundary.

BehaviourDetail
Allow and denyRules can explicitly deny, which makes NACLs the tool for blocking a specific IP address or range.
StatelessNothing is remembered. A reply is a new packet and must match its own rule in the other direction.
Numbered, first match winsRules are checked from the lowest number up (1 to 32766). The first rule that matches decides, and later rules are never read.
Final catch-allEvery NACL ends with a * rule that denies anything no numbered rule matched. It cannot be edited or removed.
One per subnetA subnet is associated with exactly one NACL; one NACL can serve many subnets. A new subnet uses the VPC’s default NACL.
Numbering habitAWS suggests steps of 100 (100, 200, 300…) so you can insert rules in between later.
Quotas20 rules per direction by default (adjustable to 40).

Network ACLs can only reference CIDR blocks, never security groups.

#Default vs custom network ACLs

This is one of the most frequently tested traps:

  • The default NACL (created with every VPC) allows all inbound and all outbound traffic.
  • A custom NACL you create denies all inbound and all outbound traffic until you add rules.

Network ACL rules: first match wins

The same two rules in two orders. Watch the scanner stop at the first rule that matches.

Scenario

Web subnet
Attacker203.0.113.50
Customer198.51.100.20
Network ACL
Web server
TCP 80

Inbound rules (lowest number first)

Rule #TypeSourceAction
100All traffic203.0.113.50/32Deny
200TCP 800.0.0.0/0Allow
*All traffic0.0.0.0/0Deny
Step 1 of 3
1

The attacker’s packet arrives. Rule 100 is checked first: source 203.0.113.50/32 matches.

#Stateful vs stateless and ephemeral ports

Every TCP connection has two ends, and both use a port:

  • The server listens on a well-known port: 80, 443, 3306…
  • The client uses a temporary port chosen by its operating system for this one connection: an ephemeral port.

So a browser on 198.51.100.20 might send 198.51.100.20:50105 → 10.0.1.10:80, and the reply travels 10.0.1.10:80 → 198.51.100.20:50105. The reply goes to the client’s ephemeral port.

A stateful security group handles this for you. A stateless network ACL does not: its outbound rules must allow the replies to the clients’ ephemeral ports, and if your servers are the clients (calling a database or an API), its inbound rules must allow the replies coming back to their ephemeral ports.

Ephemeral port ranges differ by system:

ClientEphemeral range
Most Linux kernels (including Amazon Linux)32768–60999
Windows Server 2008 and later, IANA recommendation49152–65535
AWS NAT gateway, Elastic Load Balancing, Lambda1024–65535

Because a public web server’s clients can be anything, the usual rule is TCP 1024–65535, which covers all of them.

One request, two firewalls, both directions

A browser asks a web server for a page. The network ACL checks at the subnet edge, the security group at the instance.

Scenario

Browser198.51.100.20
Network ACLsubnet edge, stateless
Security groupinstance, stateful
Web server10.0.1.10
TCP 50105 → 80
Step 1 of 7
1

The browser picks a random source port (an ephemeral port, here 50105) and connects to port 80. The packet reaches the subnet boundary first.

Self-checkQuestion

You must block a single malicious IP address from reaching every instance in a subnet. What should you use?

#Security groups vs network ACLs

Security groupNetwork ACL
Applies toInstances / network interfaces it is attached toEvery resource in the associated subnets
RulesAllow onlyAllow and deny
StateStateful: replies allowed automaticallyStateless: replies need their own rules
EvaluationAll rules, no orderBy number, lowest first, first match wins
SourcesCIDR blocks, other security groups, prefix listsCIDR blocks only
DefaultNew group: no inbound, all outboundDefault NACL: allow all. Custom NACL: deny all
Typical useThe main, fine-grained control for every resourceCoarse subnet guardrails and blocking specific addresses

In practice, most designs put precise rules in security groups and keep network ACLs simple (often the default), adding NACL rules for subnet-wide guardrails or to block known bad addresses.

#A complete two-tier rule set

A classic exam scenario: VPC 10.0.0.0/16, a public web subnet 10.0.1.0/24 serving HTTP/HTTPS, and a private database subnet 10.0.2.0/24 running MySQL on port 3306.

Web subnet NACL, inbound

Rule #TypeSourceActionPurpose
50All traffic203.0.113.50/32DenyBlock a known bad actor
100TCP 800.0.0.0/0AllowHTTP visitors
110TCP 4430.0.0.0/0AllowHTTPS visitors
120TCP 1024–6553510.0.2.0/24AllowReplies from the database
*All traffic0.0.0.0/0DenyEverything else

Web subnet NACL, outbound

Rule #TypeDestinationActionPurpose
100TCP 1024–655350.0.0.0/0AllowReplies to browsers (ephemeral ports)
110TCP 330610.0.2.0/24AllowQueries to the database subnet only
*All traffic0.0.0.0/0DenyEverything else

Database subnet NACL, inbound

Rule #TypeSourceActionPurpose
100TCP 330610.0.1.0/24AllowDatabase connections from the web subnet only
*All traffic0.0.0.0/0DenyThe internet and everything else

Database subnet NACL, outbound

Rule #TypeDestinationActionPurpose
100TCP 1024–6553510.0.1.0/24AllowQuery results back to the web servers
*All traffic0.0.0.0/0DenyNothing leaves for the internet

A web tier and a database tier, rule by rule

VPC 10.0.0.0/16 · web subnet 10.0.1.0/24 · database subnet 10.0.2.0/24 (MySQL on 3306). Each step shows the rule that decided.

Scenario

VPC10.0.0.0/16
Web subnet10.0.1.0/24
DB subnet10.0.2.0/24
Visitor198.51.100.20
Bad actor203.0.113.50
Web server10.0.1.10
MySQL10.0.2.20
TCP → 443

Web NACL · inbound

Rule #TypeSource / destinationAction
50All traffic203.0.113.50/32Deny
100TCP 800.0.0.0/0Allow
110TCP 4430.0.0.0/0Allow
120TCP 1024–6553510.0.2.0/24Allow
*All traffic0.0.0.0/0Deny
Step 1 of 5
1

The visitor’s HTTPS request enters the web subnet. Web inbound rules: 50 does not match this source; 100 is port 80, no; 110 allows TCP 443. Allow.

Three things worth noticing in this design:

  • Web outbound rule 110 is redundant: rule 100 (1024–65535 to anywhere) already covers 3306 and is checked first. It does no harm and documents intent, but it is not what allows the traffic.
  • Rule 50 blocks all traffic, not just port 80. A deny on port 80 alone would still let the attacker in on 443 through rule 110.
  • The web servers cannot start outbound connections to the internet on 80/443 (for example, to download updates): outbound only allows high ports. That is fine for a strict design, but updates would then need a proxy, a NAT path with matching rules, or VPC endpoints.

The matching security groups are simpler, because they are stateful and can reference each other:

Security groupInbound rule
sg-webTCP 80 and 443 from 0.0.0.0/0 (or from the load balancer’s security group, if there is one)
sg-dbTCP 3306 from sg-web

#Try it yourself

# Security groups: web allows HTTPS from anywhere, db allows MySQL only from the web group
WEB=$(aws ec2 create-security-group --group-name web --description web --vpc-id $VPC --query GroupId --output text)
DB=$(aws ec2 create-security-group --group-name db --description db --vpc-id $VPC --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $WEB --protocol tcp --port 443 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id $DB --protocol tcp --port 3306 --source-group $WEB

# Network ACL: block one address with a low rule number
aws ec2 create-network-acl-entry --network-acl-id $NACL --ingress --rule-number 50 \
  --protocol -1 --cidr-block 203.0.113.50/32 --rule-action deny

# Debug from a client: timeout vs refused
curl -m 5 http://203.0.113.25/     # "timed out" → firewall; "Connection refused" → no app listening

#Summary

Key takeaways

  • A VPC has two filters: network ACLs at the subnet boundary and security groups at each instance.
  • Security groups: allow rules only, stateful, all rules evaluated together, can reference other security groups; new groups block all inbound and allow all outbound.
  • Network ACLs: allow and deny, stateless, numbered and first match wins, end with a * deny, CIDR blocks only, one per subnet. Use them to block specific IPs.
  • Default NACL allows everything; a new custom NACL denies everything.
  • Replies go to the client’s ephemeral port. Stateless NACLs need explicit rules for them; 1024–65535 covers every client type (Linux uses 32768–60999, Windows 49152–65535).
  • “Request arrives, reply never does” → network ACL. Timeout → a firewall; connection refused → no application listening.
  • Chain tiers with security groups that reference each other (sg-db allows 3306 from sg-web); never open a database port to 0.0.0.0/0.