Skip to main content
Graduate Track

AWS VPC Instance Has No Internet Access: Check Route Table and NAT

Why an EC2 instance in a VPC has no internet access, and how to trace the route table, NAT gateway and internet gateway to find the missing link safely.

AWS VPC Instance Has No Internet Access: Check Route Table and NAT
Sarah LiangSarah Liang10 min readIntermediate10 min

In this lesson

Share

Before you begin

  • Isolated or non-production AWS account with confirmed permissions
  • Working knowledge of IPv4 and CIDR notation
  • Experience launching an EC2 instance

Track this tutorial

Choose your current status and tick each safety check as you complete it. Sign in to sync progress between devices.

Current status

Before you apply the change

Confirm these production-safety controls during the tutorial.

0 of 6 safety checks completed

When an EC2 instance cannot reach the internet, the cause is rarely the instance itself. Outbound traffic has to cross several independent decisions: the instance’s own addressing, the security group, the subnet’s network ACL, the subnet’s route table, and a gateway that translates or forwards the packet. Any one of them can stop the traffic, and each fails in a different way. Guessing at settings in the console tends to hide the real cause and sometimes widens access unnecessarily.

This guide builds the mental model first and then applies it. You will learn what a route table actually does, why a private subnet needs a NAT gateway while a public subnet needs an internet gateway, and how to read the evidence each component produces. The exercise is bounded and reversible, and it belongs in a non-production account. The same reasoning transfers to production, where permissions and change control matter as much as the technical fix.

#Learning Objectives

  • Explain how a VPC route table selects a target for an outbound packet.
  • Distinguish the roles of an internet gateway and a NAT gateway, and state which subnet each one serves.
  • Trace an outbound path hop by hop and identify the first missing element.
  • Collect read-only evidence using the console or the AWS CLI before changing anything.
  • Apply a minimal fix in a lab and define its rollback.

#Prerequisites

  • An isolated or non-production AWS account and permission to view and, in the lab, edit VPC resources. Confirm your permissions and the current AWS documentation before any change; this guide does not assert version-specific behaviour.
  • Working knowledge of IPv4 addresses and CIDR notation, such as what 10.0.0.0/16 and 0.0.0.0/0 mean.
  • Familiarity with launching an EC2 instance. If you cannot connect to the instance at all, read Fixing AWS EC2 SSH Connection Timed Out After Launching an Instance first, because that is a different problem: inbound reachability.

#Content

#
The mental model: a packet leaves, and something must forward it

A route table is an ordered-by-specificity list of destination ranges and targets. When the instance sends a packet, the VPC looks for the most specific destination range that matches, which is the longest prefix. Every route table contains a local route covering the VPC’s own CIDR, so traffic inside the VPC always works. A destination such as 93.184.216.34 matches nothing local, so only a route for 0.0.0.0/0 (the default route) can carry it. If that route is absent, the packet is dropped. The instance sees a timeout, not an error message.

A subnet is associated with exactly one route table, either explicitly or through the VPC’s main route table by default. This is the first common surprise: you may edit a route table that the subnet is not using.

#
Internet gateway versus NAT gateway

An internet gateway (IGW) is attached to a VPC and gives resources in a subnet a path to and from the internet, provided they have a public IPv4 address (or an Elastic IP). A subnet whose route table sends 0.0.0.0/0 to an IGW is conventionally called public.

A NAT gateway lets instances without public addresses start outbound connections while preventing the internet from starting connections to them. The NAT gateway itself lives in a public subnet and holds an Elastic IP. The private subnet’s route table sends 0.0.0.0/0 to the NAT gateway, and the NAT gateway’s subnet sends 0.0.0.0/0 to the IGW. The chain therefore has three links, and the symptom is identical whichever link is broken.

Where each element must exist for outbound internet access
ElementPublic subnet instancePrivate subnet instance
Instance addressPublic IPv4 or Elastic IP requiredPrivate address only is sufficient
Default route targetInternet gatewayNAT gateway
Gateway locationAttached to the VPCNAT gateway sits in a public subnet
Additional dependencyNone beyond the IGWNAT subnet needs its own route to the IGW

