Security group egress rules block ECS task containers from accessing external APIs

Our ECS Fargate tasks are failing to reach external third-party APIs despite having what we believe are correct security group egress rules configured. The tasks run in private subnets and we’re getting connection timeout errors.

Current security group egress configuration:


Type: Custom TCP
Port: 443
Destination: 0.0.0.0/0

The tasks need to call external payment processing APIs and weather data services. We’ve verified the APIs are accessible from our VPC using a bastion host, but ECS tasks consistently fail with timeout errors after 30 seconds. Our route table for the private subnet points to a NAT Gateway, and we’ve confirmed the NAT Gateway is in an available state in a public subnet. Is there something we’re missing in the network configuration or security group rules?

Can you verify that the NAT Gateway’s Elastic IP is actually being used for outbound traffic? Check your VPC flow logs to see if traffic is even reaching the NAT Gateway. Also, does the public subnet where your NAT Gateway resides have an Internet Gateway attached to the VPC?

Complete Solution - Network Configuration for ECS External API Access

Your issue stems from incomplete route table configuration across your availability zones. Here’s the complete solution addressing all three key areas:

Security Group Egress Rules: Your egress rule is correct, but ensure it’s attached to the ECS task’s security group (not the service security group). Verify with:


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

You need HTTPS (443) egress to 0.0.0.0/0 for external APIs. If calling HTTP endpoints, also add port 80 egress.

NAT Gateway Setup: You need one NAT Gateway per availability zone for fault tolerance. Each NAT Gateway must:

  • Reside in a PUBLIC subnet (one with IGW route)
  • Have an Elastic IP allocated
  • Be in an available state

Create NAT Gateways for each AZ:


aws ec2 create-nat-gateway \
  --subnet-id subnet-public-1a \
  --allocation-id eipalloc-xxxxx

Route Table Configuration (The Root Cause): This is where your problem lies. Each private subnet needs its own route table pointing to the NAT Gateway in the SAME availability zone:

Private Subnet 1a Route Table:

  • Local route (automatic)
  • 0.0.0.0/0 → NAT Gateway in AZ 1a

Private Subnet 1b Route Table:

  • Local route (automatic)
  • 0.0.0.0/0 → NAT Gateway in AZ 1b

Your 60% success rate indicates some subnets have correct routes while others don’t. Verify each private subnet’s route table association:


aws ec2 describe-route-tables \
  --filters Name=association.subnet-id,Values=subnet-xxxxx

Verification Steps:

  1. Enable VPC Flow Logs if not already enabled
  2. Check flow logs for ACCEPT entries on traffic from ECS task IPs to external IPs
  3. Verify NAT Gateway metrics in CloudWatch show active connections
  4. Test from within a task using curl -v https://api.external.com to see exact failure point

Common Pitfalls to Avoid:

  • Don’t attach security groups to NAT Gateways (they don’t support them)
  • Don’t use the same route table for public and private subnets
  • Don’t point all AZs to a single NAT Gateway (creates cross-AZ traffic charges and single point of failure)
  • Ensure ECS task execution role has permissions if pulling images from ECR

After implementing these changes, all ECS tasks should successfully reach external APIs regardless of which subnet/AZ they launch in.

I checked the VPC flow logs and I’m seeing REJECT entries for traffic from the ECS task IPs. The Internet Gateway is attached to the VPC. Could this be a route table association issue? I’m not entirely clear on which route table should be associated with the private subnets.