Share via

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

Serge Caron 25 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

Answer accepted by question author

VPHAN 34,635 Reputation points Independent Advisor
2025-12-19T17:36:53.1433333+00:00

Hi Serge Caron,

How was the issue? It seems your previous answer has been deleted. I could not read it.

VP

Was this answer helpful?

1 person found this answer helpful.
0 comments No comments

44 additional answers

Sort by: Most helpful
  1. Serge Caron 25 Reputation points
    2025-12-19T00:46:03.9666667+00:00

    Hello VPHAN,

    The following code fixes the "cosmetic" issue (I prefer using PowerShell so I can integrate this with the code renewing the certificate): the $Thumprint variable is set at the begining of the script.

    			### See "Configure Remote Desktop server listener certificate" on Microsoft
    			$RDServerListener = "HKLM:SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
    			$ThumbprintBinary = [byte[]] -split ($Thumbprint -replace '..', '0x$& ')
    			New-ItemProperty -Path $RDServerListener -Name SSLCertificateSHA1Hash -Type Binary -Value $ThumbprintBinary -Force
    			### Force a restart of Terminal Services
    			Try {
    				# Note to self: this should be done recursively ;-(
    				Stop-Service -Name UmRdpService -ErrorAction Stop
    				Restart-Service -Name TermService -ErrorAction Stop
    				Start-Service -Name UmRdpService -ErrorAction Stop
    			}
    			Catch {
    					Write-Warning "Restart Service TermService [$((Get-Service -Name TermService).DisplayName)]"
    					Write-Warning "Restart Service UmRdpService [$((Get-Service -Name UmRdpService).DisplayName)]"
    			}
    

    I now see the characteristic padlock when connecting to the RDG.

    I don't have as much luck with the NTLM fallback.

    My understanding is that the SPNs are stored in AD. I can see the same results on both the DC and the RDG:

            HTTP/myserver.mydomain.tld
            WSMAN/MyServer
            WSMAN/MyServer.mydomain.tld
            TERMSRV/MYSERVER
            TERMSRV/MyServer.mydomain.tld
            RestrictedKrbHost/MYSERVER
            HOST/MYSERVER
            RestrictedKrbHost/MyServer.mydomain.tld
            HOST/MyServer.mydomain.tld
    

    Notice the "MyServer" capitalization of a few entries: at this point, I suspect anything and everything.

    Since setting the encryption types on the RDG, the machine password has been reset three times.

    What else am I missing ?

    Regards,

    Was this answer helpful?

    0 comments No comments

  2. VPHAN 34,635 Reputation points Independent Advisor
    2025-12-18T18:28:13.4766667+00:00

    Hi,

    First off, maximum respect for your 54 years in the trenches. You diagnosed the "Red Zone" correctly: by strictly enforcing 0x18 (AES-Only) on the DC account without a prior krbtgt and machine key rotation, the DC lost the ability to validate its own historic identity keys (which were likely RC4-based). Re-enabling 0x1C (AES + RC4) was the correct field triage to stop the bleeding.

    To answer your specific question about the self-signed certificate: Yes, we know exactly why it behaves this way, and it is the definitive symptom of your NLA failure.

    1. Why the Certificate is Reissued (The Mechanism)

    The certificate located in Cert:\localmachine\Remote Desktop\ is controlled by the Remote Desktop Configuration service (SessionEnv) and the TermService logic. On every service startup, Windows checks the SSL certificate bound to the RDP-TCP listener (Port 3389). If no certificate is explicitly defined by the administrator, or if the defined certificate is invalid/missing, the OS automatically generates a Self-Signed Certificate to ensure the RDP stream is encrypted. This is why it comes back when deleted. The system treats an unencrypted RDP listener as a security violation and "fixes" it immediately by minting a new self-signed cert.

    1. Seeing this certificate is the "Check Engine Light" for Network Level Authentication (NLA) failure.

    Scenario A (Success): If Kerberos works, NLA authenticates the user inside the encrypted tunnel using the Ticket. The session is established securely before the screen loads. You rarely see the underlying RDP cert.

    Scenario B (Your Case): The specific artifact MYDOMAIN\UPN confirms that Kerberos failed. The client fell back to NTLM.

    The NTLM handshake failed (likely because the Gateway passed the UPN ******@domain.tld to the legacy NTLM provider, which blindly prepended the NetBIOS domain, creating the invalid user MYDOMAIN\******@domain.tld). Because NLA failed, the RDP client dropped down to Standard RDP Security (TLS/SSL). In this mode, the Server must present its certificate to the Client to start the channel. Since the RDP Listener is using the default auto-generated cert, your client sees the "Untrusted / Self-Signed" warning.

    To fix, step 1: Bind the Valid Certificate (Cosmetic Fix). You can force the RDP Listener to use the same trusted Public Certificate you use for the Gateway. This stops the certificate warning, though it won't fix the authentication failure. Run this wmic command (Admin CMD) on the RDG/Target server, using the Thumbprint of your valid Public Cert:

    DOS

    wmic /namespace:\root\cimv2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash="YOUR_CERT_THUMBPRINT_HERE"

    Restart the Remote Desktop Services service after running this.

    Step 2: Fix the Kerberos Target (Root Cause): The fact that you are getting NTLM fallback on the RDG connection implies the Client cannot get a Service Ticket for TERMSRV/RDG.FQDN. You checked the DC, but check the RD Gateway Machine Object in AD.

    Since you are migrating to AES, ensure the RD Gateway Computer Object has msDS-SupportedEncryptionTypes set to 24 (decimal) or 0x18 (hex).

    If the RD Gateway machine account password hasn't been reset since you started enforcing AES, it might still hold only RC4 keys.

    Reset the Computer Account password for the RD Gateway. This will generate fresh AES keys in ntds.dit for the TERMSRV/ principal.
    VP

    Was this answer helpful?

    0 comments No comments

  3. Serge Caron 25 Reputation points
    2025-12-18T17:57:57.8533333+00:00

    After 54 years in this business, I live in Red Zone.

    I followed your attempts to force the hand of the NLASVC/Kerberos initialization. I even added the old trick of setting the NLASVC to "automatic (delayed start)". All of this while thinking, again, this is a mundane thing that happened during testing.

    It turns out I had set the supported encryption type to 0x18 on the DC. Allowing RC4 again (0x1C) allowed the DC to welcome Kerberos again. The TGT notes RC4 for encryption but AES-256 for the session key.

    #0>     Client : MyAdmin @ MYDOMAIN.TLD
            Serveur : krbtgt/MYDOMAIN.TLD @ MYDOMAIN.TLD
            Type de chiffrement KerbTicket : RSADSI RC4-HMAC(NT)
            Indicateurs de tickets 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
            Heure de démarrage : 12/18/2025 11:27:15 (Local)
            Heure de fin :   12/18/2025 21:27:15 (Local)
            Heure de renouvellement : 12/25/2025 11:27:15 (Local)
            Type de clé de session : AES-256-CTS-HMAC-SHA1-96
            Indicateurs de cache : 0x1 -> PRIMARY
            KDC appelé : MYSERVER
    

    On my test rig, AES-256 is used for the KerbTicket encryption. This needs some sorting out.

    In the meantime, lesson learned. I have added the following code in my script to enumerate RC4 compatible objects and AES only objects so I can plan migration:

    		### List all objects supporting RC4
    		$RC4SupportedObjects = Get-ADObject -Filter "msDS-supportedEncryptionTypes -bor 0x04"
    		If ($RC4SupportedObjects.Count) {
    			Write-Warning "Encryption type RC4 is still supported on these AD objects:"
    			$RC4SupportedObjects | Format-Table Name, ObjectClass, ObjectGUID -AutoSize
    			Write-Warning ""
    		} else { Write-Warning "No RC4 Encryption supported on this domain. Kerberos may be impacted." }
    		### List all objects supporting only AES128-CTS-HMAC-SHA1-96, AES256-CTS-HMAC-SHA1-96
    		$AESSupportedObjects = Get-ADObject -Filter "msDS-supportedEncryptionTypes -eq 0x18"
    		If ($AESSupportedObjects.Count) {
    			Write-Warning "These AD objects only support Kerberos type encryption:"
    			$AESSupportedObjects | Format-Table Name, ObjectClass, ObjectGUID -AutoSize
    			Write-Warning ""
    		} else { Write-Warning "No AES Encryption supported on this domain. Kerberos may not be feasible." }
    

    I can verify on the RDG that it receives its share of kerberos tickets.

    However, there is still something missing.

    Although the RDG is configured with a proper public certificate (just like the test rig and from the same issuer), it always presents a self signed certificate to the remote client after the credentials are supplied and before connecting to the target computer on the domain. At that point, it presents the credential with the MYDOMAIN\UPN artifact and you understand that Kerberos failed without logging events.

    This self signed certificate is stored in 'Cert:\localmachine\Remote Desktop\' and is reissued if deleted. Do we know why?

    Regards,

    Was this answer helpful?

    0 comments No comments

  4. VPHAN 34,635 Reputation points Independent Advisor
    2025-12-18T04:37:13.5333333+00:00

    Hi Serge Caron,

    We are in Code Red territory. You are right to stop looking at the RD Gateway. If the Domain Controller thinks it is on a Private Network, the Windows Firewall is actively blocking the ports (LDAP/RPC/Kerberos) required for Active Directory to function, even for the DC talking to itself via the network stack.

    The "Private" profile is the root cause of the KDC initialization failure (Event 302) and the "Access Denied" loops. The KDC service starts, tries to contact the Directory Service (ntds.dit) via the network stack (RPC), gets blocked by the "Private" firewall profile, and crashes or hangs.

    Here is the recovery plan to bring the DC back to "DomainAuthenticated" status.

    Step 1: The "Chicken and Egg" Fix (NLA Service)

    The Network Location Awareness (NLA) service determines the firewall profile. On a DC, it attempts to contact the domain via LDAP to confirm "I am in the Domain." Since the firewall is blocking LDAP because it's currently "Private," NLA fails and defaults to Private.

    To fix, check DNS: ensure the Preferred DNS Server on the DC's Network Adapter is set to its actual LAN IPv4 address (e.g., 192.168.1.10), NOT 127.0.0.1.

    Reason: 127.0.0.1 often does not respond early enough during boot for NLA, or NLA ignores it.

    Restart NLA: Open PowerShell as Admin and run:
    Restart-Service NlaSvc -Force

    Wait 30 seconds. Check if the network icon changes or run Get-NetConnectionProfile. It should switch to DomainAuthenticated.

    Step 2: Fix the IPv6 "Ghost"

    You mentioned removing an "obsolete" IPv6 record for gc._msdcs. Server 2025 (and AD in general) prefers IPv6. If your DC has IPv6 enabled (default) but no static IPv6, it uses Link-Local (fe80::...) or Loopback (::1). If the DC tries to resolve _ldap._tcp.dc._msdcs.mydomain.tld and gets an IPv6 address that you just deleted (or that doesn't route), it fails.

    Ping Test: ping -6 localhost and ping -6 MyServer.

    Re-Register DNS: Force the DC to re-register the records it thinks it needs.

    ipconfig /registerdns

    nltest /dsregdns

    Step 3: KDC Event 200 (The Certificate Issue)

    You mentioned: "The DC is not exposed to the Internet and does not have a public certificate." Event ID 200 on the KDC means: "The KDC cannot find a suitable certificate to use for smart card logons or KDC validation."

    Windows Server 2016+ (and stricter in 2025) expects the KDC to have a certificate (Template: "Kerberos Authentication" or "Domain Controller Authentication").

    If you do not have an internal CA (Certificate Authority), the DC typically generates a self-signed one.

    If that cert is missing, expired, or invalid, the KDC logs Event 200.

    Crucial: While Event 200 is technically an error, standard Password Authentication (Kerberos AS-REQ) usually continues to work unless you have "Strict KDC Validation" enabled via Group Policy.

    For now, ignore Event 200. It is noise compared to the "Private Network" firewall blockage. Focus on Step 1.

    So you need to:

    Set NIC DNS to LAN IP (not loopback).

    Restart-Service NlaSvc -Force.

    Verify Firewall Profile is DomainAuthenticated.

    Restart the Kerberos Key Distribution Center service (kdc).

    Once the Firewall Profile is "Domain", the KDC will successfully contact the DS (Event 302 disappears), and you can resume the RDG testing.

    VP

    Was this answer helpful?

    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.