All tutorials
12 min read

How to Secure RDP on Windows Server: Port 3389, NLA, and Firewall

RDP security for Windows Server in 7 steps: turn on NLA, add a named admin account, set a lockout policy, limit port 3389 to your IP, and change the port.

TL;DR:

  • RDP security on Windows Server takes 7 steps: install updates, turn on Network Level Authentication (NLA), add a named administrator, set a 10/10/10 lockout policy, limit port 3389 to your IP address, change the port, and verify the settings.
  • RDP listens on TCP 3389 and UDP 3389 by default. The PortNumber registry value under RDP-Tcp holds the current port.
  • The commands use the port, registry key, NLA setting and "Remote Desktop" firewall rules that current Windows Server releases share.
  • Since the October 2022 updates, the Allow Administrator account lockout policy can lock the built-in Administrator after failed RDP sign-ins.
  • A port other than 3389 cuts the automated sign-in attempts aimed at the default port. The firewall scope and lockout policy stop password guessing.
  • To close the public port, run Tailscale or WireGuard and limit RDP to the VPN range, such as 100.64.0.0/10.

Applies to: Windows Server 2022 and 2025 · Windows PowerShell 5.1 · checked October 2026

Remote Desktop Protocol (RDP) is Microsoft's protocol for controlling a Windows desktop over the network, and Windows Server accepts RDP connections on port 3389 by default. RDP security is the set of settings that limits who can reach that port and how many passwords they can try. This tutorial hardens Remote Desktop on a Windows Server VPS with PowerShell and tests each change at the end.

Which port does RDP use?

RDP uses TCP port 3389. Windows also listens on UDP 3389 for the RDP UDP transport, so the built-in firewall rules cover both protocols. To find the port on your server, open PowerShell as Administrator and read the registry value:

Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name 'PortNumber' | Select-Object PortNumber

The output looks similar to this:

PortNumber
----------
      3389

Changing this value moves RDP to another port after Remote Desktop Services restarts. Step 6 covers the order that keeps you connected.

What are the risks of using RDP?

An RDP port open to the internet carries three risks:

  • Bots scan for port 3389 and guess passwords for common names such as Administrator. Microsoft's KB5020282 calls brute-force attacks "one of the top three ways that Windows computers are attacked today" and names RDP as the route.
  • Unpatched flaws let attackers in without a password. BlueKeep (CVE-2019-0708) did this on Windows 7 and Windows Server 2008, and CISA lists it as exploited.
  • An administrator session controls every file, service and account on the server.

Arct Cloud includes DDoS protection on every plan. Password guessing arrives as ordinary RDP sign-ins, so the settings on the server stop it.

Prerequisites

  • A Windows Server VPS with administrator Remote Desktop access. See Windows VPS for available plans.
  • A Remote Desktop client: Remote Desktop Connection (mstsc) on Windows, or Windows App on macOS, iPhone, iPad and Android.
  • A second way into the server if a firewall change blocks RDP, such as another network you control or a provider web console, if your provider offers one.

Run server commands in PowerShell opened as Administrator. Replace values in capitals, such as YOUR_PUBLIC_IP, with your own. The examples use 203.0.113.10 for the server and 198.51.100.20 for your computer.

Step 1: Install Windows updates

Updates close RDP flaws such as BlueKeep, so patch the server first. Start the Server Configuration tool:

SConfig

Type 6 and press Enter for Install updates, type 1 for all quality updates, then type A to install them. Restart the server if SConfig asks, and reconnect. Option 5 sets automatic updates.

Step 2: Turn on Network Level Authentication

Network Level Authentication (NLA) makes the client prove the user's credentials before Windows creates a remote session. Check the current setting:

Get-CimInstance -Namespace root/cimv2/TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-tcp'" | Select-Object TerminalName, UserAuthenticationRequired

The output looks similar to this:

TerminalName UserAuthenticationRequired
------------ --------------------------
RDP-Tcp                               1

A value of 1 means NLA is on. If it shows 0, turn it on:

Get-CimInstance -Namespace root/cimv2/TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-tcp'" | Invoke-CimMethod -MethodName SetUserAuthenticationRequired -Arguments @{ UserAuthenticationRequired = 1 }

A ReturnValue of 0 means Windows saved the change. Your current session stays open, and new connections need a client that supports RDP 6.0 or later.

Step 3: Add a named administrator account

Automated tools guess the name Administrator first. A second administrator account with a name of your choice keeps working when those guesses lock out the built-in account. Create it and add it to the Administrators group:

$Password = Read-Host -AsSecureString "Password for the new account"
New-LocalUser -Name "YOUR_ADMIN_NAME" -Password $Password -FullName "YOUR_ADMIN_NAME" -PasswordNeverExpires
Add-LocalGroupMember -Group "Administrators" -Member "YOUR_ADMIN_NAME"

Replace YOUR_ADMIN_NAME with a name other than admin or administrator, and use a long random password from a password manager. Give the built-in account a new long password too:

$Password = Read-Host -AsSecureString "New password for Administrator"
Set-LocalUser -Name "Administrator" -Password $Password -PasswordNeverExpires $true