#
Other controls on the same path

Route correctness is necessary but not sufficient. A security group is stateful and, by default, allows all outbound traffic, but it may have been tightened. A network ACL is stateless and applies per subnet, so it needs rules for both the outbound request and the returning ephemeral ports. DNS resolution can also fail separately: if the instance can reach 93.184.216.34 but not a hostname, the route is fine and the resolver is the problem.

Detailed view of blue ethernet cables connected to a network switch in a data center.
Photo by Brett Sayles on Pexels

#
Production bridge

In production, the fix is usually a single route entry, but the permission to make it is not trivial. Route table edits change the network reach of every workload in the associated subnets. Use an account role with the narrowest EC2 route permissions, make the change through your normal change process or infrastructure-as-code, and record who approved it. If you manage routes in code, a console edit creates drift; see the related guidance on reconciling console edits before you edit by hand. Adding a default route to the internet also widens the data exfiltration path, so check whether egress filtering or a proxy is required by policy. Escalate to the network or cloud platform team if the route table is shared across accounts, if a transit gateway or firewall sits in the path, or if the NAT gateway is owned by another team. The AWS Well-Architected Reliability Pillar documents failure management and recovery practices; the idea that a change needs a recovery path applies directly here.

#Examples

#
Worked example: private instance times out

Input: an instance at 10.0.2.15 in subnet-private-a runs curl -m 5 https://example.com and prints curl: (28) Connection timed out. The instance’s subnet has an association with route table rtb-private. The route table shows:

Routes in rtb-private (illustrative)
DestinationTargetStatus
10.0.0.0/16localactive
0.0.0.0/0nat-0abc (illustrative ID)blackhole

Interpretation: the route exists, so the earlier theory of a missing route is wrong. A blackhole status means the target no longer exists or is unusable, typically because the NAT gateway was deleted. The correct fix is to create or choose a working NAT gateway in a public subnet and point the default route at it. Do not try to add a second 0.0.0.0/0 route, because a route table cannot contain two routes for the same destination. Instead, replace (edit) the target of the existing blackhole route so that it points at the working NAT gateway, and record the previous target first.

#
Worked example: no default route at all

Here the table shows only the local route. The packet matches nothing, so it is dropped. The fix is to add 0.0.0.0/0 to the NAT gateway. Before doing so, confirm that the NAT gateway’s own subnet has a route to an IGW; otherwise the new route simply moves the failure one hop along.

#Exercises

#
Exercise: trace and repair a lab path

Objective: identify the first broken link in an outbound path and repair it with one change.

Setup: in a non-production account, use a VPC with one public subnet, one private subnet, an IGW and a NAT gateway. Note that a NAT gateway may incur charges while it exists; check current AWS pricing yourself. Launch a small instance in the private subnet with no public IP, and reach it using Session Manager or another method already approved in your lab. Do not open inbound ports for this exercise. Use a dedicated lab route table associated only with the lab private subnet, not a shared one. Record its existing routes first, then either start from a table that lacks a default route or remove the default route as a single manual, reviewed change.

Steps and why:

  1. Record the instance’s subnet ID. This anchors every later check to the real subnet rather than an assumed one.
  2. Find the route table associated with that subnet, including the main-table fallback. Evidence: a route table ID.
  3. Read its routes. Evidence: presence or absence of 0.0.0.0/0, and its target and status.
  4. Follow the target. If it is a NAT gateway, check its state and its subnet. Then read that subnet’s route table for 0.0.0.0/0 to the IGW.
  5. Make the smallest change that fixes the first broken link. Note the previous state so you can restore it.
  6. Retest from the instance with a short timeout.

