Overview
If a Windows Server can be accessed through Virtualizor → noVNC, but a direct Remote Desktop (RDP) connection fails, the issue may be caused by the Windows Firewall blocking inbound RDP traffic.
This guide explains how to:
- Enable Remote Desktop
- Start the Remote Desktop Services service
- Open TCP/UDP port
3389 - Verify that RDP is listening
- Test port accessibility
- Apply the fix using PowerShell
- Manually configure the firewall
- Configure the Virtualizor/Linux host firewall when required
1. Prerequisites
You must have:
- Access to the Windows Server through Virtualizor noVNC/console
- Administrator access to Windows
- The server's public IP address
For Linux/Virtualizor node configuration, you need:
- SSH/root access to the Virtualizor node
2. Check Whether RDP Is Enabled
Open PowerShell as Administrator and run:
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections
Expected result
fDenyTSConnections : 0
0 means RDP is enabled.
If it returns:
fDenyTSConnections : 1
enable RDP:
Set-ItemProperty `
"HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" `
-Name fDenyTSConnections `
-Value 0
3. Ensure Remote Desktop Services Is Running
Run:
Get-Service TermService
Expected:
Status Name
------ ----
Running TermService
If it is not running:
Set-Service TermService -StartupType Automatic
Start-Service TermService
4. Open Windows Firewall Port 3389
Recommended method
Create an explicit firewall rule for TCP 3389:
New-NetFirewallRule `
-DisplayName "Allow RDP TCP 3389" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 3389 `
-Action Allow `
-Profile Any
For UDP:
New-NetFirewallRule `
-DisplayName "Allow RDP UDP 3389" `
-Direction Inbound `
-Protocol UDP `
-LocalPort 3389 `
-Action Allow `
-Profile Any
Note: TCP is the critical protocol for establishing a normal RDP connection. UDP can improve RDP performance and is therefore recommended.
5. Verify Port 3389 Is Listening
Run:
netstat -ano | findstr :3389
You should see something similar to:
TCP 0.0.0.0:3389 0.0.0.0:0 LISTENING
TCP [::]:3389 [::]:0 LISTENING
If LISTENING appears, Windows is accepting connections on port 3389.
6. Test RDP Locally
From the Windows Server itself:
Test-NetConnection 127.0.0.1 -Port 3389
Expected:
TcpTestSucceeded : True
If this returns True, the RDP service and local TCP listener are working correctly.
7. Test RDP From an External Machine
From another computer, test the public IP.
Windows
Test-NetConnection SERVER_IP -Port 3389
Example:
Test-NetConnection 95.216.50.253 -Port 3389
Linux/macOS
nc -vz -w 5 SERVER_IP 3389
Example:
nc -vz -w 5 95.216.50.253 3389
Successful result
Connection to 95.216.50.253 3389 port [tcp/ms-wbt-server] succeeded!
Timeout / failed connection
If the connection times out, check:
- Windows Firewall
- Virtualizor node firewall
- NAT/port forwarding
- Provider firewall/security group
- Network/bridge configuration
8. Automated PowerShell Fix
For administrators who need a quick fix, use the following PowerShell script.
Save as:
enable-rdp.ps1
# ==========================================
# Windows Server RDP Firewall Fix
# ==========================================
$Port = 3389
Write-Host "Enabling Remote Desktop..." -ForegroundColor Cyan
# Enable RDP
Set-ItemProperty `
-Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" `
-Name "fDenyTSConnections" `
-Type DWord `
-Value 0
# Ensure RDP service is enabled and running
Write-Host "Starting Remote Desktop Services..." -ForegroundColor Cyan
Set-Service `
-Name "TermService" `
-StartupType Automatic
Start-Service `
-Name "TermService" `
-ErrorAction SilentlyContinue
# Allow TCP 3389
if (-not (Get-NetFirewallRule -DisplayName "Allow RDP TCP 3389" -ErrorAction SilentlyContinue)) {
New-NetFirewallRule `
-DisplayName "Allow RDP TCP 3389" `
-Direction Inbound `
-Protocol TCP `
-LocalPort $Port `
-Action Allow `
-Profile Any
} else {
Write-Host "TCP 3389 firewall rule already exists." -ForegroundColor Yellow
}
# Allow UDP 3389
if (-not (Get-NetFirewallRule -DisplayName "Allow RDP UDP 3389" -ErrorAction SilentlyContinue)) {
New-NetFirewallRule `
-DisplayName "Allow RDP UDP 3389" `
-Direction Inbound `
-Protocol UDP `
-LocalPort $Port `
-Action Allow `
-Profile Any
} else {
Write-Host "UDP 3389 firewall rule already exists." -ForegroundColor Yellow
}
Write-Host ""
Write-Host "==========================================" -ForegroundColor Green
Write-Host " RDP configuration completed successfully"
Write-Host "==========================================" -ForegroundColor Green
Write-Host ""
Write-Host "RDP Service:"
Get-Service TermService |
Select-Object Status, Name, StartType
Write-Host ""
Write-Host "RDP Registry:"
Get-ItemProperty `
"HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" `
-Name fDenyTSConnections
Write-Host ""
Write-Host "Port 3389:"
netstat -ano | findstr ":3389"
Run it from an Administrator PowerShell:
Set-ExecutionPolicy Bypass -Scope Process -Force
.\enable-rdp.ps1
9. Manual CMD Method
If PowerShell firewall cmdlets are unavailable, use netsh.
Enable RDP
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
Start RDP service
sc config TermService start= auto
net start TermService
Allow TCP 3389
netsh advfirewall firewall add rule name="Allow RDP TCP 3389" dir=in action=allow protocol=TCP localport=3389
Allow UDP 3389
netsh advfirewall firewall add rule name="Allow RDP UDP 3389" dir=in action=allow protocol=UDP localport=3389
Verify
netstat -ano | findstr :3389
10. Virtualizor/Linux Node Firewall
If the Windows VM has a public IP directly assigned to it, normally the Windows firewall is the important layer.
If the VM uses NAT/private networking, the Virtualizor node may also need to allow/forward RDP traffic.
firewalld
firewall-cmd --permanent --add-port=3389/tcp
firewall-cmd --permanent --add-port=3389/udp
firewall-cmd --reload
Verify:
firewall-cmd --list-ports
UFW
ufw allow 3389/tcp
ufw allow 3389/udp
ufw reload
Verify:
ufw status
iptables
iptables -I INPUT -p tcp --dport 3389 -j ACCEPT
iptables -I INPUT -p udp --dport 3389 -j ACCEPT
Verify:
iptables -L INPUT -n -v | grep 3389
11. Bash Automation Script
For Linux/Virtualizor nodes:
#!/usr/bin/env bash
set -e
PORT=3389
if [ "$(id -u)" -ne 0 ]; then
echo "ERROR: Run this script as root."
exit 1
fi
echo "=========================================="
echo " RDP Firewall Configuration"
echo " TCP/UDP Port: $PORT"
echo "=========================================="
# firewalld
if command -v firewall-cmd >/dev/null 2>&1 &&
systemctl is-active --quiet firewalld; then
echo "[+] Configuring firewalld..."
firewall-cmd --permanent --add-port="${PORT}/tcp"
firewall-cmd --permanent --add-port="${PORT}/udp"
firewall-cmd --reload
# UFW
elif command -v ufw >/dev/null 2>&1; then
echo "[+] Configuring UFW..."
ufw allow "${PORT}/tcp"
ufw allow "${PORT}/udp"
# nftables
elif command -v nft >/dev/null 2>&1 &&
systemctl is-active --quiet nftables 2>/dev/null; then
echo "[+] Configuring nftables..."
nft add rule inet filter input tcp dport "$PORT" accept 2>/dev/null || true
nft add rule inet filter input udp dport "$PORT" accept 2>/dev/null || true
# iptables
elif command -v iptables >/dev/null 2>&1; then
echo "[+] Configuring iptables..."
iptables -C INPUT -p tcp --dport "$PORT" -j ACCEPT 2>/dev/null ||
iptables -I INPUT -p tcp --dport "$PORT" -j ACCEPT
iptables -C INPUT -p udp --dport "$PORT" -j ACCEPT 2>/dev/null ||
iptables -I INPUT -p udp --dport "$PORT" -j ACCEPT
else
echo "ERROR: No supported firewall detected."
exit 1
fi
echo ""
echo "RDP port $PORT has been allowed."
echo "Test externally with:"
echo ""
echo "nc -vz -w 5 SERVER_IP $PORT"
12. Troubleshooting Flow
Use the following sequence when troubleshooting:
RDP Connection
│
▼
Is RDP enabled?
│ │
NO YES
│ │
▼ ▼
Enable RDP TermService running?
│
┌────┴────┐
NO YES
│ │
▼ ▼
Start Port 3389
service listening?
│
┌────┴────┐
NO YES
│ │
▼ ▼
Fix RDP Windows
listener Firewall
│
▼
Allow TCP 3389
│
▼
External port test
│
┌────────┴────────┐
FAIL PASS
│ │
▼ ▼
Check Virtualizor Check RDP
node/provider authentication
firewall/NAT /NLA/user
Important Security Note
Do not permanently disable Windows Firewall just to make RDP work.
Avoid:
netsh advfirewall set allprofiles state off
Instead, create an explicit inbound rule for 3389.
For production servers, an even better setup is to restrict RDP to trusted source IP addresses rather than exposing 3389 to the entire Internet.
