Can’t RDP or SSH to an Azure VM

“Azure VM RDP not working” is one of the most searched Azure problems, and the same steps fix SSH on Linux. The trick is to stop guessing and check the path in order: is the VM up, does Azure let the packet in, does the guest firewall let it in, is the service listening, and do the credentials work.

Each layer has its own tool, and each tool tells you something definite. Test-NetConnection tells you whether TCP gets through. IP flow verify tells you whether an NSG allows it.

Run Command tells you what the guest thinks. Within ten minutes you know which layer is wrong.

In this lab you build a Windows Server VM you can RDP to, then break the NSG and the Windows Firewall, and fix each one from outside the VM.

TimeYou needCostBy the end you can
About 50 minutesA free account, the CLI, PowerShell and Remote Desktop on your laptopAbout 10 US cents: a small Windows VM and a public IP for under an hourFind which layer blocks RDP or SSH in minutes, and fix it without logging in

What it is, in one line

When RDP or SSH fails, check each layer in order: VM state, NSG, guest firewall, service, then credentials.

In Simple Words

Visiting a friend in a gated society

You can’t reach your friend’s flat. Before you complain, check in order. Is your friend at home (VM running)?

Did the society gate let you in (NSG)? Did the building door open (guest firewall)? Is anyone answering the flat’s doorbell (RDP service)?

Do you know the door code (credentials)?

Each check has its own sign. If the gatekeeper turned you away, there’s no point ringing the doorbell louder.

Engineers who jump to “reset the password” first are ringing the doorbell while still standing at the gate.

Engineer's View

The RDP and SSH path, layer by layer

  • VM state: Running, agent Ready, boot finished (Lesson 60 if not).
  • Network path: public IP or Bastion, NSGs on subnet and NIC (both must allow), route tables, and Azure Firewall if traffic goes through a hub.
  • IP flow verify: Network Watcher tests a specific 5-tuple against the effective NSG rules and names the rule that allows or denies it.
  • Guest firewall: Windows Firewall rules “Remote Desktop – User Mode (TCP-In)” (name RemoteDesktop-UserMode-In-TCP); on Linux, ufw, firewalld or iptables for port 22.
  • Service: TermService listening on 3389 (or a changed port); sshd on 22 with a valid config.
  • Credentials: reset with az vm user update (VMAccess extension) for passwords or SSH keys; on Linux, az vm user reset-ssh resets the SSH configuration.
  • Better than public RDP: Bastion or just-in-time access (Lessons 27 and 28). Port 3389 open to the internet is attacked within minutes.

How it works, step by step

How to read the two most useful tests together:

Azure VM RDP not working: the layer-by-layer checklist
  1. Run Test-NetConnection from your laptop to port 3389.
  2. If it succeeds, the network is fine: look at credentials, the RDP client, or the user’s rights.
  3. If it fails, run IP flow verify with your public IP. If it says Deny, the NSG is the problem and it names the rule.
  4. If IP flow verify says Allow but TCP still fails, the packet reaches the VM and something inside drops it: guest firewall or the service.
  5. Use Run Command to check the guest firewall and the listening port, and fix them without logging in.

That split, Azure says allow but TCP fails, is the single most useful clue in this whole lesson.

Reading Test-NetConnection and IP flow verify together

For Linux, swap 3389 for 22, Windows Firewall for ufw or firewalld, and TermService for sshd. The order stays the same.

The same checks for SSH on Linux

The SSH client’s error message already tells you which layer to look at, so read it carefully before doing anything:

SSH errorWhat it meansWhere to look
Connection timed outPackets never got an answerNSG, route tables, public IP, Azure Firewall
Connection refusedThe VM answered, but nothing listens on 22sshd stopped, wrong port, or guest firewall reject
Permission denied (publickey)Network fine, login rejectedUser name, key, authorized_keys permissions
Host key verification failedThe VM was rebuilt with a new host keyRemove the old entry from known_hosts after checking

For the guest checks, Run Command works the same way on Linux, with RunShellScript instead of RunPowerShellScript:

az vm run-command invoke --resource-group <rg> --name <vm> --command-id RunShellScript --scripts 'ss -tlnp | grep :22; ufw status | head -3; sshd -t && echo sshd config ok' --query "value[0].message" -o tsv
az vm user reset-ssh --resource-group <rg> --name <vm>
az vm user update --resource-group <rg> --name <vm> --username azureuser --ssh-key-value ~/.ssh/id_rsa.pub

