I added a security group rule to allow HTTPS traffic from my load balancer to backend instances, but traffic still didn’t flow. I triple-checked the SG rule—it was clearly allowing port 443 inbound—yet the connection timed out. After an hour of debugging, I realized the issue was in the Network ACL on the subnet, which was blocking the return traffic on ephemeral ports. I had been so focused on the security group that I completely missed the NACL configuration. In this post, I’ll walk through exactly what causes this and how to fix it.

The Problem

Traffic is being blocked somewhere in your VPC, but you can’t figure out if it’s a security group or a Network ACL. You added security group rules but traffic is still blocked. Or traffic flows in one direction but not the other. Understanding when and how each filter applies is critical.

Here’s what you might see when testing connectivity:

Security Group SG-A has rule: Allow port 443 from SG-B inbound
But traffic still times out after 30 seconds
NACL on the subnet has rule: Allow port 443 inbound
But missing rules for ephemeral port range 1024-65535 outbound
Component Behavior
Security Group Stateful — allow inbound, return traffic automatically allowed
Network ACL Stateless — must explicitly allow both inbound AND outbound, including ephemeral ports
Both Active Traffic must pass BOTH filters — either one can block
Rule Evaluation SG: no priority number; NACL: lowest rule number wins

Why Does This Happen?

  • Misunderstanding stateful vs stateless filtering: Security groups are stateful. If you allow port 443 inbound, return traffic on that same connection is automatically allowed. NACLs are stateless. If you allow port 443 inbound, you must separately allow the client’s ephemeral ports (1024-65535) on the outbound direction for responses.

  • Forgetting ephemeral port ranges in NACL outbound rules: This is the most common mistake. You allow inbound port 443 (HTTPS), but NACLs require you to also allow outbound ephemeral ports. Without it, the server can’t send responses back to the client.

  • Both filters active: Most engineers think of one or the other, but both are always active. Traffic must pass the SG AND the NACL. If either blocks, traffic fails.

  • NACL rule evaluation order by rule number: NACLs evaluate rules in order by their rule number (lowest first). If you have rule 90 (deny all) before rule 100 (allow specific), traffic gets denied. Rule numbering matters.

  • Checking only inbound when the issue is outbound: For TCP connections, traffic flows in both directions. You check the inbound rule and it looks correct, but you forget to check the outbound rule on the other side of the connection.

The Fix

First, use AWS’s Reachability Analyzer to diagnose the issue systematically:

aws ec2 create-network-insights-path \
  --source eni-0a1b2c3d4e5f6g7h8 \
  --destination eni-0x1y2z3a4b5c6d7e8 \
  --protocol tcp \
  --destination-port 443 \
  --output text

This returns a path ID. Now run the analysis:

aws ec2 start-network-insights-analysis \
  --network-insights-path-id nip-0a1b2c3d4e5f6g7h8 \
  --output text

Wait a moment, then check the results:

aws ec2 describe-network-insights-analyses \
  --network-insights-analysis-ids nia-0a1b2c3d4e5f6g7h8 \
  --query 'NetworkInsightsAnalyses[0].[NetworkPathFound,NetworkInsightsAnalysisFindings]' \
  --output text

The output will tell you exactly which component is blocking: SG, NACL, route table, or IGW.

Manual Check: Security Group

Get the instance’s security groups:

aws ec2 describe-instances \
  --instance-ids i-0a1b2c3d4e5f6g7h8 \
  --query 'Reservations[0].Instances[0].SecurityGroups[*].[GroupId,GroupName]' \
  --output table

Check the inbound rules:

aws ec2 describe-security-groups \
  --group-ids sg-0a1b2c3d4e5f6g7h8 \
  --query 'SecurityGroups[0].IpPermissions[*].[FromPort,ToPort,IpProtocol,IpRanges[*].CidrIp,UserIdGroupPairs[*].GroupId]' \
  --output table

Check the outbound rules (important for the return path):

aws ec2 describe-security-groups \
  --group-ids sg-0a1b2c3d4e5f6g7h8 \
  --query 'SecurityGroups[0].IpPermissionsEgress' \
  --output table

If inbound is missing, add a rule:

aws ec2 authorize-security-group-ingress \
  --group-id sg-0a1b2c3d4e5f6g7h8 \
  --protocol tcp \
  --port 443 \
  --source-group sg-0x1y2z3a4b5c6d7e8

Manual Check: Network ACL

Find the NACL for the subnet:

aws ec2 describe-network-acls \
  --filters "Name=association.subnet-id,Values=subnet-0a1b2c3d4e5f6g7h8" \
  --query 'NetworkAcls[0].[NetworkAclId,Entries[*].[RuleNumber,Protocol,RuleAction,CidrBlock,PortRange]]' \
  --output table

Look for rules allowing port 443 inbound and ephemeral ports (1024-65535) outbound. If they’re missing, add them:

aws ec2 create-network-acl-entry \
  --network-acl-id acl-0a1b2c3d4e5f6g7h8 \
  --rule-number 100 \
  --protocol tcp \
  --port-range From=443,To=443 \
  --cidr-block 10.0.0.0/16 \
  --ingress

aws ec2 create-network-acl-entry \
  --network-acl-id acl-0a1b2c3d4e5f6g7h8 \
  --rule-number 110 \
  --protocol tcp \
  --port-range From=1024,To=65535 \
  --cidr-block 10.0.0.0/16 \
  --egress

How to Run This

  1. Use Reachability Analyzer first — it pinpoints the exact component blocking traffic.
  2. Check security group inbound rules match the traffic source.
  3. Check security group outbound rules if return traffic is blocked.
  4. Check NACL inbound rules for the destination subnet.
  5. Check NACL outbound rules and ensure ephemeral port range (1024-65535) is allowed.
  6. Remember: both must allow traffic, and NACL rules are evaluated by rule number.

Is This Safe?

Yes, adding security group and NACL rules is safe. These are standard networking configurations. Just ensure you understand the source/destination IPs and protocols you’re allowing.

Key Takeaway

Security Groups and NACLs are different beasts. SGs are stateful; NACLs are stateless and require explicit ephemeral port rules. Both must allow traffic for connectivity to work. Use Reachability Analyzer to quickly identify which component is blocking—it’s faster and more reliable than manual checking.


Have questions or ran into a different networking issue? Connect with me on LinkedIn or X.