With Server 2025, how do you avoid NTLM authentication for a RDP session originating from a non domain workstation ?

Serge Caron 0 Reputation points
2025-12-06T19:48:13.38+00:00

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 ?

Windows for business | Windows Server | Directory services | User logon and profiles
0 comments No comments
{count} votes

11 answers

Sort by: Most helpful
  1. VPHAN 10,565 Reputation points Independent Advisor
    2025-12-06T20:58:16.07+00:00

    Hi,

    When you install only the RD Gateway role without the full RDS farm (Connection Broker, etc.), the underlying KDC Proxy Service (KpsSvc) is often not automatically configured to listen for generic Kerberos traffic, or it is configured to expect Client Certificate authentication (Smart Card) rather than Password authentication, forcing the fallback to NTLM.

    To achieve Kerberos over HTTPS for a non-domain joined client on Windows Server 2025, you must manually configure the KDC Proxy registry settings and service state.

    Step 1: Configure the KDC Proxy Registry (Server Side)

    By default, the KDC Proxy service might be restricting authentication methods. You need to explicitly allow password-based authentication for the tunnel and define the Kerberos library: On your Server 2025 domain controller (where RDG is running), open regedit. Navigate to: HKLM\SYSTEM\CurrentControlSet\Services\KPSSVC\Settings

    (Note: If the Settings key does not exist, create it.)

    Create/Modify the following DWORD value:

    Name: HttpsClientAuth

    Value: 0

    Create/Modify the following Multi-String Value (REG_MULTI_SZ):

    Name: LibNames

    Value: kerberos.dll

    Step 2: Ensure the KDC Proxy Service is Running: On standalone RDG installations, this service is sometimes set to Manual or not running => Open services.msc. Locate KDC Proxy Server service (KpsSvc). Set the Startup type to Automatic. Start or Restart the service. Restart the Remote Desktop Gateway service as well to ensure it picks up the hook.

    Step 3: Verify the RDP File Configuration (Client Side)

    Your settings look correct, but the syntax must be precise for the client to understand that MyServer.MyDomain.TLD is the authoritative KDC for the realm MYDOMAIN.LOCAL.

    Open your .rdp file in Notepad and ensure these lines are present:

    rdgiskdcproxy:i:1

    kdcproxyname:s:MyServer.MyDomain.TLD

    authentication level:i:2

    Step 4: For a non-domain joined client to trigger the Kerberos process via the proxy, it must know the Realm (Domain) name to request a ticket for.

    Do not use: MyDomain\Administrator

    You MUST use: Administrator@MyDomain.local (UPN Format)

    After applying the registry changes and restarting the services: Connect via the RDP file. Open a Command Prompt on the Windows 10 Client. Run klist. You should see a Kerberos ticket for krbtgt/MYDOMAIN.LOCAL in the list.

    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

    0 comments No comments

  2. Serge Caron 0 Reputation points
    2025-12-07T13:37:59.3366667+00:00

    Hello VPHAN,

    Thank you for your answer.

    In Windows Server 2025, Microsoft sets up a better configuration than what was done in previous versions. There is a detailled capture of the current setup at the bottom of this answer.

    The defaults settings match your answer in Steps 1 and 2.

    In step 3, "authentication level:i:2" is the standard setting meaning "If server authentication fails, show a warning, and choose to connect or refuse the connection".

    This usually refers to the INTERNAL certificate of the server which is self signed. It is the default in my test configuration and I do not get this warning when connecting to MyServer.MyDomain.TLD.

    I know for a fact that this test client can get Kerberos tickets from this test server because, at some point in the testing process, I did get some using the UPN.

    Unfortunately, I can only guess that some detail changed in my configuration and this picture perfect setup does not work!

    Regards,

    The following SPNs are created when installing ONLY the RD Gateway Role in Windows Server 2025

    netsh http show urlacl url="https://+:443/remoteDesktopGateway/"

    netsh http show urlacl url="https://+:443/kdcproxy/"

    The following registry entries are created when installing ONLY the RD Gateway Role in Windows Server 2025 and the KPSSVC service startup is set to automatic:

    Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\KPSSVC

    DependOnService : {rpcss, http}

    Description : @%systemroot%\system32\kpssvc.dll,-101

    DisplayName : @%systemroot%\system32\kpssvc.dll,-100

    ErrorControl : 1

    FailureActions : {128, 81, 1, 0...}

    FailureCommand : not used

    ImagePath : C:\Windows\system32\svchost.exe -k KpsSvcGroup

    ObjectName : NT AUTHORITY\NetworkService

    RebootMessage : not used

    Start : 2

    Type : 32

    Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\KPSSVC\Parameters

    ServiceDll : C:\Windows\system32\kpssvc.dll

    ServiceDllUnloadOnStop : 1

    Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\KPSSVC\Settings

    DisallowUnprotectedPasswordAuth : 0

    HttpsClientAuth : 0

    HttpsUrlGroup : {+:443, , , ...}

    0 comments No comments

  3. VPHAN 10,565 Reputation points Independent Advisor
    2025-12-08T15:15:06.75+00:00

    Hi Serge Caron,

    The fact that you provided the registry dump allows us to pinpoint exactly why the "picture perfect" setup on Server 2025 is still failing to proxy the Kerberos tickets. You are 99% there, but the 1% you are missing is critical for the KDC Proxy service (KpsSvc) to actually function as a proxy for Kerberos traffic.

    Based on your registry dump and the behavior you are describing, here is the solution.

    1. The Missing Registry Key

    You mentioned that the default settings match my previous answer, but looking at your registry dump for HKLM\SYSTEM\CurrentControlSet\Services\KPSSVC\Settings, there is one specific Multi-String value missing.

    Your dump shows:

    DisallowUnprotectedPasswordAuth : 0

    HttpsClientAuth : 0

    HttpsUrlGroup : {+:443, ...}

    It is missing: LibNames

    Without the LibNames value, the KDC Proxy service is running and listening on port 443, but it has not loaded the Kerberos DLL to handle the actual authentication payloads. It is effectively a "hollow" service right now.

    => On your Server 2025 Domain Controller: Open regedit and go to HKLM\SYSTEM\CurrentControlSet\Services\KPSSVC\Settings.

    Create a Multi-String Value (REG_MULTI_SZ) named LibNames.

    Set the value to: kerberos.dll

    Restart the KDC Proxy Server service (KpsSvc).

    1. Client-Side Mapping (The "BYOD" Fix)

    Since your client is a non-domain joined Windows 10 Pro machine, relying solely on the .rdp file directives (kdcproxyname) can sometimes be flaky if the client OS doesn't inherently know that MYDOMAIN.LOCAL belongs to that proxy.

    To "force" the issue and prove Kerberos works, you should manually map the realm on the client using ksetup. This is often required for BYOD scenarios to work reliably.

    => On the Windows 10 Client (Command Prompt as Admin): Map the Realm to the Proxy: Tells the client: "Anytime you need a ticket for MYDOMAIN.LOCAL, go to this HTTPS URL."

    ksetup /addkdc MYDOMAIN.LOCAL MyServer.MyDomain.TLD

    Map the Realm to the KDC (Internal mapping): this helps the client understand that the KDC logic resides at that address.

    ksetup /addkdc MYDOMAIN.LOCAL MyServer.MyDomain.local

    Flush and Test:

    klist purge

    Now try connecting via your RDP file again.

    1. Verify the RDP File "Target"

    For Kerberos to function, the Service Principal Name (SPN) requested by the client must match the machine account in AD.

    Internal Server Name: MyServer.MyDomain.local

    External Name: MyServer.MyDomain.TLD

    In your .rdp file, ensure the connection target is the Internal FQDN: full address:s:MyServer.MyDomain.local

    The client authenticates to the proxy (using the TLD name), but it requests a ticket for the terminal server (the Internal name). If you put the TLD in the full address line, the client will request a ticket for TERMSRV/MyServer.MyDomain.TLD, which does not exist in your Active Directory, causing an immediate fallback to NTLM.

    So,

    Server: Add LibNames = kerberos.dll to the registry.

    Client: Run ksetup /addkdc MYDOMAIN.LOCAL MyServer.MyDomain.TLD.

    Client: Ensure RDP file connects to MyServer.MyDomain.local (Internal Name).

    Once you add that LibNames key, you should see the klist on the client populate with tickets for krbtgt/MYDOMAIN.LOCAL almost immediately upon connection.

    VP

    0 comments No comments

  4. Serge Caron 0 Reputation points
    2025-12-08T21:18:25.5333333+00:00

    Hello VPHAN,

    The Regisgtry keys dump was to display the DEFAULT Windows Server 2025 Standard setup.

    The actual LibNames is created with:

    PS C:\Users\Administrator> $KpsSvcSettingsReg = "HKLM:\SYSTEM\CurrentControlSet\Services\KPSSVC\Settings"

    PS C:\Users\Administrator> New-ItemProperty -Path $KpsSvcSettingsReg -Name "LibNames" -Type MultiString -Value @("kerberos.dll") -Force

    LibNames : {kerberos.dll}

    PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\KPSSVC\Settings

    PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\KPSSVC

    I have enabled Kerberos logging on the server and I can see the client contacting the proxy:

    - <EventData>

    <Data Name="LogonSession">MYDOMAIN\Administrator</Data>

    <Data Name="ClientTime" />

    <Data Name="ServerTime">20:33:17.0000 12/8/2025 Z</Data>

    <Data Name="ErrorCode">0x19</Data>

    <Data Name="ErrorMessage">KDC_ERR_PREAUTH_REQUIRED</Data>

    <Data Name="ExtendedError" />

    <Data Name="ClientRealm" />

    <Data Name="ClientName" />

    <Data Name="ServerRealm">MYDOMAIN</Data>

    <Data Name="ServerName">krbtgt/MYDOMAIN</Data>

    <Data Name="TargetName">krbtgt/MYDOMAIN@MYDOMAIN</Data>

    <Data Name="ErrorText" />

    <Data Name="File">onecore\ds\security\protocols\kerberos\client2\logonapi.cxx</Data>

    <Data Name="Line">1135</Data>

    <Binary>[ ... hex string ... ]</Binary>

    </EventData>

    I am told this KDC_ERR_PREAUTH_REQUIRED message is normal Kerberos behavior but I can see in the NTLM audit log that the logon was downgraded. There are no other Kerberos event logged.

    Of course, no ticket was issued, even if ksetup on the client shows the realm in uppercase and the FQDN of the kdc.

    I can verify that no logon occurs if I add the user to the Protected Users group.

    Is there a way to understand or trace why the authentication is silently downgraded to NTLMv2 ?

    Regards,

    0 comments No comments

  5. VPHAN 10,565 Reputation points Independent Advisor
    2025-12-09T01:46:58.8966667+00:00

    The fact that you see KDC_ERR_PREAUTH_REQUIRED (Event ID 4768 or 4771) on the Server means the Client -> Proxy -> DC path is working perfectly. The "Pipe" is open.

    The "Downgrade to NTLM" is happening because the Client receives the KDC's "Pre-Auth" challenge (which says: "I see you, now encrypt a timestamp with your password hash so I know it's really you") and the Client refuses to answer, dropping the conversation and switching to NTLM.

    As for the trace method you asked to find the "Why," here is the procedure to pinpoint the failure on the client side, along with the solution for a Server 2025 / Windows 10 mismatch.

    1. How to Trace the "Silent Downgrade" (Client Side)

    The server logs won't tell you why the client quit. You must look at the Windows 10 client's decision-making process.

    On your Windows 10 Client: Open Event Viewer (eventvwr.msc). Navigate to Applications and Services Logs > Microsoft > Windows > Security-Kerberos > Operational. Right-click Operational and select Enable Log. Clear the log to remove noise. Attempt the RDP connection again. Refresh the log.

    What to look for:

    Event ID 202 (KDC Proxy): This will show if the proxy handshake (HTTPS) failed.

    Event ID 108: This indicates a generic KDC error.

    Error Code 0x10 (KDC_ERR_PADATA_TYPE_NOSUPP): This is the most common cause in your specific scenario (see "The Solution" below).

    Error Code 0xe (KDC_ERR_ETYPE_NOSUPP): Encryption type mismatch.

    1. Solution: Encryption Type Mismatch

    You are connecting to Windows Server 2025 (which hardens security by disabling RC4 and prioritizing AES) from a non-domain joined Windows 10 client.

    When you use ksetup to add a manual realm, Windows 10 defaults to a "Compatibility Mode" that often fails to negotiate AES-256 with a hardened KDC unless explicitly told that the Realm supports it. When the Server 2025 DC responds to the Pre-Auth request demanding AES encryption, the client panics and drops to NTLM.

    => To fix, run this command on your Windows 10 Client (Admin Command Prompt) to force it to speak AES-256 with your test domain:

    ksetup /SetEncTypeAttr MYDOMAIN.LOCAL AES256-CTS-HMAC-SHA1-96

    After running this, run klist purge and try the connection again.

    1. Verify the Host Mapping

    Even if the UPN is correct (Administrator@MYDOMAIN.LOCAL), the RDP client (mstsc.exe) validates the target server's identity against the realm. If mstsc thinks MyServer.MyDomain.local belongs to the "Public Internet" and not "MYDOMAIN.LOCAL", it won't send the Kerberos reply.

    Verify you have mapped the DNS suffix to the Realm on the client:

    ksetup /addhosttorealmmap .MyDomain.local MYDOMAIN.LOCAL

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.