I launched an EC2 instance in what I thought was a public subnet with an Internet Gateway attached to the VPC, assigned a public IP, and expected it to reach the internet immediately. But when I SSH’d in and tried curl https://aws.amazon.com, the request timed out. The Internet Gateway was there, the public IP was assigned, yet the instance couldn’t reach anything outside the VPC. In this post, I’ll walk through exactly what causes this and how to fix it.
The Problem
Your EC2 instance has a public IP or Elastic IP assigned, the VPC has an Internet Gateway attached, but the instance can’t reach the internet. SSH and HTTP/HTTPS connections from the instance all time out. When you run curl or wget, you get connection refused or timeout errors.
Here’s what the error looks like from inside the EC2 instance:
$ curl https://aws.amazon.com
curl: (7) Failed to connect to aws.amazon.com port 443: Connection timed out
$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
--- 8.8.8.8 statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 45ms
| Issue | Description |
|---|---|
| No Internet Connectivity from Instance | Instance with public IP can’t reach external IPs or domains |
| Curl/Wget Timeout | Connection attempts to external services time out |
| DNS Resolution Fails | Even internal DNS queries fail or resolve incorrectly |
| Internet Gateway Present but Unused | IGW attached to VPC but not in the traffic path |
Why Does This Happen?
-
Route table doesn’t have a route to the Internet Gateway: The subnet’s route table must have a route to
0.0.0.0/0(all traffic) pointing to the Internet Gateway ID. Without this route, traffic destined for the internet gets dropped (blackholed). -
Instance doesn’t have a public IP or Elastic IP: Even with an IGW and correct routes, the instance needs a public IP. Private IPs can’t route to the internet; AWS needs a public IP to map return traffic back.
-
Security group outbound rules are too restrictive: By default, security groups allow all outbound traffic. But if outbound rules were modified to deny or restrict, you’ll lose internet connectivity even with correct routing.
-
Network ACL has a deny rule or missing ephemeral ports: NACLs evaluate rules in order. If an outbound rule is placed before the allow rule, traffic gets blocked. Also, ephemeral port ranges (1024-65535) must be allowed for return traffic.
-
Instance’s OS firewall blocking outbound: iptables on Linux or Windows Firewall on EC2 Windows instances might have rules blocking outbound traffic by default.
-
Internet Gateway not attached to the VPC: The IGW exists but isn’t attached to your VPC, or it’s attached to a different VPC.
The Fix
First, verify the Internet Gateway is attached to your VPC:
aws ec2 describe-internet-gateways \
--filters "Name=attachment.vpc-id,Values=vpc-0a1b2c3d4e5f6g7h8" \
--query 'InternetGateways[*].[InternetGatewayId,Attachments[0].State]' \
--output table
If nothing returns, attach an IGW:
aws ec2 create-internet-gateway --output text
aws ec2 attach-internet-gateway \
--internet-gateway-id igw-0a1b2c3d4e5f6g7h8 \
--vpc-id vpc-0a1b2c3d4e5f6g7h8
Check the route table for the instance’s subnet:
aws ec2 describe-route-tables \
--filters "Name=association.subnet-id,Values=subnet-0a1b2c3d4e5f6g7h8" \
--query 'RouteTables[0].Routes' \
--output table
Add a route to the Internet Gateway if missing:
aws ec2 create-route \
--route-table-id rtb-0a1b2c3d4e5f6g7h8 \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id igw-0a1b2c3d4e5f6g7h8
Verify the instance has a public IP:
aws ec2 describe-instances \
--instance-ids i-0a1b2c3d4e5f6g7h8 \
--query 'Reservations[0].Instances[0].[PublicIpAddress,PrivateIpAddress]'
If no public IP, allocate and assign an Elastic IP:
aws ec2 allocate-address --domain vpc --output text
aws ec2 associate-address \
--instance-id i-0a1b2c3d4e5f6g7h8 \
--allocation-id eipalloc-0a1b2c3d4e5f6g7h8
Check Security Group
Verify the security group allows outbound traffic:
aws ec2 describe-security-groups \
--group-ids sg-0a1b2c3d4e5f6g7h8 \
--query 'SecurityGroups[0].IpPermissionsEgress' \
--output table
If outbound is restricted, add a rule to allow all outbound:
aws ec2 authorize-security-group-egress \
--group-id sg-0a1b2c3d4e5f6g7h8 \
--protocol -1 \
--cidr 0.0.0.0/0
Check Network ACL
Verify the NACL for the subnet:
aws ec2 describe-network-acls \
--filters "Name=association.subnet-id,Values=subnet-0a1b2c3d4e5f6g7h8" \
--query 'NetworkAcls[0].Entries' \
--output table
Ensure outbound rules allow destination ports (443 for HTTPS, 80 for HTTP) and ephemeral return ports (1024-65535).
How to Run This
- Verify Internet Gateway is attached to the VPC.
- Ensure the route table has a
0.0.0.0/0route to the IGW. - Confirm the instance has a public IP assigned.
- Check security group egress rules allow outbound.
- Verify NACL rules don’t block outbound on the required ports and ephemeral ranges.
- Test from the instance:
curl -v https://aws.amazon.com.
Is This Safe?
Yes, these configurations are safe. The 0.0.0.0/0 route to an Internet Gateway is the standard way instances access the internet. Public subnets are designed to allow outbound internet traffic.
Key Takeaway
Internet connectivity requires four things: an attached Internet Gateway, a route in the subnet’s route table, a public IP on the instance, and security group/NACL rules allowing outbound. Missing any one of these will break connectivity. Always check the route table first—it’s the most commonly overlooked piece.
Have questions or ran into a different networking issue? Connect with me on LinkedIn or X.