sshd -t tests the SSH configuration file and prints the exact line that’s wrong. reset-ssh puts the SSH configuration back to defaults, and user update replaces the key for one user. Both use the VMAccess extension, so the VM agent must be Ready.

Build an RDP path and test every layer

1A Windows VM that only your IP can reach

Find your public IP, create the VM, and allow RDP from that IP only (about 5 minutes):

$myIp = (Invoke-RestMethod https://api.ipify.org)
$pw = 'Sv-' + (-join ((65..90) + (97..122) + (48..57) | Get-Random -Count 14 | ForEach-Object { [char]$_ })) + '9!'
az group create --name rg-saat-l61 --location centralindia --tags course=saatvedha-azure lesson=61 -o none
az vm create --resource-group rg-saat-l61 --name vm-win --image Win2022Datacenter --size Standard_B2s --public-ip-sku Standard --nsg-rule NONE --admin-username azureadmin --admin-password $pw --tags course=saatvedha-azure lesson=61 -o none
az network nsg rule create --resource-group rg-saat-l61 --nsg-name vm-winNSG --name allow-rdp-me --priority 100 --direction Inbound --access Allow --protocol Tcp --source-address-prefixes $myIp --destination-port-ranges 3389 -o none
$ip = az vm show --resource-group rg-saat-l61 --name vm-win --show-details --query publicIps -o tsv
$priv = az vm show --resource-group rg-saat-l61 --name vm-win --show-details --query privateIps -o tsv

2Test the path from outside

Check TCP from your laptop and ask Network Watcher what the NSG decides:

Test-NetConnection $ip -Port 3389 -WarningAction SilentlyContinue | Select-Object RemoteAddress, TcpTestSucceeded
az network watcher test-ip-flow --resource-group rg-saat-l61 --vm vm-win --direction Inbound --protocol TCP --local "${priv}:3389" --remote "${myIp}:50000" -o table

You should see something like this:

RemoteAddress  TcpTestSucceeded
-------------  ----------------
20.x.x.x                   True

Access    RuleName
--------  ---------------------------
Allow     securityRules/allow-rdp-me

3Connect

Open Remote Desktop to the VM and sign in as azureadmin with $pw:

mstsc /v:$ip

Accept the certificate warning (the VM uses a self-signed RDP certificate). Sign out when you see the desktop.

Azure VM RDP not working lab: working Remote Desktop session
Remote Desktop session to vm-win, signed in as azureadmin.
Healthy RDP path with TCP success and NSG allow
TCP succeeds and the NSG names the rule that allows you.

✅ Checkpoint: vm-win accepts RDP from your IP only, and you know what a healthy Test-NetConnection and IP flow verify look like.

Break It, Then Fix It

Keep the VM running for both breaks.

1Break it: your IP changed

Home and office internet IPs change. Simulate it by pointing the rule at a different address:

az network nsg rule update --resource-group rg-saat-l61 --nsg-name vm-winNSG --name allow-rdp-me --source-address-prefixes 203.0.113.10 -o none
Test-NetConnection $ip -Port 3389 -WarningAction SilentlyContinue | Select-Object RemoteAddress, TcpTestSucceeded
az network watcher test-ip-flow --resource-group rg-saat-l61 --vm vm-win --direction Inbound --protocol TCP --local "${priv}:3389" --remote "${myIp}:50000" -o table

You should see something like this:

RemoteAddress  TcpTestSucceeded
-------------  ----------------
20.x.x.x                  False

Access    RuleName
--------  ----------------------------------
Deny      defaultSecurityRules/DenyAllInBound

TCP fails and Azure says Deny, naming the default rule. The NSG doesn’t know your current IP. Resetting the password or restarting the VM would change nothing.

Fix it: update the rule to your current IP, then test again:

$myIp = (Invoke-RestMethod https://api.ipify.org)
az network nsg rule update --resource-group rg-saat-l61 --nsg-name vm-winNSG --name allow-rdp-me --source-address-prefixes $myIp -o none
Test-NetConnection $ip -Port 3389 -WarningAction SilentlyContinue | Select-Object RemoteAddress, TcpTestSucceeded

TcpTestSucceeded is True again. For people whose IP changes often, Bastion or just-in-time access is the lasting fix.

2Break it: Azure allows it, the VM doesn’t

Someone “hardens” the server and disables the Remote Desktop firewall rules inside Windows:

az vm run-command invoke --resource-group rg-saat-l61 --name vm-win --command-id RunPowerShellScript --scripts 'Disable-NetFirewallRule -Name RemoteDesktop-UserMode-In-TCP,RemoteDesktop-UserMode-In-UDP' --query "value[0].message" -o tsv
Test-NetConnection $ip -Port 3389 -WarningAction SilentlyContinue | Select-Object RemoteAddress, TcpTestSucceeded
az network watcher test-ip-flow --resource-group rg-saat-l61 --vm vm-win --direction Inbound --protocol TCP --local "${priv}:3389" --remote "${myIp}:50000" -o table

You should see something like this:

RemoteAddress  TcpTestSucceeded
-------------  ----------------
20.x.x.x                  False

Access    RuleName
--------  ---------------------------
Allow     securityRules/allow-rdp-me

Azure says Allow, yet TCP fails. The packet reaches the VM and something inside drops it. That rules out the whole Azure network in one step.

Check the guest firewall and the listener from outside, then fix it:

az vm run-command invoke --resource-group rg-saat-l61 --name vm-win --command-id RunPowerShellScript --scripts 'Get-NetFirewallRule -Name RemoteDesktop-UserMode-In-TCP | Select-Object Name, Enabled; Get-NetTCPConnection -LocalPort 3389 -State Listen | Select-Object LocalPort, State' --query "value[0].message" -o tsv
az vm run-command invoke --resource-group rg-saat-l61 --name vm-win --command-id RunPowerShellScript --scripts 'Enable-NetFirewallRule -Name RemoteDesktop-UserMode-In-TCP,RemoteDesktop-UserMode-In-UDP' --query "value[0].message" -o tsv
Test-NetConnection $ip -Port 3389 -WarningAction SilentlyContinue | Select-Object RemoteAddress, TcpTestSucceeded

You should see something like this:

Name                            Enabled
----                            -------
RemoteDesktop-UserMode-In-TCP     False

LocalPort  State
---------  -----
     3389 Listen

RemoteAddress  TcpTestSucceeded
-------------  ----------------
20.x.x.x                   True

The service was listening all along; only the firewall rule was off. After enabling it, RDP works again.

RDP blocked by Windows Firewall while the NSG allows it
Azure says Allow, so the block is inside Windows.

3Clean up

Delete the lab resource group:

az group delete --name rg-saat-l61 --yes

✅ Checkpoint: You told an NSG block from a guest firewall block with two commands, and fixed both without logging in.

This happened at work

The RDP port that moved

A bank’s security team changed the RDP port on all Windows servers from 3389 to 50133 through Group Policy, to “reduce scanning”. The NSGs still allowed 3389. After the next policy refresh, the operations team couldn’t reach any server, and the change ticket had been closed as “no impact”.

IP flow verify on 3389 said Allow, so the NSGs looked fine. Test-NetConnection on 3389 failed. A Run Command with Get-NetTCPConnection showed the listener on 50133, not 3389.

The servers were healthy; they were simply listening somewhere else.

What they changed: RDP back to 3389, reachable only through Azure Bastion, with no public RDP at all. Changing ports was replaced by removing exposure. The change process now asks “which network rules depend on this setting?” for any guest-level security change.

Common mistakes and troubleshooting

MistakeWhat you seeWhat to do
Resetting the password firstStill can’t connectTest TCP and IP flow verify before touching credentials.
Rule on NIC NSG but subnet NSG deniesIP flow verify DenyBoth NSGs must allow; check effective rules.
Guest firewall rule disabledAzure Allow, TCP failsCheck with Run Command and re-enable the rule.
RDP port changed in the guestAllow on 3389 but nothing listensCheck the listening port; align NSG or revert.
Home IP changedDeny by DenyAllInBoundUpdate the source IP or use Bastion or JIT.
Linux sshd_config brokenConnection refused on 22az vm user reset-ssh or fix via Run Command.

Interview questions

Click a question to open it. Each one is written the way an interviewer would ask it. Under it you will see why they ask it and one way you could answer, in your own words.

Fresher level

1. A user can’t RDP to a VM. What do you check first?

Why they ask this: The basic method.

How you might answer: That the VM is running, then whether TCP 3389 gets through with Test-NetConnection, then the NSG with IP flow verify.

2. What is IP flow verify?

Why they ask this: Tool knowledge.

How you might answer: A Network Watcher test that checks a specific source, destination, port and protocol against effective NSG rules and names the matching rule.

3. How do you reset a forgotten admin password?

Why they ask this: A practical task.

How you might answer: az vm user update or the portal’s Reset password, which use the VMAccess extension; the VM agent must be running.

2–5 years experience

4. IP flow verify says Allow, but RDP fails. Why?

Why they ask this: A real troubleshooting path.

How you might answer: The packet reaches the VM, so the guest drops it: Windows Firewall, a changed RDP port, a stopped service, or third-party security software. Check with Run Command.

5. RDP gives “An internal error has occurred”. What could it be?

Why they ask this: Experience question.

How you might answer: RDP certificate or TLS problems, a full disk, licensing in RDS setups, or CredSSP mismatches. Check event logs through Run Command and the boot screenshot.

6. How do you troubleshoot SSH on Linux the same way?

Why they ask this: Parity check.

How you might answer: Test TCP 22, IP flow verify, check ufw or firewalld, sshd status and sshd_config, then reset the SSH key or configuration with az vm user commands.

Senior level

7. How should administrators reach VMs in production?

Why they ask this: They want secure design.

How you might answer: No public RDP or SSH. Azure Bastion or a VPN, just-in-time access, Entra ID login with MFA, and NSGs that allow management only from the Bastion subnet or a jump host.

8. How do you troubleshoot at scale when 100 VMs lose RDP?

Why they ask this: Scale thinking.

How you might answer: Look for the common change: GPO, NSG, route or firewall update in the Activity log, then test a sample with IP flow verify and Run Command, and roll back the shared change.

9. What do you check when RDP through Bastion fails?

Why they ask this: Bastion depth.

How you might answer: Bastion subnet NSG rules, VM NSG allowing the Bastion subnet, the VM’s guest firewall, and whether the SKU supports the connection method being used.

Quick quiz

Q1. Test-NetConnection fails and IP flow verify says Deny. Problem is?

  1. Guest firewall
  2. An NSG
  3. Password
  4. DNS
Show answer

B — The NSG blocks the packet.

Q2. IP flow verify Allow but TCP fails. Look where?

  1. NSG
  2. Inside the guest
  3. Route table
  4. Subscription
Show answer

B — The packet reached the VM.

Q3. Which tool resets a VM password without logging in?

  1. az vm restart
  2. az vm user update
  3. az vm redeploy
  4. az network nsg
Show answer

B — It uses the VMAccess extension.

Q4. Windows Firewall rule name for RDP TCP?

  1. RDP-Allow
  2. RemoteDesktop-UserMode-In-TCP
  3. TermService-In
  4. Port3389
Show answer

B — That’s the built-in rule name.

Q5. Best long-term way to avoid IP-based NSG rules for admins?

  1. Open 3389 to all
  2. Bastion or JIT
  3. Change the port
  4. Disable NSGs
Show answer

B — Remove public RDP exposure.

Quick recap

You can now find the broken layer behind any RDP or SSH ticket in minutes, and fix it from outside.

  • Check VM, NSG, guest firewall, service, then credentials.
  • Test-NetConnection says whether TCP gets through.
  • IP flow verify says whether the NSG allows it and which rule.
  • Azure Allow plus TCP failure means the guest is blocking.
  • Use Bastion or JIT instead of public RDP and SSH.

Next lesson

Lesson 62: Network Watcher: IP flow verify and Next hop → You use Network Watcher’s IP flow verify, next hop, connection troubleshoot and VNet flow logs to prove where packets go.

Further reading: Azure VM RDP not working

Want to go deeper into Azure VM RDP not working? See Microsoft’s Troubleshoot Remote Desktop connections to an Azure VM and IP flow verify overview. You can also see the full plan for this course on the Azure Cloud Administration course page.

Scroll to Top