Home / Azure

AzureTroubleshootingIntermediate

Azure Windows VM not activated: fixing KMS activation errors 0xC004F074 and forced-tunnel routing

Windows VMs in Azure show "Activate Windows" or error 0xC004F074. Check the KMS settings, port 1688, DNS and forced-tunnel routes to azkms.core.windows.net, then fix them.

Deepak Bhardwaj7 min read

Applies toAzure VMs running Windows Server 2012 R2 to 2025 (including Azure Edition) from Azure Marketplace images, Azure public cloud

Symptom

You see one or more of these on a Windows VM in Azure:

  • The "Activate Windows" watermark on the desktop, or Settings > Activation says Windows is not activated.
  • slmgr /ato fails with 0xC004F074 ("No Key Management Service (KMS) could be contacted") or a timeout such as 0x800705B4.
  • Application log events from source Security-SPP (for example event 8198) reporting a failed activation attempt.
  • After a grace period, Windows reminds users to activate and some personalisation settings are locked.

Marketplace Windows images are set up as KMS clients. They activate against the Azure KMS service at azkms.core.windows.net on TCP 1688. That name resolves to 20.118.99.224 and 40.83.235.53. Microsoft moved all Azure VMs to these addresses in 2023, so allow-lists or routes that only cover the old kms.core.windows.net (23.102.135.246) no longer work.

In most cases the VM can't reach those two IPs, usually because of a forced-tunnel route, a firewall rule or custom DNS.

Quick triage table

Symptom / error Likely cause Fix
0xC004F074, TcpTestSucceeded: False 1688 blocked by NSG, Azure Firewall, NVA or guest firewall Allow outbound TCP 1688 to both KMS IPs
0xC004F074, name doesn't resolve Custom DNS server can't resolve azkms.core.windows.net Forward to Azure DNS (168.63.129.16) or a resolver that can
Works in one spoke, fails in another 0.0.0.0/0 route to on-premises or an NVA (forced tunnelling) Add /32 routes with next hop Internet, or allow 1688 on the NVA
0xC004F06C VM clock is badly skewed Fix time sync, then retry
Error about the product key or "not a KMS client" Custom or migrated image with a retail/MAK key Install the right generic volume license key (GVLK)
slmgr /dlv shows the wrong KMS host Old GPO or image sets kms.core.windows.net or an on-prem KMS Point it at azkms.core.windows.net:1688

Checks, without logging in

You can run all of these through Run Command if RDP is not available.

1. Licence status and configured KMS host

az vm run-command invoke -g rg-prod -n vm-app01 \
  --command-id RunPowerShellScript \
  --scripts "cscript //nologo C:\Windows\System32\slmgr.vbs /dlv"

In the output, look at:

  • License Status: Licensed, Initial grace period, Notification.
  • Description: it should contain VOLUME_KMSCLIENT channel. If it says RETAIL or MAK, go to the product key section below.
  • KMS machine name: if it is set to anything other than azkms.core.windows.net:1688, someone has overridden it.

2. Name resolution and port 1688 from inside the VM

Resolve-DnsName azkms.core.windows.net
Test-NetConnection azkms.core.windows.net -Port 1688
Test-NetConnection 20.118.99.224 -Port 1688
Test-NetConnection 40.83.235.53 -Port 1688
  • The name fails to resolve but the IPs connect: this is a DNS problem.
  • The name resolves but TcpTestSucceeded : False: this is a network path problem (steps 3 and 4).
  • Everything succeeds: go to step 5 (time, key, activation command).

3. Effective routes: is 0.0.0.0/0 going somewhere other than the internet?

az network nic show-effective-route-table -g rg-prod -n vm-app01-nic -o table

az network watcher show-next-hop -g rg-prod --vm vm-app01 \
  --source-ip 10.20.1.4 --dest-ip 20.118.99.224

A next hop of VirtualNetworkGateway or VirtualAppliance means the activation traffic goes to on-premises or to a firewall. On-premises proxies normally drop it, because activation traffic must come from an Azure public IP.

4. NSG and firewall rules

az network watcher test-ip-flow -g rg-prod --vm vm-app01 \
  --direction Outbound --protocol TCP \
  --local 10.20.1.4:50000 --remote 20.118.99.224:1688

If the result is Deny, the output names the NSG rule. If traffic goes through Azure Firewall, search its logs for port 1688. Table and column names vary by version (resource-specific or AzureDiagnostics mode), so check what your workspace has:

