Cloud NAT in GCP Explained: Outbound Internet for Private VMs
Cloud NAT is a managed GCP service that gives private VMs outbound internet access without assigning them a public IP address. VMs can download OS patches, pull container images, and call third-party APIs. The internet never sees their real IP address and cannot initiate connections back to them.
The standard security practice in GCP is to remove external IPs from compute workloads unless they are absolutely necessary. An external IP expands your attack surface: every public-facing IP is reachable from anywhere on the internet. But stripping external IPs from VMs creates an immediate operational problem: those VMs can no longer reach the internet for outbound tasks.
Common reasons private VMs still need outbound internet access: apt and yum package updates, pulling container images from Docker Hub or other registries, sending data to third-party APIs, and downloading libraries at build or boot time. Cloud NAT handles all of this cleanly, at scale, with no VM or appliance to manage.
Simple explanation
Cloud NAT sits between your private VM and the internet. When your VM sends a packet to an external destination, Cloud NAT catches it at the VPC edge, swaps the source IP from the VM’s private IP to a public NAT IP, and forwards it on. The external server replies to that NAT IP. Cloud NAT catches the response, translates the destination back to the VM’s private IP, and delivers it.
The VM can start connections. Responses can come back. But no one on the internet can initiate a connection through Cloud NAT to your VM. There is no inbound path.
Cloud NAT is not a VPN and is not a port-forward. There is no inbound path. If you are counting on Cloud NAT to let external systems reach your private VMs, that will not work. You need a load balancer or an external IP for inbound access.
Your home router does exactly this. Your laptop has a private IP (192.168.1.x), but the router uses its one public IP for all outbound traffic. Websites see the router’s IP, not your laptop’s. You can browse, download, and make requests, but someone on the internet cannot directly reach your laptop unless you set up port forwarding. Cloud NAT is the same concept applied to GCP private VMs, managed by Google, and scaled automatically.
Cloud NAT is not a VM or appliance. It is a software-defined, distributed service with no single point of failure and no instance to manage, patch, or resize. Google handles scaling automatically as your traffic grows.
How Cloud NAT works
Cloud NAT is configured per region per VPC network. A single NAT gateway can cover all subnets in a region, or you can restrict it to specific subnets.
Here is the full packet flow:
- A VM with no external IP sends a packet to an internet destination (for example, a package server at 185.x.x.x).
- GCP consults the VPC’s route table. The default route (
0.0.0.0/0via the default internet gateway) matches. - Cloud NAT intercepts the packet before it leaves the VPC boundary. It replaces the private source IP with one of the gateway’s public NAT IP addresses, and assigns a source port from the pool allocated for that VM.
- The packet is forwarded to the internet. The external server sees the NAT IP as the sender and replies to it.
- The reply packet arrives at the NAT gateway. Cloud NAT looks up the original session using IP and port, reverses the translation, and delivers the response to the VM’s private IP.
This entire translation happens without any configuration on the VM itself. The VM only knows its private IP. Cloud NAT handles everything at the network edge.
Regional scope
A Cloud NAT gateway covers one region within one VPC. If you have private VMs in europe-west1 and us-central1, you need a Cloud NAT gateway in each region. A gateway in europe-west1 does nothing for VMs in us-central1.
Think of a Cloud NAT gateway like a local post office. Mail from your neighbourhood goes through the local office. A post office in Paris does not handle letters from Berlin, even if both cities are in the same country. One gateway per region, and it only processes traffic from VMs in that region.
Cloud Router dependency
Cloud NAT requires a Cloud Router in the same region and VPC. Cloud Router is a managed BGP speaker. Cloud NAT uses it as a regional control-plane component. You do not need to configure BGP sessions for this use case; just create the Cloud Router and attach the NAT gateway to it.
NAT IP addresses
Your NAT gateway can use:
- Auto-allocated IPs: GCP assigns public IPs automatically and adds more as demand grows. Simpler to manage, but the IPs can change over time.
- Reserved static IPs: you reserve specific external IP addresses and assign them explicitly. The outbound IP stays constant, which is required when external systems need to allowlist your traffic by IP.
Cloud NAT does not apply to traffic destined for Google APIs. That traffic should go through Private Google Access instead, which routes it over Google’s internal network. Sending Google API calls through Cloud NAT means they travel out to the public internet and back, which is slower, more expensive, and incompatible with VPC Service Controls.
When to use Cloud NAT
Use Cloud NAT when private VMs need to reach destinations on the public internet:
- OS and software updates: apt, yum, and similar package managers pull from public repositories. Private VMs without Cloud NAT cannot run updates.
- Container image pulls: pulling from Docker Hub, GitHub Container Registry, or other public registries requires outbound internet access.
- Third-party API calls: sending data to payment processors, analytics endpoints, external monitoring services, or other partner APIs.
- IP allowlisting requirements: when external services require a fixed source IP from you, use Cloud NAT with reserved static IPs. You control exactly which IP appears in outbound traffic.
- Private GKE nodes: nodes in private GKE clusters have no external IPs. Cloud NAT is how those nodes pull images from the internet and reach external endpoints during workload execution.
- Serverless egress to the internet: Cloud Run and Cloud Functions can reach the internet directly by default, but if your workloads are attached to a VPC via Serverless VPC Access, all their traffic routes through the VPC. Add Cloud NAT to that VPC to give those workloads outbound internet access.
When not to use Cloud NAT
Cloud NAT solves one specific problem: outbound internet from private VMs. For other connectivity needs, different services are a better fit:
- Reaching Google APIs privately: use Private Google Access. Traffic to Cloud Storage, BigQuery, Pub/Sub, and other Google services should stay on Google’s internal network, not go through Cloud NAT to the public internet.
- Accepting inbound traffic from the internet: Cloud NAT does not support this at all. Assign an external IP directly to the VM, or put a load balancer in front of it. See Private vs Public IP Addresses for guidance on when each approach fits.
- Private connectivity to on-premises or another cloud: use Cloud VPN, Cloud Interconnect, or VPC Peering depending on the topology. Cloud NAT has nothing to do with private network paths between environments.
- Internal VPC-to-VPC traffic: traffic between VMs in the same VPC, or across VPCs via peering, stays on Google’s private network. Cloud NAT is not involved and not needed for this.
- Shared VPC outbound: in a Shared VPC setup, Cloud NAT is configured in the host project. Service projects use the host project’s NAT gateway. Do not create duplicate gateways in service projects.
Cloud NAT vs Private Google Access
These two services are frequently confused because both allow private VMs to reach external destinations. They are complementary, not competing. Most production environments use both.
| Feature | Cloud NAT | Private Google Access |
|---|---|---|
| Purpose | Outbound internet access for private VMs | Private access to Google-managed APIs |
| Traffic destination | Any public internet address | Google APIs only (Cloud Storage, BigQuery, etc.) |
| Internet traversal | Yes, traffic goes out to the public internet | No, traffic stays on Google’s internal network |
| Where configured | Cloud Router + NAT gateway (per region) | Subnet flag (per subnet) |
| Egress cost | Standard internet egress applies | No internet egress, cheaper for Google API calls |
| VPC Service Controls | Not the recommended path for Google APIs | Yes, via restricted.googleapis.com |
| Use both together? | Yes. They serve different needs and most environments need both | |
If your VMs need to call both Google APIs and external internet services, enable Private Google Access on the subnet and configure Cloud NAT on the Cloud Router. They do not conflict.
Cloud NAT vs external IPs
Both approaches give a VM outbound internet access, but they have different security and operational characteristics.
| Feature | Cloud NAT | External IP on VM |
|---|---|---|
| Inbound internet access | Not possible through Cloud NAT | Yes, VM is directly reachable from internet |
| Outbound internet access | Yes | Yes |
| Attack surface | Lower: VM has no public-facing address | Higher: every VM IP is reachable from internet |
| IP visibility | NAT IP is shared across VMs on the gateway | Each VM has its own unique public IP |
| Setup complexity | Cloud Router + NAT gateway required | Assign IP to VM, simpler initially |
| Best for | Production backend workloads, batch jobs, private GKE nodes | Bastion hosts, services that genuinely need inbound access |
For most backend workloads, Cloud NAT is the right default. Use external IPs only where inbound reachability is actually required. See Private vs Public IP Addresses and Network Security Best Practices for the broader context.
Setting up Cloud NAT
Cloud NAT requires a Cloud Router in the same region and VPC. Create that first, then attach the NAT gateway to it.
# Create a Cloud Router (required by Cloud NAT)
gcloud compute routers create my-nat-router \
--network=my-vpc \
--region=europe-west1
# Create a Cloud NAT gateway covering all subnets, with auto-allocated IPs
gcloud compute routers nats create my-nat-gateway \
--router=my-nat-router \
--region=europe-west1 \
--nat-all-subnet-ip-ranges \
--auto-allocate-nat-external-ips
# Verify the gateway was created
gcloud compute routers nats describe my-nat-gateway \
--router=my-nat-router \
--region=europe-west1The —nat-all-subnet-ip-ranges flag applies Cloud NAT to all subnets in that region within the VPC. To restrict coverage to specific subnets, use —nat-custom-subnet-ip-ranges=my-subnet instead.
You can also create Cloud NAT through the GCP Console under Network services > Cloud NAT, which walks through the same choices in a guided form.
Using static NAT IPs
If external systems need to allowlist your outbound IP (common for third-party APIs and partner firewall policies), reserve a static external IP and assign it explicitly to the gateway.
# Reserve a static external IP for NAT use
gcloud compute addresses create my-nat-ip \
--region=europe-west1
# Create Cloud NAT using the reserved static IP
gcloud compute routers nats create my-nat-gateway \
--router=my-nat-router \
--region=europe-west1 \
--nat-all-subnet-ip-ranges \
--nat-external-ip-pool=my-nat-ipYour outbound traffic will consistently appear from my-nat-ip. Give that IP to the external system for allowlisting. It will not change unless you replace the reserved address.
Logging, ports, and scaling
NAT logging
Cloud NAT can log translation events to Cloud Logging, which is useful for auditing and diagnosing connectivity issues.
# Enable logging on an existing Cloud NAT gateway
gcloud compute routers nats update my-nat-gateway \
--router=my-nat-router \
--region=europe-west1 \
--enable-logging \
--log-filter=ALL
# Query Cloud NAT logs in Cloud Logging
gcloud logging read \
'resource.type="nat_gateway" AND resource.labels.router_id="my-nat-router"' \
--project=my-project \
--limit=20Logging at the ALL level generates high log volume for busy gateways and will raise your Cloud Logging bill noticeably. Use ERRORS_ONLY in production unless you are actively troubleshooting. Switch to ALL temporarily when you need a full audit trail or are chasing an intermittent failure.
Port allocation and exhaustion
Each NAT IP address provides 64,512 usable ports. Cloud NAT allocates a minimum number of ports per VM when the gateway starts. The default is 64 ports per VM.
For most background workloads (periodic updates, occasional API calls), 64 ports is enough. For VMs making many simultaneous outbound connections (high-throughput data pipelines, parallel HTTP clients, batch jobs with hundreds of threads), 64 ports can run out. When port exhaustion hits, new outbound connections fail intermittently in ways that are hard to diagnose without metrics.
Exhausted ports do not produce a clear error message. Connections just start failing at random, and VM logs show generic timeouts. The only reliable way to catch this early is to monitor nat/allocated_ports in Cloud Monitoring. Set up an alert before you see failures in production.
Watch the nat/allocated_ports metric in Cloud Monitoring. If VMs are approaching their port ceiling, increase the minimum before you see failures.
# Increase minimum ports per VM
gcloud compute routers nats update my-nat-gateway \
--router=my-nat-router \
--region=europe-west1 \
--min-ports-per-vm=256See Troubleshooting Network Issues for a broader packet-path validation approach when port metrics alone are not enough.
Common mistakes
- Assuming Cloud NAT supports inbound traffic. It does not. Cloud NAT is strictly outbound. Traffic from the internet cannot reach a VM through Cloud NAT. If a VM needs to accept inbound connections, give it an external IP or put a load balancer in front of it.
- Forgetting Cloud NAT is regional. A NAT gateway in europe-west1 does not help VMs in us-central1. Create a gateway per region where private VMs need outbound internet access.
- Routing Google API calls through Cloud NAT. Traffic to Cloud Storage, BigQuery, and other Google APIs should go through Private Google Access, not Cloud NAT. Sending API traffic through Cloud NAT costs more in egress fees, adds latency, and can bypass VPC Service Controls.
- Missing the default route. Cloud NAT depends on the VPC’s default route (
0.0.0.0/0via the internet gateway) being present. If it was deleted in a hardening exercise, outbound traffic has nowhere to go even with Cloud NAT configured. Check Routes in GCP first when troubleshooting. - Forgetting firewall egress rules. If your VPC has a deny-all egress rule, you must add an explicit allow rule for outbound traffic. Cloud NAT does not override firewall policy. See Firewall Rules Explained.
- Not planning for port exhaustion. The default 64 minimum ports per VM is fine for light workloads but not for VMs with many simultaneous connections. Monitor
nat/allocated_portsand increase—min-ports-per-vmbefore you see random connection failures. - Expecting Cloud NAT to fix serverless egress on its own. Cloud Run and Cloud Functions that need to route traffic through a VPC require Serverless VPC Access to be configured first. Cloud NAT handles the outbound internet leg, but only after the connector is in place.
Troubleshooting Cloud NAT
If a private VM cannot reach the internet, work through this checklist in order:
- Same region check. Confirm the VM is in the same region as the Cloud NAT gateway. A gateway in europe-west1 does not serve VMs in us-central1.
- Correct VPC and Cloud Router. Verify the Cloud Router and NAT gateway exist in the same VPC as the VM. Check with
gcloud compute routers listandgcloud compute routers nats list —router=my-nat-router —region=europe-west1. - Default route exists. Confirm that
0.0.0.0/0via the default internet gateway is present in the VPC. See Routes in GCP. Cloud NAT depends on this route being in place. - Firewall egress rules. If your VPC has deny-all egress, confirm there is an allow rule covering the destination port and IP range. See Firewall Rules Explained.
- Subnet coverage. Check whether the VM’s subnet is included in the NAT gateway’s coverage. If you used
—nat-custom-subnet-ip-rangesat creation time, the VM’s subnet may have been excluded. - NAT logging. Enable
ERRORS_ONLYlogging on the gateway and check Cloud Logging for translation errors. Error logs often point directly at the cause. - Port exhaustion. Check the
nat/allocated_portsmetric in Cloud Monitoring. If VMs are hitting their port ceiling, new connections will fail intermittently. Increase—min-ports-per-vm. - Serverless connector validation. If this is a Cloud Run or Cloud Functions workload, verify that a Serverless VPC Access connector is correctly attached. See Serverless VPC Access.
For packet-level validation and more advanced network diagnosis, see Troubleshooting Network Issues.
Frequently asked questions
What is Cloud NAT in GCP?
Cloud NAT is a managed, software-defined Network Address Translation service. It lets VM instances that have no external IP address initiate outbound connections to the internet. The VM sends traffic with its private IP; Cloud NAT replaces the source with a public NAT IP, forwards the packet, and delivers the response back to the VM. No inbound sessions can be started through Cloud NAT — only connections initiated by the VM are possible.
Does Cloud NAT allow inbound internet traffic?
No. Cloud NAT is strictly outbound. Your VMs can initiate connections and receive responses, but no external host can start a new connection to a VM through Cloud NAT. If you need a VM to receive inbound internet traffic, assign it an external IP, place it behind a load balancer, or use a reverse proxy. Cloud NAT provides no inbound path.
What is the difference between Cloud NAT and Private Google Access?
Cloud NAT routes traffic from private VMs out to the public internet for any destination. Private Google Access is a subnet-level flag that opens a private path from VMs to Google-managed APIs (Cloud Storage, BigQuery, Pub/Sub), without any internet traversal. For reaching Google APIs, Private Google Access is faster and cheaper. For reaching anything outside of Google — third-party APIs, package repos, public registries — use Cloud NAT. Most environments need both. See Private Google Access for the full comparison.
Do I need one Cloud NAT gateway per region?
Yes. Cloud NAT is regional. Each gateway covers VMs in one region of one VPC. If you have private VMs spread across multiple regions, create a Cloud NAT gateway in each region. Each one needs its own Cloud Router in the same region and VPC.
When should I use static NAT IPs?
Use static NAT IPs when external systems need to allowlist your outbound IP addresses. Third-party APIs, SaaS platforms, and partner firewalls often require a known, stable source IP before they will accept your traffic. Reserve a static external IP, then assign it to your Cloud NAT gateway. Your outbound traffic will always appear from that IP. Without static assignment, Cloud NAT uses auto-allocated IPs that can change over time.
Summary
- Cloud NAT gives private VMs outbound internet access without external IPs. No inbound path exists through it.
- It is a managed, distributed service, not a VM or appliance, with no single point of failure
- Configured per region per VPC, attached to a Cloud Router in the same region
- NAT IPs can be auto-allocated or reserved as static IPs for allowlisting requirements
- Use Private Google Access for Google API traffic: it is cheaper, faster, and stays off the public internet
- The default VPC route (0.0.0.0/0) must exist and egress firewall rules must permit outbound traffic
- Monitor
nat/allocated_portsand increase—min-ports-per-vmfor high-connection workloads - For serverless workloads that route through a VPC, Serverless VPC Access is required alongside Cloud NAT
Frequently asked questions
What is Cloud NAT in GCP?
Cloud NAT (Network Address Translation) is a managed GCP service that lets VM instances without external IP addresses initiate outbound connections to the internet. The VM sends a packet with its private IP, Cloud NAT translates the source address to a public NAT IP, and forwards it out. Return packets are translated back to the VM. Traffic initiated from the internet cannot reach the VM through Cloud NAT — it is outbound-only.
Does Cloud NAT allow inbound internet traffic?
No. Cloud NAT is strictly outbound. It supports connections that your VMs initiate — traffic flows out and responses can return. But no one on the internet can start a new connection to your VM through Cloud NAT. If you need inbound internet access, you need an external IP on the VM, a load balancer, or a reverse proxy in front of it.
What is the difference between Cloud NAT and Private Google Access?
They solve different problems. Cloud NAT gives private VMs outbound internet access to any destination — package repositories, third-party APIs, and so on. Private Google Access is a subnet flag that lets private VMs reach Google-managed APIs (Cloud Storage, BigQuery, Pub/Sub) over Google internal paths, without any internet transit. For reaching Google APIs, Private Google Access is cheaper, faster, and does not go over the public internet. Many environments use both.
Do I need one Cloud NAT gateway per region?
Yes. Cloud NAT is regional. A gateway in europe-west1 only covers VMs in that region. If you have private VMs in us-central1 and europe-west1, you need a Cloud NAT gateway in each region, each attached to a Cloud Router in the same region and VPC.
When should I use static NAT IPs?
Use static NAT IPs when external systems need to allowlist your outbound IP addresses. Third-party APIs or partner firewall rules often require a fixed source IP before they will accept your traffic. Reserve a static external IP address, then assign it explicitly to your Cloud NAT gateway instead of using auto-allocation. Your outbound traffic will consistently use that IP.