Symptoms
- The portal shows "Connecting..." then a blank screen or "The network connection to the Bastion Host appears unstable".
- "Bastion host could not be reached" or a 403 when you click Connect.
- Native client (
az network bastion ssh/rdp) returns an error about the SKU or the feature not being enabled. - RDP opens but you get a credential or "remote computer refused" error.
Most failures fall into five buckets: subnet/NSG, SKU and features, RBAC, the target VM, or the client.
Quick triage table
| Symptom | Likely cause | Fix |
|---|---|---|
| Bastion deployment fails | Subnet not named AzureBastionSubnet or smaller than /26 | Recreate the subnet with the exact name and /26 or larger |
| Portal session hangs, never connects | NSG on AzureBastionSubnet missing required rules | Add the inbound/outbound rules below |
| "Feature not supported" on native client | Basic SKU, or native client support not enabled | Upgrade to Standard and enable native client support |
| Connect button greyed out / 403 | Missing Reader on VM, NIC or Bastion | Grant Reader on the three resources |
| Session opens then drops | VM NSG blocks 3389/22 from the Bastion subnet | Allow from the AzureBastionSubnet prefix |
| Login fails | Wrong credentials, account locked, Entra login not configured | Reset password or fix the Entra extension |
1. Check the subnet
az network vnet subnet show -g rg-hub --vnet-name vnet-hub -n AzureBastionSubnet \
--query "{prefix:addressPrefix, nsg:networkSecurityGroup.id, rt:routeTable.id}" -o table
- The name must be exactly
AzureBastionSubnet. - It must be /26 or larger.
- Don't attach a route table that sends 0.0.0.0/0 to a firewall. Bastion needs to reach its control plane directly, and a forced-tunnel route on this subnet is a common cause of hanging sessions.
2. Check the NSG on AzureBastionSubnet
An NSG on the Bastion subnet is optional. If you add one, it must contain all of these rules. Missing just one is enough to break sessions.
| Direction | Source | Destination | Ports | Purpose |
|---|---|---|---|---|
| Inbound | Internet | Any | 443 | User sessions |
| Inbound | GatewayManager | Any | 443 | Control plane |
| Inbound | AzureLoadBalancer | Any | 443 | Health probes |
| Inbound | VirtualNetwork | VirtualNetwork | 8080, 5701 | Bastion data plane |
| Outbound | Any | VirtualNetwork | 22, 3389 | To target VMs |
| Outbound | Any | AzureCloud | 443 | Diagnostics, logging |
| Outbound | VirtualNetwork | VirtualNetwork | 8080, 5701 | Bastion data plane |
| Outbound | Any | Internet | 80 | Session and certificate validation |
List what is there now:
az network nsg rule list -g rg-hub --nsg-name nsg-bastion \
--query "sort_by([], &priority)[].{p:priority,dir:direction,acc:access,src:sourceAddressPrefix,dst:destinationAddressPrefix,ports:destinationPortRange}" -o table
Add a missing rule, for example GatewayManager inbound:
az network nsg rule create -g rg-hub --nsg-name nsg-bastion -n AllowGatewayManager \
--priority 130 --direction Inbound --access Allow --protocol Tcp \
--source-address-prefixes GatewayManager --destination-port-ranges 443
Tip
Check the Microsoft "Working with NSG access and Azure Bastion" page for the current rule list before you change production. The rules above match the documented set at the time of writing.
3. Check the target VM's NSG
The VM's NIC or subnet NSG must allow 3389 (Windows) or 22 (Linux) from the AzureBastionSubnet address range, not from the internet.
az network nic list-effective-nsg -g rg-app -n vm-app-01-nic -o json \
| jq '.value[].effectiveSecurityRules[] | select(.destinationPortRange=="22-22" or .destinationPortRange=="3389-3389")'
4. Check SKU and features
az network bastion show -g rg-hub -n bas-hub \
--query "{sku:sku.name, native:enableTunneling, ip:enableIpConnect, copy:disableCopyPaste}" -o table
- Native client (
az network bastion ssh/rdp/tunnel) needs Standard or Premium withenableTunnelingtrue. - Connecting by IP address (for example to a peered or on-premises machine) needs IP-based connection enabled.
- Basic SKU only supports the portal experience.
Upgrade and enable native client:
az network bastion update -g rg-hub -n bas-hub --sku Standard --enable-tunneling true
Warning
You can upgrade a SKU but not downgrade it. Plan the change in a maintenance window, because existing sessions drop.
5. Check permissions
The user needs Reader on the VM, the VM's NIC and the Bastion resource (plus the VNet if the VM is in a peered VNet). Without one of these, the Connect button is greyed out or returns a 403.
az role assignment list --assignee user@contoso.com --all \
--query "[].{role:roleDefinitionName, scope:scope}" -o table
6. Test with the native client
az extension add --name bastion --upgrade
# Linux with SSH key
az network bastion ssh -g rg-hub -n bas-hub \
--target-resource-id $(az vm show -g rg-app -n vm-app-01 --query id -o tsv) \
--auth-type ssh-key --username azureuser --ssh-key ~/.ssh/id_rsa
# Windows RDP (runs from a Windows client)
az network bastion rdp -g rg-hub -n bas-hub \
--target-resource-id $(az vm show -g rg-app -n vm-win-01 --query id -o tsv)
The CLI error message is usually more specific than the portal's.
7. Check the VM itself
If Bastion connects but login fails, the problem is on the VM:
- RDP disabled, Windows firewall blocking 3389, or the guest is hung. Use Run command or the serial console.
- For Entra ID login, the
AADLoginForWindows/AADSSHLoginForLinuxextension must be installed and the user needs the "Virtual Machine Administrator Login" or "Virtual Machine User Login" role.
az vm run-command invoke -g rg-app -n vm-win-01 --command-id RunPowerShellScript \
--scripts "Get-NetFirewallRule -DisplayGroup 'Remote Desktop' | Select DisplayName,Enabled"
Prevent it next time
- Deploy Bastion and its NSG from a template that already contains the required rules.
- Keep forced-tunnel route tables off AzureBastionSubnet.
- Grant Bastion access through a group that has Reader on the hub and spoke resource groups.
- Turn on Bastion diagnostic logs (BastionAuditLogs) to see who connected and where.
Checklist
- Subnet named AzureBastionSubnet, /26 or larger, no forced tunnelling
- NSG rules complete (or no NSG)
- VM NSG allows 22/3389 from the Bastion subnet
- SKU and native client support match how users connect
- Reader on VM, NIC and Bastion
- Guest OS accepts RDP/SSH