AZFWNetworkRule
| where TimeGenerated > ago(1d)
| where DestinationPort == 1688
| project TimeGenerated, SourceIp, DestinationIp, Action, Policy, RuleCollection, Rule
| order by TimeGenerated desc

Inside the guest, check that no outbound Windows Firewall rule or third-party agent blocks 1688:

Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultOutboundAction

Fixes

Forced tunnelling: send KMS traffic straight to the internet

Add two /32 routes to the route table on the VM's subnet. A more specific route wins over 0.0.0.0/0.

az network route-table route create -g rg-network --route-table-name rt-spoke-app \
  -n azkms-1 --address-prefix 20.118.99.224/32 --next-hop-type Internet

az network route-table route create -g rg-network --route-table-name rt-spoke-app \
  -n azkms-2 --address-prefix 40.83.235.53/32 --next-hop-type Internet

Warning

A next hop of Internet only works if the VM has outbound access, through NAT Gateway, a public IP or a load balancer outbound rule. On subnets without default outbound access the route alone won't fix it. If your security policy requires all egress to go through the firewall, allow TCP 1688 to both IPs on the firewall instead of bypassing it.

Azure Firewall: allow the flow

az network firewall policy rule-collection-group collection add-filter-collection \
  -g rg-network --policy-name fwpol-hub --rcg-name rcg-platform \
  --name allow-azure-kms --collection-priority 200 --action Allow \
  --rule-type NetworkRule --rule-name azkms \
  --source-addresses 10.0.0.0/8 --ip-protocols TCP \
  --destination-addresses 20.118.99.224 40.83.235.53 --destination-ports 1688

For NSGs that deny outbound internet traffic, add an allow rule for TCP 1688 to the same two IPs, with a lower priority number than the deny rule.

Custom DNS

If your DNS servers can't resolve azkms.core.windows.net, add a forwarder (or a conditional forwarder for core.windows.net) to 168.63.129.16, or to your Azure DNS Private Resolver inbound endpoint. Then run ipconfig /flushdns on the VM.

Wrong KMS host, clock or product key

Reset the KMS host and activate:

cscript //nologo C:\Windows\System32\slmgr.vbs /skms azkms.core.windows.net:1688
cscript //nologo C:\Windows\System32\slmgr.vbs /ato
cscript //nologo C:\Windows\System32\slmgr.vbs /xpr

If a Group Policy or a script keeps setting the old host, fix it at the source, or the problem will come back at the next refresh.

If you see 0xC004F06C, fix the time first:

w32tm /query /status
w32tm /resync /force

For custom or migrated images that are not KMS clients, install the GVLK for the exact edition. Get it from Microsoft's "Key Management Services (KMS) client activation and product keys" page; don't copy keys from forums. Then run /ato:

cscript //nologo C:\Windows\System32\slmgr.vbs /ipk <GVLK-for-your-edition>
cscript //nologo C:\Windows\System32\slmgr.vbs /ato

Caution

Windows Server Datacenter: Azure Edition only activates in supported Azure environments. If you move it to a different host, it won't activate, and no network change can fix that.

Verify across the fleet

After a network change, check many VMs at once:

for vm in $(az vm list -g rg-prod --query "[?storageProfile.osDisk.osType=='Windows'].name" -o tsv); do
  echo "== $vm"
  az vm run-command invoke -g rg-prod -n "$vm" --command-id RunPowerShellScript \
    --scripts "(Get-CimInstance SoftwareLicensingProduct -Filter \"PartialProductKey IS NOT NULL AND Name LIKE 'Windows%'\").LicenseStatus" \
    --query "value[0].message" -o tsv
done

LicenseStatus 1 means licensed. Any other value needs follow-up.

Prevent it next time

  • Put the two KMS /32 routes, or the firewall allow rule, in your hub/spoke templates so every new spoke gets them.
  • Use IP addresses in firewall rules and routes, not only the old kms.core.windows.net name. Review them when Microsoft announces endpoint changes in Service Health.
  • Include Test-NetConnection azkms.core.windows.net -Port 1688 in your VM build validation.
  • Collect the Application log through a data collection rule and alert on Security-SPP activation failures. Event IDs vary by Windows version, so confirm them on one failing VM first.
  • Keep custom images as KMS clients (sysprep from a Marketplace base) so new VMs activate without anyone touching them.