Troubleshoot Azure Windows VM RDP failures by checking NSGs, routes, guest firewall, RDP service and Azure VM health.
Work outward from the VM itself (boot state, agent health) through Azure networking (NSG, routes) to the guest OS firewall and RDP service.
Use Azure Bastion or serial console to reach the VM when RDP itself is the thing broken — don't rely on RDP to fix RDP.
Review boot diagnostics and resource health before focusing on RDP.
Check Azure VM health before touching networking
Confirm the VM is actually running and the guest agent is responsive — an RDP failure that's really a stopped VM or an unresponsive agent will waste time if you start with NSG rules instead:
Get-AzVM -ResourceGroupName "RG" -Name "VMName" -Status | Select-Object -ExpandProperty Statuses
Look for PowerState/running and VM running/ProvisioningState/succeeded. If the guest agent shows as unresponsive, boot diagnostics (Azure Portal → VM → Boot diagnostics → Screenshot) will tell you whether the VM is actually stuck at a Windows logon screen, stuck applying updates, or genuinely hung — three very different problems that all present as "can't RDP."
Check network security groups
Confirm TCP 3389 is allowed from the actual source you're connecting from — not just that an "Allow RDP" rule exists somewhere:
Get-AzNetworkSecurityGroup -ResourceGroupName "RG" -Name "NSGName" |
Get-AzNetworkSecurityRuleConfig | Where-Object { $_.DestinationPortRange -contains '3389' }
Check both the subnet-level and NIC-level NSG if both exist — a rule allowing traffic at one level doesn't help if a higher-priority deny exists at the other. Azure's Network Watcher → IP flow verify tool is the fastest way to confirm which specific rule is actually blocking traffic rather than reading rule priorities manually.
Check routing
If the subnet has a custom route table (common when traffic is forced through an Azure Firewall or third-party NVA for inspection), confirm the route for the client's source range doesn't send RDP traffic somewhere it can't return from — asymmetric routing is a frequent, hard-to-spot cause of "connects then hangs" RDP behavior specifically (as opposed to an immediate refused connection, which is usually NSG).
Check the guest OS without relying on RDP
Use Run Command (doesn't require network connectivity to the VM — it goes through the Azure guest agent channel) to check the actual RDP service and firewall state from inside the VM:
Invoke-AzVMRunCommand -ResourceGroupName "RG" -VMName "VMName" -CommandId 'RunPowerShellScript' -ScriptString "Get-Service TermService; Get-NetFirewallRule -DisplayGroup 'Remote Desktop' | Select DisplayName,Enabled"
This is the single most useful step when NSGs and routing both look correct — it tells you definitively whether the problem is inside the guest (service stopped, firewall disabled, RDP port changed in the registry) rather than in Azure networking.
Test from the client side
Confirm the actual TCP path from where you're connecting:
Test-NetConnection -ComputerName <public-or-private-ip> -Port 3389
If this fails but Run Command confirmed TermService is running and the guest firewall allows it, the block is happening in Azure networking (NSG or route) or somewhere on your local network/VPN — not on the VM.
Validate and clean up
After the fix, retest RDP from the actual client that originally failed, not just from a jump box that may already have broader access. If you added a temporary broad NSG rule (e.g., allowing 3389 from Any) to isolate the problem, remove it once confirmed — leaving RDP open to the internet is one of the most common sources of brute-force compromise on Azure VMs.