Troubleshooting Remote Desktop Service Running But Not Listening on Port 3389 in Hyper-V Server 2019


2 views

After setting up a fresh Hyper-V Server 2019 installation (version 1809/10.0.17763.1), I encountered an issue where Remote Desktop appeared enabled but wasn't actually listening on the default port 3389. Here's how I verified this:

# Basic connectivity test
Test-NetConnection -ComputerName hypervserver -Port 3389

# Service status check
Get-Service -Name termservice | Select-Object Status,StartType

# Port listening check
Get-NetTCPConnection -State Listen | Where-Object {$_.LocalPort -eq 3389}

# Registry verification
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' | Select fDenyTSConnection
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' | Select PortNumber

Through extensive troubleshooting, I identified several possible reasons for this behavior:

  • Network Level Authentication (NLA) misconfiguration
  • RDP Security Layer settings conflict
  • Missing or corrupted RDP certificate
  • Port redirection at the Hyper-V level
  • Group Policy override of local settings

Here's the complete procedure that finally resolved the issue:

# First, verify and reset RDP configuration
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnections -Value 0

# Ensure proper security layer is set
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name SecurityLayer -Value 1
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication -Value 1

# Reset the RDP certificate
$cert = Get-ChildItem Cert:\LocalMachine\Remote\Desktop | Where-Object {$_.Thumbprint -ne $null} | Select-Object -First 1
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name SSLCertificateSHA1Hash -Value $cert.Thumbprint

# Complete firewall configuration
netsh advfirewall firewall add rule name="Remote Desktop Custom" dir=in protocol=TCP localport=3389 action=allow

To confirm everything is working properly, run this verification script:

function Test-RDPConfiguration {
    $service = Get-Service -Name termservice
    $listener = Get-NetTCPConnection -State Listen -LocalPort 3389 -ErrorAction SilentlyContinue
    $registry = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'
    $firewall = Get-NetFirewallRule -DisplayName "Remote Desktop*" | Where-Object {$_.Enabled -eq 'True'}

    [PSCustomObject]@{
        ServiceRunning = ($service.Status -eq 'Running')
        PortListening = ($null -ne $listener)
        RegistryEnabled = ($registry.fDenyTSConnections -eq 0)
        FirewallConfigured = ($null -ne $firewall)
        CompleteCheck = ($service.Status -eq 'Running') -and ($null -ne $listener) -and ($registry.fDenyTSConnections -eq 0) -and ($null -ne $firewall)
    }
}

Test-RDPConfiguration

If you're still experiencing issues, consider these advanced troubleshooting steps:

  1. Check for Virtual Switch Configuration: Hyper-V virtual switches might interfere with network traffic
  2. Examine Security Software: Some security solutions block RDP even when Windows Firewall is disabled
  3. Review Event Logs: Specifically check the TerminalServices-LocalSessionManager operational log
# Check Hyper-V virtual switch configuration
Get-VMSwitch | Format-Table Name, NetAdapterInterfaceDescription

# Query security event logs
Get-WinEvent -LogName "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" -MaxEvents 20 | Format-Table TimeCreated, Message -AutoSize

After installing Hyper-V Server 2019 (version 1809/10.0.17763.1), I encountered an issue where Remote Desktop Protocol (RDP) wasn't accessible despite the service appearing to be properly configured. Here's what I found during initial diagnostics:

PS> Test-NetConnection -ComputerName hypervserver -Port 3389
ComputerName     : hypervserver
RemoteAddress    : {IP}
RemotePort       : 3389
InterfaceAlias   : Ethernet
SourceAddress    : {local_IP}
TcpTestSucceeded : False

The Remote Desktop Services (TermService) was running, but not listening on the expected port:

PS> Get-Service TermService | Select-Object Status,StartType
Status   StartType
------   ---------
Running  Automatic

PS> Get-NetTCPConnection -State Listen | Where-Object LocalPort -eq 3389
# No output

Network connectivity was confirmed working through ICMP, but TCP/3389 remained inaccessible:

PS> Test-Connection hypervserver -Count 2
Source        Destination     IPV4Address      Bytes    Time(ms)
------        -----------     -----------      -----    --------
CLIENT01      hypervserver    {IP}             32       1
CLIENT01      hypervserver    {IP}             32       1

When basic troubleshooting didn't reveal the issue, I went deeper:

# Check RDP listener components
PS> Get-WindowsFeature -Name *RDS* | Where-Object Installed
Display Name                                            Name
-----------                                            ----
Remote Desktop Services                                 RDS-RD-Server

# Verify network restrictions
PS> Get-NetFirewallRule -DisplayName "*Remote Desktop*" | Select-Object Name,Enabled
Name                          Enabled
----                          -------
RemoteDesktop-UserMode-In-TCP True
RemoteDesktop-UserMode-In-UDP True

The critical issue was that the RDP Listener component wasn't properly initialized. Here's how to fix it:

# First, ensure all required services are running
PS> Restart-Service TermService -Force

# Then reset the RDP-Tcp configuration
PS> (Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-Tcp'").SetUserAuthenticationRequired(0)

# Alternative method if WMI fails
PS> reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
PS> reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v UserAuthentication /t REG_DWORD /d 0 /f

# Final restart to apply changes
PS> Restart-Service TermService -Force

After implementing these changes, verify the listener is active:

PS> Test-NetConnection -ComputerName hypervserver -Port 3389
ComputerName     : hypervserver
RemoteAddress    : {IP}
RemotePort       : 3389
InterfaceAlias   : Ethernet
SourceAddress    : {local_IP}
TcpTestSucceeded : True