Pass condition: the request completes from the instance and the route table shows an active default route. Stop conditions: stop if the route table is shared with subnets you do not recognise, if your permissions are denied, or if the account is not the lab. Cleanup: if the route was added only for the exercise, remove that one route through the console, then confirm the instance times out again; delete any NAT gateway you created and release its Elastic IP so that no charges or exposed addresses remain.

#Validation Guidance

Validate with evidence at each layer, in this order, because each result narrows the search.

1aws ec2 describe-route-tables --filters Name=association.subnet-id,Values=SUBNET_ID
2aws ec2 describe-nat-gateways --nat-gateway-ids NAT_GATEWAY_ID

The first command is read-only and should return the route table with its routes, including any blackhole state. If it returns nothing, the subnet uses the main route table, so repeat the query using the VPC ID and the main association. The second command queries the specific NAT gateway named in your route, without a state filter; read its state (it should be available) and its subnet from the output, then confirm that subnet is public. Replace SUBNET_ID and NAT_GATEWAY_ID with your own values and set the region explicitly.

Then retest from the instance. Success is a completed response, not merely an edited route. If the request still fails, move down the list: the network ACL for the subnet, the security group’s outbound rules, then DNS. Distinguish an observation (the route is active) from an inference (so the NAT is working) and from a recommendation (so close the ticket). Only the final request result confirms the path.

Close-up view of Ethernet ports with cables and illuminated LED indicator. Modern data connection setup.
Photo by panumas nikhomkhai on Pexels

#Common Mistakes

#
Editing the wrong route table

Symptom: the route looks correct but nothing changes. Cause: the subnet is associated with a different table. Diagnosis: query by subnet association. Correction: edit the associated table. Recovery: restore the earlier entry from your notes.

#
Putting the NAT gateway in a private subnet

Symptom: the NAT gateway is available but traffic times out. Cause: its own subnet has no route to the IGW. Diagnosis: read the NAT subnet’s route table. Correction: create a NAT gateway in a public subnet. Recovery: repoint the private default route to the previous target, then delete the misplaced gateway once nothing uses it.

#
Pointing a private subnet at the IGW

Symptom: still no access. Cause: the instance has no public address, so the IGW cannot translate its traffic. Correction: use a NAT gateway rather than assigning public addresses casually, which widens exposure. Create the NAT gateway in a public subnet with an Elastic IP, then replace the private route’s 0.0.0.0/0 target with it, recording the previous target first so you can restore it.

#
Blackhole route after deletion

Symptom: route shows blackhole. Cause: the target was deleted. Correction: replace the target.

#
Ignoring the network ACL or DNS

Symptom: routes are correct, yet failures persist, or only hostnames fail. Diagnosis: check stateless ACL return rules and resolver settings. Escalate to the network team if a shared firewall is in the path.

#Key Takeaways

  • An outbound path has links: instance, route table, gateway, and the gateway’s own route to the IGW. Find the first broken one.
  • A private subnet needs a default route to a NAT gateway located in a public subnet that routes to an IGW.
  • Read the evidence before editing: the associated table, the route status, the NAT gateway state and the final request result.
  • Rollback boundary: record the previous route, change one entry only, and restore that entry if the retest fails or other subnets are affected. Remove lab-only NAT gateways and Elastic IPs afterwards.
  • Next safe decision: in production, hand the verified finding and proposed single-route change to the owner of the route table for approval, rather than editing a shared table yourself.

About this page

Credited to

Sarah LiangKBY Technologies editorial account, not an individual author

Dates

Published

Sources

This page lists no external sources.

Corrections

No corrections are listed for this page. Some review sweeps corrected pages without naming each one; those are in the corrections log.

Reader Interaction

Comments

Add a thoughtful note on AWS VPC Instance Has No Internet Access: Check Route Table and NAT. Comments are checked for spam and held for moderation before appearing.

Loading comments...

Discover more

Learn More About KBY

Was this useful?

Reports go to the site owner and are used to correct pages. Corrections are listed at /corrections.

Build practical engineering skills.

Receive new lessons, learning paths, practical exercises and early-career guidance.