Cloud & infrastructure

Azure Default Outbound Access Retirement: Migrate VMs to NAT Gateway

New Azure virtual networks now get private subnets with no default outbound access. Find the VMs that depend on it, add a NAT gateway, make the subnet private and verify egress.

10 min read
On this page

Azure hasn't switched off default outbound access for existing networks, but subnets in new virtual networks created with an API version released after 31 March 2026 are private by default, so VMs placed in them can't reach the internet until you add an explicit outbound method. The fix for both new and existing networks is the same: attach a NAT gateway (Microsoft's recommended method) to the subnet, set Default outbound access to Disabled, then stop and deallocate the VMs so they pick up the change.

Who this is for and what you will have at the end

This guide is for Azure network and platform engineers who either deploy new virtual networks and find that VMs can't reach the internet, or have Azure Advisor recommendations telling them to "add explicit outbound method to disable default outbound".

At the end you will have:

  • A list of VMs and scale set instances that rely on default outbound access.
  • A zone-redundant StandardV2 NAT gateway with a static public IP attached to the right subnets.
  • Private subnets, so no new default outbound IPs are created.
  • A verified, predictable outbound IP you can give to partners for allow lists.

What changed and what didn't

When a VM has no explicit outbound method, Azure gives it a default outbound public IP. That address is owned by Microsoft and can change without notice. It also doesn't support fragmented packets or ICMP ping, and with multiple NICs or scaling scale sets the outbound IP can be inconsistent.

ScenarioDefault outbound access
Subnet in a new VNet created with an API version released after 31 March 2026Off by default (defaultOutboundAccess is false)
Subnet created in the Azure portalThe portal already defaults to private subnets
Template or Terraform pinned to an older API versionProperty left null, which still allows default outbound
Existing VNets, existing and new VMs in themStill provided until you make the subnet private
Flexible orchestration scale setsNever provided; an explicit method is always required

Explicit outbound methods, in the order Azure uses them for new connections:

  1. A user-defined route sending 0.0.0.0/0 to a virtual appliance (such as Azure Firewall) or a virtual network gateway.
  2. A NAT gateway on the subnet.
  3. A public IP on the VM's network interface.
  4. Outbound rules on a Standard public load balancer.
  5. The default system route to the internet.

A NAT gateway takes over all new connections from a load balancer, instance public IPs or Azure Firewall. Microsoft states that a Standard NAT gateway doesn't drop existing flows that use those methods, but lists as a known issue that existing outbound connections might be interrupted when you add a StandardV2 NAT gateway, so attach it in a maintenance window.

Prerequisites

  • Network Contributor (or equivalent) on the virtual network, the subnets and the resource group for the NAT gateway and public IP.
  • Azure CLI or Azure PowerShell. Microsoft's NAT gateway quickstarts require Az PowerShell 5.4.1 or later.
  • No Basic SKU resources in the target subnet. NAT gateway doesn't work in subnets with a Basic load balancer or Basic public IPs. Upgrade those first; see upgrading Basic public IPs to Standard.
  • A maintenance window. VMs must be stopped and deallocated for a subnet's private setting to apply to their NICs.
  • A region that supports StandardV2. Check the region list in the NAT gateway overview; Microsoft lists a small number of regions without StandardV2 support.

You can't deploy a NAT gateway in a GatewaySubnet or in a subnet that contains a SQL managed instance, and delegated subnets that host PaaS services manage outbound connectivity themselves.

Step 1: Find VMs that use default outbound access

Each NIC has a defaultOutboundConnectivityEnabled parameter that tracks whether a default outbound IP is allocated. Advisor uses it to raise two separate recommendations.

  1. In the Azure portal, search for Advisor.
  2. Select Operational Excellence.
  3. Open Add explicit outbound method to disable default outbound and Add explicit outbound method to disable default outbound for Virtual Machine Scale Sets.
  4. Each recommendation lists the NICs of VMs or scale set instances that have default outbound enabled.

Then check the subnet setting itself. With Azure PowerShell, loop through a virtual network's subnets:

$vnet = Get-AzVirtualNetwork -ResourceGroupName 'rg-network' -Name 'vnet-prod'
$vnet.Subnets | Select-Object Name, DefaultOutboundAccess, NatGateway

A value of $false means the subnet is private. A blank (null) value means default outbound access is still allowed.

Step 2: Choose the explicit outbound method

MethodUse it whenNotes
NAT gateway (StandardV2)Most subnets that need outbound onlyZone redundant, up to 16 IPv4 and 16 IPv6 public IPs, up to 100 Gbps, flow logs
NAT gateway (Standard)StandardV2 isn't available in the region, or you need to reuse a Standard public IPZonal or no-zone, up to 16 IPv4 public IPs, up to 50 Gbps
Standard load balancer outbound rulesVMs are already in a public load balancer backend poolManage SNAT port allocation yourself
Instance-level public IPA single VM needs inbound and outbound on one addressLarger attack surface; Standard IPs need an NSG
Azure Firewall or NVA through a UDREgress must be inspected or filteredA NAT gateway can also sit on the firewall subnet in a hub

Standard and StandardV2 NAT gateways cost the same. A Standard gateway can't be upgraded to StandardV2; you create a new StandardV2 gateway and swap it onto the subnet.

Step 3: Create a StandardV2 NAT gateway

A StandardV2 NAT gateway only accepts StandardV2 public IPs or prefixes, so create the IP with that SKU. Azure CLI:

az network public-ip create \
    --resource-group rg-network \
    --name pip-natgw-prod \
    --location eastus \
    --sku StandardV2 \
    --allocation-method Static \
    --version IPv4 \
    --zone 1 2 3
 
az network nat gateway create \
    --resource-group rg-network \
    --name natgw-prod \
    --location eastus \
    --public-ip-addresses pip-natgw-prod \
    --idle-timeout 4 \
    --sku StandardV2 \
    --zone 1 2 3

Azure PowerShell:

$ip = @{
    Name              = 'pip-natgw-prod'
    ResourceGroupName = 'rg-network'
    Location          = 'eastus'
    Sku               = 'StandardV2'
    AllocationMethod  = 'Static'
    IpAddressVersion  = 'IPv4'
    Zone              = 1,2,3
}
$publicIp = New-AzPublicIpAddress @ip
 
$nat = @{
    ResourceGroupName    = 'rg-network'
    Name                 = 'natgw-prod'
    IdleTimeoutInMinutes = '4'
    Sku                  = 'StandardV2'
    Location             = 'eastus'
    PublicIpAddress      = $publicIp
    Zone                 = 1,2,3
}
$natGateway = New-AzNatGateway @nat

The TCP idle timeout defaults to 4 minutes and can be raised to 120. UDP idle timeout is fixed at 4 minutes. If partners need a range rather than single addresses, use a public IP prefix instead; supported prefix sizes are /28 to /31.

Step 4: Attach the NAT gateway and make the subnet private

Attach the NAT gateway and disable default outbound access in one update:

az network vnet subnet update \
    --resource-group rg-network \
    --vnet-name vnet-prod \
    --name snet-app \
    --nat-gateway natgw-prod \
    --default-outbound false

To make every subnet in a virtual network private with PowerShell, use the loop from Microsoft's documentation:

$vnet = Get-AzVirtualNetwork -ResourceGroupName 'rg-network' -Name 'vnet-prod'
 
foreach ($subnet in $vnet.Subnets) {
    if ($subnet.DefaultOutboundAccess -eq $null) {
        $subnet.DefaultOutboundAccess = $false
        Write-Output "Set DefaultOutboundAccess to false for subnet: $($subnet.Name)"
    }
    elseif ($subnet.DefaultOutboundAccess -eq $false) {
        Write-Output "Already private: $($subnet.Name)"
    }
}
Set-AzVirtualNetwork -VirtualNetwork $vnet

In the portal, open the virtual network, select Subnets, select the subnet, set Default outbound access to Disabled and select Save.

Finally, stop and deallocate each existing VM in the subnet and start it again. Until you do, the NIC keeps its previous default outbound state. The NAT gateway itself carries new connections immediately, so there's no reason to deallocate everything at once; work through the VMs in your maintenance window.

Fix UDRs with next hop Internet

In a private subnet, routes with next hop type Internet stop working unless the source also has an explicit outbound method. This often appears where a 0.0.0.0/0 route points at a firewall and service-tag routes with next hop Internet bypass it. A NAT gateway on the subnet gives those bypass routes a working egress path. Service endpoints aren't affected because they use the VirtualNetworkServiceEndpoint next hop.

Pin the setting in infrastructure as code

Templates and Terraform configurations that target older API versions leave defaultOutboundAccess as null, which still allows default outbound. Set it explicitly in every subnet definition so new environments behave the same way regardless of API version. In an ARM template the subnet property is:

"properties": {
  "addressPrefix": "10.1.0.0/24",
  "defaultOutboundAccess": false
}

Verify outbound connectivity

  1. Note the NAT gateway's public IP: open the NAT gateway, expand Settings and select Outbound IP.
  2. Connect to a VM in the subnet, for example through Azure Bastion, and check the address the internet sees:
curl ifconfig.me

The result must match the NAT gateway IP. On Windows, use Invoke-WebRequest against the same kind of endpoint.

  1. StandardV2 supports outbound ICMP echo for IPv4 and IPv6, so ping 8.8.8.8 is a quick reachability test. A timeout points to a missing subnet association, an NSG blocking outbound ICMP, routing, or an upstream firewall.
  2. After the VMs have been deallocated and restarted, the Advisor recommendations for those NICs should clear.
  3. For flow-level evidence, enable NAT gateway flow logs (StandardV2) or virtual network flow logs.

Troubleshooting

"Basic resources can't exist in the same subnet as NAT gateway." The subnet contains a Basic load balancer or Basic public IP. Upgrade them to Standard or move them to another subnet.

Can't add the public IP to the NAT gateway. Standard public IPs work only with Standard NAT gateways and StandardV2 public IPs only with StandardV2 gateways. Public IPs with routing preference Internet, DDoS-protected public IPs and (for StandardV2) custom BYOIP prefixes can't be used either.

NAT gateway can't be attached because a NIC is in a failed state. Fix the NIC first: run Get-AzNetworkInterface and Set-AzNetworkInterface on it (a GET then SET), or use Azure Resource Explorer to PUT the resource, then retry.

VNet or NAT gateway goes into a failed state after attaching StandardV2. This is a known issue for empty subnets created before April 2025. Remove the NAT gateway, create a VM in the subnet, then reattach the gateway.

Subnet update fails with an internal server error. Adding a StandardV2 NAT gateway and enabling a service endpoint in the same operation on a subnet with running VMs can fail. Do the two changes separately.

IPv6 outbound stops after adding StandardV2. Load balancer outbound rules for IPv6 are disrupted when a StandardV2 NAT gateway is attached. Use outbound rules for both IPv4 and IPv6, or a Standard NAT gateway for IPv4 with outbound rules for IPv6.

VMs behind an internal load balancer can't reach the internet. Standard internal load balancers don't provide outbound access. Attach a NAT gateway to the backend subnet. When a backend pool is configured by IP address, a known issue makes it use default outbound access, which is another reason to add the NAT gateway.

Advisor still shows a default outbound IP. The subnet isn't private yet or the VM hasn't been deallocated since it was made private.

Checklist

  • Advisor default outbound recommendations reviewed for VMs and scale sets.
  • Basic load balancers and Basic public IPs removed from target subnets.
  • StandardV2 NAT gateway and StandardV2 public IP (or prefix) created; outbound IP shared with partners.
  • NAT gateway attached and defaultOutboundAccess set to false on each subnet.
  • Each VM stopped, deallocated and started in a maintenance window.
  • UDRs with next hop Internet reviewed.
  • Templates and Terraform modules set defaultOutboundAccess explicitly.
  • curl ifconfig.me returns the NAT gateway IP and the Advisor recommendation has cleared.

For the identity and access side of a private-by-default network, see zero trust enterprise remote access architecture.

References

Questions people ask

Does the default outbound access change break my existing VMs?

No. Existing virtual networks aren't changed, and both existing and new VMs in them can keep receiving default outbound IPs until you make the subnet private. The change affects subnets in new virtual networks created with an API version released after 31 March 2026, which default to private.

Why can't a VM in a private subnet activate Windows or install updates?

Windows activation and Windows Update need to reach public endpoints, and a private subnet doesn't provide default outbound access. Add an explicit outbound method such as a NAT gateway, a Standard load balancer with outbound rules, an instance public IP, or a firewall reached through a user-defined route.

Why does Advisor still flag a VM after I added a NAT gateway?

In a non-private subnet a default outbound IP can still be assigned even though the NAT gateway carries the traffic. Make the subnet private, then stop and deallocate the VM so the network interface flag clears.

Should I use a Standard or StandardV2 NAT gateway?

StandardV2 is zone redundant, supports IPv6 and flow logs, and costs the same as Standard. Microsoft's migration tutorial uses it to replace default outbound access because it's zone redundant, while a Standard gateway is zonal. It needs StandardV2 public IPs and isn't available in every region, and a Standard gateway can't be upgraded in place.

Azure Virtual NetworkAzure NAT GatewayAzure Load BalancerAzure Firewall
  1. Build an Azure hub-and-spoke network with Azure Firewall and UDRs

    Peer spoke virtual networks to a hub, send their traffic through Azure Firewall with user-defined routes, inspect on-premises flows and configure forced tunnelling without breaking routing.

  2. Upgrade Azure Basic Public IPs to Standard SKU and Keep the Same Address

    Basic SKU public IPs were retired on 30 September 2025. Upgrade them to Standard and keep the address, with Microsoft's VM and load balancer scripts or a manual detach and upgrade.

  3. Azure Bastion SKUs compared: choose Developer, Basic, Standard or Premium

    Compare the four Azure Bastion SKUs on features, capacity and requirements, then deploy the right one to RDP and SSH into VMs that have no public IP address.