Hi Serge Caron,
How was the issue? It seems your previous answer has been deleted. I could not read it.
VP
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
In order to reduce complexity, I am using a test domain consisting of a single domain controller ON PREMISES and a single user, the domain administrator.
There is a single role installed: Remote Desktop Gateway. None of the other 5 RDS roles are installed. Direct Access and/or VPNs are not allowed in this test.
The AD domain is MyDomain.local and the internal FQDN is MyServer.MyDomain.local
There is a Let's Encrypt certificate installed on this server for MyServer.MyDomain.TLD.
Finally, there is a single port 443 forwarded to the server from the firewall.
I can RDP into this server from the Internet to MyServer.MyDomain.local via RDG MyServer.MyDomain.TLD.
However, all logons are downgraded to NTLMv2 even if I set
rdgiskdcproxy:i:1
kdcproxyname:s:MyServer.Mydomain.TLD
In this test case, I am using a non domain joined Windows 10 Pro client (even if I know it is deprecated): we need to demonstrate RDG working with BYOD, including non Windows devices.
Is there a way to do this in Windows Server 2025 ?
Hi Serge Caron,
How was the issue? It seems your previous answer has been deleted. I could not read it.
VP
Hello VPHAN,
I have a glass full / glass empty type of result.
Once the SPN for the HTTP/fqdn is created for MYSERVER, the RDP client connects sucessfully.
Before I go on, I have beefed up the Poor Man's config script for these clients and will provide a final version when this can be reused for anyone who has this issue. See below ;-)
Now, I do not see any event in the server's NTLM Audit Log for a successful logon and I do see the details of the connection in the Remote Destop Gateway Console.
I also do not see any event in the Security-Kerberos Operational Log (LogLevel is set to 1 on this servver): somehow, I find this disturbing knowing that a ticket was granted.
I made sure that the only user in this domain (Administrator) is a member of the Protected Users group and redid the tests: all OK.
Now, for the empty part: there are no tickets received by the client. Obviously, RDP does not create a endpoint on the network and the client will not communicate directly with any ressource on the network other than the RDG. So, are we chasing a Kerberos ticket that will never be delivered ?
Regards,
Here is the beefed up script (it can suffer some beautyfying ;-):
$Realm = Read-Host "Please enter the remote Active Directory domain name (not the NetBIOS domain name)"
$KdcFQDN = Read-Host "Please enter the fully qualified domain name (FQDN) of the Remote Desktop Gateway"
### Make sure proper case is used in these namespaces
$KdcFQDN = $KdcFQDN.ToLOWER()
$Realm = $Realm.ToUPPER()
### Warn if IIS is not reachable on $KdcFQDN
If ( -Not $(Test-NetConnection -ComputerName $KdcFQDN -Port 443) ) {
Write-Warning "HTTPS is not enabled on $KdcFQDN"
}
### Location of Kerberos keys
$KerberosLSA = "HKLM:\SYSTEM\CurrentControlSet\Control\LSA\Kerberos"
$KerberosPolicies = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies\System\Kerberos\Parameters"
### Delete this realm and dump actual configuration
ksetup /DelHostToRealmMap ".$Realm" "$Realm" # /RemoveRealm will not remove duplicate mappings
ksetup /RemoveRealm $Realm
ksetup /DumpState
## Host to Realm
ksetup /AddHostToRealmMap ".$Realm" "$Realm"
If ( (Get-ItemProperty -Path "$KerberosLSA\HostToRealm\$Realm").SpnMappings.Count -eq 2 ) {
If ( ((Get-ItemProperty -Path "$KerberosLSA\HostToRealm\$Realm").SpnMappings[0] -ceq ".$Realm") `
-and ("" -eq (Get-ItemProperty -Path "$KerberosLSA\HostToRealm\$Realm").SpnMappings[1] ) ) {
Write-Host "Standard mapping for $Realm"
} else { Write-Warning "Registy entries for $Realm mapping not managed by ksetup" }
} else { Write-Warning "More than one mapping defined for $Realm" }
### KDC
ksetup /addkdc "$Realm" $KdcFQDN
If ( (Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm").KdcNames.Count -eq 2 ) {
If ( ((Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm").KdcNames[0] -ceq $KdcFQDN) `
-and ("" -eq (Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm").KdcNames[1]) ) {
Write-Host "Standard KDC setup for $Realm"
} else { Write-Warning "Registy entries for $Realm KDC not managed by ksetup" }
} else { Write-Warning "More than one KDC defined for $Realm" }
### Encryption Types
$EncTypes = ksetup /Domain $Realm /SetEncTypeAttr AES-256-CTS-HMAC-SHA1-96 AES-128-CTS-HMAC-SHA1-96
Try { Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm" -Name SupportedEncryptionTypes -ErrorAction Stop | `
Select-Object -ExpandProperty SupportedEncryptionTypes | Format-Table
}
Catch { Write-Warning "ksetup failed to create encryption attributes for $Realm"
New-ItemProperty -Path "$KerberosLSA\Domains\$Realm" -Name "SupportedEncryptionTypes" -PropertyType DWORD -Value 24 -Force | `
Select-Object SupportedEncryptionTypes | Format-Table -HideTableHeaders
}
If ( (Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm").SupportedEncryptionTypes -ne `
(Get-ItemProperty -Path "$KerberosPolicies").SupportedEncryptionTypes ) {
Write-Warning "Encryption types for $Realm do not match default Kerberos policies for this computer."
}
### LogLevel
Write-Host "Kerberos Log Level", (Get-ItemProperty -Path "$KerberosLSA\Parameters").LogLevel
### Final configuration
ksetup /DumpState
Hi Serge Caron,
You've done a great job!! However, the solution is staring us in the face within the setspn output you provided. If you look closely at the command you ran and the subsequent output, the issue is not a technical mystery of Windows Server 2025, but a simple syntax oversight during the registration attempt.
In your console output, you executed: setspn -S HTTP/MyServer.MyDomain.local MYSERVER. The system correctly responded with "Duplicate SPN detected, operation aborted" because, as shown in the dump lines immediately preceding it, HTTP/MyServer.MyDomain.local already exists on the object.
Crucially, HTTP/MyServer.MyDomain.TLD is completely missing from that list.
The RD Gateway / KDC Proxy authentication process is extremely strict regarding the "Front Door." When the client connects, it does not care about the internal AD name yet; it is talking to the public URL defined in the gateway settings. The client requests a ticket for HTTP/MyServer.MyDomain.TLD. Active Directory looks at the CN=MYSERVER object, sees HTTP/Internal, TERMSRV/Internal, and HOST/Internal, but it does not find HTTP/ExternalTLD. Consequently, it returns 0x7 (Principal Unknown), and the client correctly aborts the Kerberos exchange.
You must run the command specifically for the external address. Please open the Administrator Command Prompt on your DC and run: setspn -S HTTP/MyServer.MyDomain.TLD MYSERVER
Once you run this, verify it immediately with setspn -L MYSERVER. You must see the TLD variant explicitly listed in the output. As soon as that entry appears, your Windows 10 client, with its current registry configuration, will successfully obtain the service ticket for the proxy, establish the tunnel, and then proceed to obtain the TERMSRV ticket for the RDP session.
I hope you've found something useful here. If it helps you get more insight into the issue, it's appreciated to accept the answer then. Should you have more questions, feel free to leave a message. Have a nice day!
VP
Hello VPHAN,
Rather than rely on expected behavior from ksetup and/or direct RegEdit modifications, I decided to go for a "belt and suspenders" script.
Here is the script (you need to edit the first two lines to define the Realm and the FQDN of the KDC): see other comments below.
$Realm = "MYDOMAIN.LOCAL"
$KdcFQDN = "MyServer.MyDomain.TLD"
### Make sure proper case is used in these namespaces
$KdcFQDN = $KdcFQDN.ToLOWER()
$Realm = $Realm.ToUPPER()
### Location of Kerberos keys
$KerberosLSA = "HKLM:\SYSTEM\CurrentControlSet\Control\LSA\Kerberos"
$KerberosPolicies = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies\System\Kerberos\Parameters"
### Delete this realm and dump actual configuration
ksetup /DelHostToRealmMap ".$Realm" "$Realm" # /RemoveRealm will not remove duplicate mappings
ksetup /RemoveRealm $Realm
ksetup /DumpState
## Host to Realm
ksetup /AddHostToRealmMap ".$Realm" "$Realm"
(Get-ItemProperty -Path "$KerberosLSA\HostToRealm\$Realm").SpnMappings.Count
(Get-ItemProperty -Path "$KerberosLSA\HostToRealm\$Realm").SpnMappings[0] -eq ".$Realm"
"" -eq (Get-ItemProperty -Path "$KerberosLSA\HostToRealm\$Realm").SpnMappings[1]
### KDC
ksetup /addkdc "$Realm" $KdcFQDN
(Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm").KdcNames.Count
(Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm").KdcNames[0] -eq $KdcFQDN
"" -eq (Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm").KdcNames[1]
### Encryption Types
New-ItemProperty -Path "$KerberosLSA\Domains\$Realm" -Name "SupportedEncryptionTypes" -PropertyType DWORD -Value 24 -Force | `
Select-Object SupportedEncryptionTypes
(Get-ItemProperty -Path "$KerberosLSA\Domains\$Realm").SupportedEncryptionTypes -eq (Get-ItemProperty -Path "$KerberosPolicies").SupportedEncryptionTypes
### LogLevel
(Get-ItemProperty -Path "$KerberosLSA\Parameters").LogLevel
### Final configuration
ksetup /DumpState
Comments:
With this configuration in place, the client still reports Event ID 100, error code 0x07, missing spn HTTP/MyServer.MyDomain.TLD@MYDOMAIN.LOCAL.
On the server, I have the following SPNs in place: I did the duplicate HTTP entry out of desperation ;-)
PS C:\Users\Administrateur> setspn -S HTTP/MyServer.MyDomain.local MYSERVER
Vérification du domaine DC=MyServer,DC=local
CN=MYSERVER,OU=Domain Controllers,DC=MyServer,DC=local
HTTP/MyServer.MyDomain.local
HTTP/MyServer.MyDomain.local@MYDOMAIN.LOCAL
TERMSRV/MYSERVER
TERMSRV/MyServer.MyDomain.local
Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/MyServer.MyDomain.local
ldap/MyServer.MyDomain.local/ForestDnsZones.MYDOMAIN.LOCAL
ldap/MyServer.MyDomain.local/DomainDnsZones.MYDOMAIN.LOCAL
DNS/MyServer.MyDomain.local
GC/MyServer.MyDomain.local/MYDOMAIN.LOCAL
RestrictedKrbHost/MyServer.MyDomain.local
RestrictedKrbHost/MYSERVER
RPC/068ad705-a4dd-4de4-9ca2-84103dc61040._msdcs.MYDOMAIN.LOCAL
HOST/MYSERVER/MYDOMAIN
HOST/MyServer.MyDomain.local/MYDOMAIN
HOST/MYSERVER
HOST/MyServer.MyDomain.local
HOST/MyServer.MyDomain.local/MYDOMAIN.LOCAL
E3514235-4B06-11D1-AB04-00C04FC2DCD2/068ad705-a4dd-4de4-9ca2-84103dc61040/MYDOMAIN.LOCAL
ldap/MYSERVER/MYDOMAIN
ldap/068ad705-a4dd-4de4-9ca2-84103dc61040._msdcs.MYDOMAIN.LOCAL
ldap/MyServer.MyDomain.local/MYDOMAIN
ldap/MYSERVER
ldap/MyServer.MyDomain.local
ldap/MyServer.MyDomain.local/MYDOMAIN.LOCAL
Détection d'un SPN en double, opération abandonnée.
PS C:\Users\Administrateur>
And I still did not see a kerberos ticket on the client.
Regards,
PS: I updated the server with the december 20205 patch tuesday updates.
Hi,
I think we are dealing with two distinct issues here, so it is crucial to separate them to avoid chasing ghosts.
Error 0x7 (Server Side): The client cannot find the Service Principal Name (SPN). This is a hard blocker in Active Directory.
Error 0xc0000034 (Client Side): The ksetup tool is buggy when running on non-domain joined machines (Workgroup) because it fails to properly handle handles for LSA objects that don't fully exist in a local SAM context.
We will bypass the buggy ksetup tool by manipulating the registry directly, and we will fix the SPN.
Phase 1: Bypass the ksetup 0xc0000034 Error
Since ksetup is failing to write the encryption attributes because of an "Object Name Not Found" error (likely looking for a domain policy object that doesn't exist in a workgroup), we will inject the configuration directly into the registry where ksetup is supposed to put it.
Open PowerShell as Administrator on your Windows 10 Client and run this.
$RealmPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Domains\MYDOMAIN.LOCAL"
New-ItemProperty -Path $RealmPath -Name "SupportedEncryptionTypes" -PropertyType DWORD -Value 24 -Force
After running this, run ksetup /DumpState. You should now see the encryption types listed, proving the configuration has been accepted by the LSA.
Phase 2: The Critical SPN Fix (Error 0x7)
You mentioned the client log showed KDC_ERR_S_PRINCIPAL_UNKNOWN (0x7) regarding HTTP/MyServer.MyDomain.TLD.
You can't skip this step. Even if the client is perfectly configured, if Active Directory does not know that the URL MyServer.MyDomain.TLD belongs to your Domain Controller, it will reject the ticket request immediately. This is why you see the 0x7 error.
On your Server 2025 Domain Controller (Admin Cmd), run:
setspn -S HTTP/MyServer.MyDomain.TLD MyServer
(Replace MyServer at the very end with the actual NetBIOS name of the server object in AD if it is different).
Phase 3: Final Verification Steps
Once the Registry key is injected on the client and the SPN is registered on the server:
Flush Client Cache:
klist purge
Verify Host Mapping: Ensure the registry has the host mapping. Check HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\HostToRealm. You should see a value named .MyDomain.local containing MYDOMAIN.LOCAL. If not, create it manually via regedit to bypass any ksetup silence.
Connect: Launch your RDP file.
Windows 10 Workgroup clients rely on the KDC Proxy to "tunnel" the Kerberos request. The Client asks: "I need a ticket for HTTP/MyServer.MyDomain.TLD".
The KDC (Server) looks up that name. Without setspn, it returns "Unknown Principal" (0x7).
If setspn is present, the KDC replies with a Ticket.
The Client then uses that ticket to establish the HTTP tunnel.
Inside the tunnel, the Client requests a ticket for TERMSRV/MyServer.MyDomain.local (the internal name).
By manually setting the Registry key on the client, you force the client to propose AES encryption during that first handshake, preventing the downgrade to NTLM caused by protocol mismatch.
VP