Azure VM has no outbound internet access: private subnets are the new default
A new Azure VM that can't reach the internet, activate Windows or install updates is usually in a private subnet, which new virtual networks now get by default. How to tell, which explicit way out to add (NAT Gateway for most), and the stop-and-deallocate step people miss.
Networking & VMsFix a problem6 min read
For years, an Azure VM without any public IP could still reach the internet, because Azure quietly gave it an address of its own for outbound traffic. That's ending for new networks. Subnets created through the portal are already private, and so are subnets in new virtual networks created with API versions released after 31 March 2026. A VM in a private subnet has no outbound internet access until you give it an explicit way out, so Windows activation, Windows Update, package managers and calls to public APIs all fail. Existing networks keep working as they are. This guide shows how to tell which kind of subnet you have, which way out to add, and how to move older subnets over on your own schedule.
- A new VM can't reach
https://sites,aptordnfrepositories, or a public API. - Windows says it can't activate, and Windows Update fails.
- The VM still reaches storage accounts in its own region, which makes it look like a firewall problem.
- Templates that worked last year now create VMs without internet access.
What changed, and what didn't
Default outbound access is the address Azure assigned to a VM that had no other route to the internet. Microsoft owns that address, it can change without notice, it doesn't answer ICMP pings or carry fragmented packets, and several VMs or scale-set instances get inconsistent addresses from it. Microsoft has been steering everyone off it for those reasons, and because implicit internet access doesn't fit Zero Trust.
| Situation | Outbound internet without your own method? |
|---|---|
| Subnet created in the Azure portal (any date) | No: the portal makes subnets private |
| New virtual network created with an API version released after 31 March 2026 | No: its subnets are private by default |
| New virtual network created with an older API version (older templates, pinned Terraform providers) | Yes: defaultOutboundAccess is left empty, which still allows it |
| Existing virtual network, including new VMs added to it | Yes, unless someone made the subnet private |
| VM that already has a NAT Gateway, public IP, load balancer outbound rule or firewall route | Uses that method; nothing changes |
So the same template can behave differently depending on its API version. Setting defaultOutboundAccess explicitly in every template removes the guesswork.
Is the subnet private?
az network vnet subnet show --resource-group <rg> --vnet-name <vnet> --name <subnet> \
--query "{subnet:name, defaultOutbound:defaultOutboundAccess, nat:natGateway.id}"
defaultOutboundAccess | Meaning |
|---|---|
false | Private subnet: VMs need an explicit method to reach public endpoints |
true | Default outbound access allowed |
null (empty) | Created the older way: default outbound access is still allowed |
In the portal it's the Private subnet (or Default outbound access) setting on the subnet. If nat is empty and the subnet is private, that's your answer.
The four ways out
| Method | Use it when | Watch out for |
|---|---|---|
| NAT Gateway on the subnet | Almost always: every VM in the subnet shares one or more static outbound addresses you own | Billed while it exists and for data processed; one NAT Gateway per subnet |
| Public IP on the VM's network interface | A single VM that also needs to be reachable from outside | Opens a path in as well as out; lock it down with a network security group |
| Outbound rules on a Standard public load balancer | The VMs already sit behind that load balancer | More to configure than NAT; a backend pool configured by IP address still falls back to default outbound (a known issue Microsoft lists) |
Firewall or network appliance with a route 0.0.0.0/0 to it | You need central inspection and logging of outbound traffic | Routes with next hop Internet that bypass the firewall for service tags stop working in a private subnet |
NAT Gateway is also the fix for SNAT port exhaustion: each of its public addresses gives 64,512 ports shared across the subnet, and you can attach up to 16 addresses. Intermittent timeouts and "address already in use" errors under load are the classic sign that a VM ran out of ports with the other methods.
Add a NAT Gateway
# A Standard public IP for the NAT Gateway to use
az network public-ip create --resource-group <rg> --name nat-ip --sku Standard
# The NAT Gateway itself
az network nat gateway create --resource-group <rg> --name app-nat \
--public-ip-addresses nat-ip --idle-timeout 4
# Attach it to the subnet
az network vnet subnet update --resource-group <rg> --vnet-name <vnet> --name <subnet> \
--nat-gateway app-nat
The VMs' outbound traffic now leaves from nat-ip, which is also the address to give anyone who allow-lists your traffic, such as a partner's API or a SaaS firewall. It stays the same until you delete it.
Changing a subnet needs a stop and deallocate
A subnet's private setting is copied onto each VM's network interface when the VM is allocated. After you switch a subnet to private, or back, every existing VM in it has to be stopped (deallocated) and started again before the change applies. A restart from inside Windows or Linux doesn't count. Plan the transition for older subnets like this:
- Add the explicit method first (a NAT Gateway on the subnet), so nothing loses its way out.
- Set the subnet to private.
- Stop and deallocate each VM, then start it, in a maintenance window.
az network vnet subnet update --resource-group <rg> --vnet-name <vnet> --name <subnet> \
--default-outbound false
Azure Advisor lists the VMs that still hold a default outbound address under Operational Excellence, as "Add explicit outbound method to disable default outbound". The alert clears once the subnet is private and the VMs have been deallocated, even if they already used a NAT Gateway, because the old address lingers on the network interface until then.
What else changes in a private subnet
- Windows activation and updates need the explicit way out; there's no exception for them.
- Storage accounts in the same region stay reachable without one. Use network security groups if you want to control that traffic too.
- Service endpoints keep working; their routes use a different next hop type.
- Delegated subnets for platform services (App Service integration, Power Platform, Container Apps) aren't affected by the setting; each service manages its own outbound traffic. For Power Platform, see the virtual network support checklist.
- Flexible virtual machine scale sets never had default outbound addresses, so they already needed an explicit method.
Sources
- Default outbound access in Azure, Microsoft Learn (what's affected and not, private subnets, the limitations, stop and deallocate, the Advisor alert)
- Outbound internet access: control egress from Azure, Microsoft Learn (replacing default outbound access, firewall routes, SNAT port exhaustion and NAT Gateway capacity)
- What is Azure NAT Gateway?, Microsoft Learn
- Outbound rules in Azure Load Balancer, Microsoft Learn
- Default outbound access for VMs in Azure will be retired, Azure Updates (the announcement)
Did this fix it?
Comments
No comments yet. Share what worked for you.
Sign in to comment. Comments show under a display name you choose, never your email.