Windows expires local passwords after 42 days by default, and with NLA on, an expired password cannot be changed over Remote Desktop. Both commands set the password not to expire. Run Get-LocalUser if the built-in account has another name on your image. Sign out and connect as YOUR_ADMIN_NAME before you continue. Renaming the built-in account is optional: a renamed Administrator keeps its well-known SID ending in 500, which attackers can discover.

Step 4: Set an RDP account lockout policy

An account lockout policy blocks an account for a set time after repeated wrong passwords. A server set up from media older than the October 2022 updates uses a threshold of 0, which never locks an account. A server set up from media that includes those updates starts with 10/10/10. Check your server:

net accounts

Open Local Security Policy (secpol.msc), go to Security Settings > Account Policies > Account Lockout Policy, and set these values:

PolicyValue
Account lockout threshold10
Account lockout duration10 minutes
Reset account lockout counter after10 minutes
Allow Administrator account lockoutEnabled

If Windows suggests 30 minutes for the other two values after you set the threshold, accept, then change both to 10. These are the 10/10/10 values Microsoft recommends in KB5020282. Run net accounts again. The output looks similar to this:

...
Lockout threshold:                                    10
Lockout duration (minutes):                           10
Lockout observation window (minutes):                 10
Computer role:                                        SERVER

The Administrator lockout applies to network sign-ins such as RDP. Sign-ins at the server's console still work during a lockout.

Step 5: Limit RDP to your IP address

The built-in Remote Desktop rules in Windows Defender Firewall accept RDP from any address. Limiting them to your IP address blocks scanners before the sign-in screen. Confirm the firewall is on and blocks unmatched inbound traffic:

Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction

Every profile should show True under Enabled, and NotConfigured or Block under DefaultInboundAction. If a profile shows False or Allow, turn on the Remote Desktop rules before you change the profile, because the change can otherwise close your session:

Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True -DefaultInboundAction Block

Read your public IP address as the server sees it:

Get-NetTCPConnection -LocalPort 3389 -State Established | Select-Object RemoteAddress

The output looks similar to this:

RemoteAddress
-------------
198.51.100.20

Apply that address to every inbound rule that names port 3389, built-in or added by your provider:

Get-NetFirewallPortFilter |
  Where-Object LocalPort -eq 3389 |
  Get-NetFirewallRule |
  Where-Object { $_.Direction -eq 'Inbound' -and $_.Action -eq 'Allow' } |
  Set-NetFirewallRule -RemoteAddress YOUR_PUBLIC_IP

Replace YOUR_PUBLIC_IP with that address, and list more addresses or ranges with commas, such as 198.51.100.20, 192.0.2.0/24. Your session stays open. A rule that allows every port still lets RDP through, and the test from another network in Step 7 shows whether port 3389 stays open. If your home IP address changes, RDP stops answering, so add a second address you control, or confirm another way in such as a provider web console, if your provider offers one.

Step 6: Change the RDP port (optional)

A port other than 3389 cuts the automated sign-in attempts aimed at the default port. A full port scan still finds RDP, so keep Steps 4 and 5. Pick a port between 1024 and 49151, because Windows uses 49152 to 65535 for outgoing connections. Run this step in one PowerShell window, starting with a check that the port is unused:

$RdpPort = 'YOUR_RDP_PORT'
Get-NetTCPConnection -LocalPort $RdpPort -ErrorAction SilentlyContinue
Get-NetUDPEndpoint -LocalPort $RdpPort -ErrorAction SilentlyContinue

No output from either command means the port is free. Open the port in any firewall in front of the server, then add Windows Defender Firewall rules for it before you move the listener:

New-NetFirewallRule -DisplayName "Remote Desktop custom port (TCP-In)" -Direction Inbound -Action Allow -Protocol TCP -LocalPort $RdpPort -RemoteAddress YOUR_PUBLIC_IP
New-NetFirewallRule -DisplayName "Remote Desktop custom port (UDP-In)" -Direction Inbound -Action Allow -Protocol UDP -LocalPort $RdpPort -RemoteAddress YOUR_PUBLIC_IP

Change the port and restart Remote Desktop Services:

Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name 'PortNumber' -Value $RdpPort
Restart-Service TermService -Force

The restart ends your session. Reconnect to 203.0.113.10:YOUR_RDP_PORT in Remote Desktop Connection or Windows App, then turn off the built-in rules for 3389:

Disable-NetFirewallRule -DisplayGroup "Remote Desktop"

Step 7: Verify your RDP security settings

Test the firewall scope from your own Windows computer:

Test-NetConnection -ComputerName 203.0.113.10 -Port 3389

Use your custom port if you changed it. The output looks similar to this:

ComputerName     : 203.0.113.10
RemoteAddress    : 203.0.113.10
RemotePort       : 3389
...
TcpTestSucceeded : True

From another network, such as a phone hotspot, the same test should show TcpTestSucceeded : False. On macOS or Linux, use nc -vz 203.0.113.10 3389.

Next, connect once with a wrong password, sign in correctly, and read the failed sign-in events on the server:

