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.

In this lesson
Table of Contents
Table of contents
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.
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 IPv4The KBY LexiconIPv4IPv4 is the 32-bit addressing and packet-delivery protocol underlying most network-layer communication, from subnetting and NAT to routing and coexistence with IPv6. 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.
| Element | Public subnet instance | Private subnet instance |
|---|---|---|
| Instance address | Public IPv4 or Elastic IP required | Private address only is sufficient |
| Default route target | Internet gateway | NAT gateway |
| Gateway location | Attached to the VPC | NAT gateway sits in a public subnet |
| Additional dependency | None beyond the IGW | NAT 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.

#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:
| Destination | Target | Status |
|---|---|---|
| 10.0.0.0/16 | local | active |
| 0.0.0.0/0 | nat-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:
- Record the instance’s subnet ID. This anchors every later check to the real subnet rather than an assumed one.
- Find the route table associated with that subnet, including the main-table fallback. Evidence: a route table ID.
- Read its routes. Evidence: presence or absence of 0.0.0.0/0, and its target and status.
- 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.
- Make the smallest change that fixes the first broken link. Note the previous state so you can restore it.
- 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_IDThe 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.

#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
Dates
Published
Sources
Corrections
No corrections are listed for this page. Some review sweeps corrected pages without naming each one; those are in the corrections log.
Related articles
Cloud Infrastructure and Operations
Fixing AWS EC2 SSH Connection Timed Out After Launching an Instance
Diagnose an EC2 SSH timeout in order: public IP, security group, route table, internet gateway and network ACL, with safe checks, a fix and rollback.
Security & Operations
Hunting BGP Route Hijacking in Real-Time Networks
Real-time BGP route hijacking detection using RPKI validation, AS-path anomaly scoring, and prefix origin tracking to stop network traffic diversion.
Systems Engineering
Linux Disk Full but df Shows Free Space: Inode Exhaustion Fix
How to tell inode exhaustion from deleted-but-open files when Linux reports 'No space left on device' although df shows free space, and how to recover safely.
Discover more
Graduate Learning
Lexicon Definitions
Learn More About KBY
About KBY
Learn about our mission, how our content is produced, and how we handle corrections.
Why Trust KBY
How KBY content is produced, what is checked automatically, and how errors are corrected.
The KBY Brief
A short email about twice a week with new runbooks, configuration traps and fixes from KBY Technologies.
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.
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.