Get-WinEvent -FilterHashtable @{ LogName = 'Security'; Id = 4625 } -MaxEvents 5 | Select-Object TimeCreated, Id

Event 4625 records a failed sign-in and event 4740 records a lockout. If no 4625 events appear, failure auditing is off: turn it on with auditpol /set /subcategory:"Logon" /failure:enable.

A new client shows a certificate warning because RDP uses a self-signed certificate. Compare the thumbprint in the warning with the server's value before you accept it:

(Get-CimInstance -Namespace root/cimv2/TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-tcp'").SSLCertificateSHA1Hash

Keep RDP off the public internet with a VPN

Microsoft recommends a VPN over exposing Remote Desktop to the internet. With a private VPN, you limit the RDP port to addresses inside the tunnel.

  • Tailscale supports Windows Server 2016 and later and gives each device an address in 100.64.0.0/10. Install it on the server and your computer, and turn on Run Unattended on the server so the tunnel survives a restart.
  • WireGuard for Windows runs on Windows Server 2016 to 2025, with the server as one peer and RDP limited to a tunnel subnet such as 10.8.0.0/24. How to Set Up a WireGuard VPN Server on Ubuntu 24.04 explains keys and peers.

Then limit RDP to the tunnel with the Step 5 command, using your RDP port and the VPN range:

Get-NetFirewallPortFilter |
  Where-Object LocalPort -eq YOUR_RDP_PORT |
  Get-NetFirewallRule |
  Where-Object { $_.Direction -eq 'Inbound' -and $_.Action -eq 'Allow' } |
  Set-NetFirewallRule -RemoteAddress YOUR_VPN_RANGE, YOUR_PUBLIC_IP

Replace YOUR_RDP_PORT with 3389, or with your port from Step 6. YOUR_VPN_RANGE is 100.64.0.0/10 for Tailscale or your WireGuard subnet, such as 10.8.0.0/24. Your public IP address stays as a fallback. Remove it once the VPN connection works after a server restart.

Windows Server 2025 defaults that affect RDP

Windows Server 2025 changes two defaults from earlier releases:

  • TLS 1.0 and 1.1 are off by default, so RDP clients that support only those versions cannot connect.
  • The OpenSSH server is installed by default. Run Get-Service sshd to see whether it runs. The OpenSSH Server (sshd) firewall rule opens TCP port 22, so limit it the same way as RDP.

Troubleshoot common RDP errors

SymptomCauseFix
Remote Desktop can't connect to the remote computer for one of these reasons after Step 5Your public IP address changedConnect from another allowed address, or a provider web console if your provider offers one, then rerun Step 5 with the new address
As a security precaution, the user account has been locked because there were too many logon attempts or password change attempts.The lockout threshold was reachedWait 10 minutes, or sign in with your other administrator account
You must change your password before logging on the first time.The account password expired, and NLA blocks the change promptSign in with your other administrator account and run Set-LocalUser -Name "YOUR_USER" -Password (Read-Host -AsSecureString) -PasswordNeverExpires $true
The connection was denied because the user account is not authorized for remote login.The account is not in Administrators or Remote Desktop UsersAdd it with Add-LocalGroupMember -Group "Remote Desktop Users" -Member "YOUR_USER"
The connection fails after Step 6The client still uses 3389, or a firewall blocks the new portConnect to 203.0.113.10:YOUR_RDP_PORT and check the custom port rules

FAQ

Which port needs to be open for RDP?

TCP port 3389 by default, and Windows also listens on UDP 3389 for the RDP UDP transport. Open both only to your own IP address or VPN range. If you changed the listening port, open the new port instead.

How can I find my RDP port number?

Read the PortNumber value in the registry under HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp. It shows 3389 unless someone changed it.

Is port 3389 vulnerable?

Yes, when it is open to the internet. Port 3389 draws constant scans and password guessing, and unpatched RDP bugs such as BlueKeep (CVE-2019-0708) on Windows 7 and Server 2008 let attackers run code without a password. Install updates, keep NLA on, and limit the port to your IP address.

How do I allow RDP through the firewall?

Enable the built-in Remote Desktop rule group in Windows Defender Firewall, which covers TCP and UDP 3389. Then set the remote address on those rules to your own IP address so only you can connect.

Is Network Level Authentication enough for RDP security?

No. NLA makes the client sign in before Windows creates a session, which keeps unauthenticated connections away from the desktop. A guessed password still passes, so pair NLA with an account lockout policy and a firewall rule limited to your IP address.

Is Microsoft discontinuing RDP?

No. Microsoft ended support for the Remote Desktop client for Windows (MSI) in public cloud environments on March 27, 2026. RDP and the built-in Remote Desktop Connection app remain, and Windows App is the client on macOS, iOS and Android.

What VPS size does Windows Server need for Remote Desktop?

On Arct Cloud, Windows Server needs a plan with 2 or more vCPU and deploys in 2 to 4 minutes depending on the image size. Administrator Remote Desktop is available once the deploy finishes. Linux images run on every plan.

Next steps

Arct Cloud Windows Server plans include administrator Remote Desktop. Compare plans.

This work is licensed under CC BY-NC-SA 4.0.