Step 1: Allow RDP Only From Your IP
The strongest single change is to stop the world from reaching port 3389 at all. Windows Firewall already has rules for Remote Desktop; narrow them to the address you connect from:
Set-NetFirewallRule -DisplayGroup "Remote Desktop" -RemoteAddress 203.0.113.10Replace 203.0.113.10 with your own public IP. Several addresses or a range are fine: -RemoteAddress 203.0.113.10,198.51.100.0/24.
If your home IP changes often, this rule will lock you out the day it changes. Either allow your ISP's range, or use Step 5 (a VPN) instead. Blocking port 3389 at the firewall is also one of the mitigations the US CISA listed for the BlueKeep RDP vulnerability.
Step 2: Make Sure Network Level Authentication Is On
Network Level Authentication (NLA) makes the client prove the password before Windows starts a full desktop session. Without it, every guess costs the server a login screen, and pre-authentication bugs are exposed. BlueKeep (CVE-2019-0708) let an attacker act "before authentication" with no user interaction, and CISA's advisory told admins to enable NLA as a mitigation.
Check it:
(Get-CimInstance -Namespace root/cimv2/TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-tcp'").UserAuthenticationRequired1 means NLA is on. If you see 0, enable it:
Get-CimInstance -Namespace root/cimv2/TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-tcp'" | Invoke-CimMethod -MethodName SetUserAuthenticationRequired -Arguments @{UserAuthenticationRequired=1}Microsoft's own Remote Desktop clients support NLA, so there is rarely a reason to leave it off.
Step 3: Lock Out Repeated Failures
An account lockout policy turns an endless guessing loop into a handful of attempts. Microsoft's lockout documentation calls 10 failed attempts "an acceptable starting point", and the default on a stand-alone server is 0, meaning never lock. Ten failures within ten minutes locks the account for ten minutes:
net accounts /lockoutthreshold:10 /lockoutwindow:10 /lockoutduration:10Three things to know before relying on it:
- The built-in Administrator account is a special case, and it is the account you log in with on a fresh Windows VPS. Microsoft's lockout page says it "is excluded from this policy". Since the October 2022 updates, Windows has a separate policy, Allow Administrator account lockout, that brings it under lockout for network logons such as RDP. It is set by default only on installs that included those updates before initial setup. Check it in
secpol.mscunder Account Policies, Account Lockout Policy, and enable it if it is off. - The lockout only applies to network logons. Per the same Microsoft article, console logons are still allowed during the lockout period, so the browser console on the server page still gets you in.
- A lockout policy also locks you out if you mistype your password ten times.
Step 4: Use a Long, Unique Password
Bots try lists of common and leaked passwords. A random password of 20 or more characters from a password manager is effectively out of reach for them. Never reuse the password from another service, and change the one you received at deploy time if you have shared it anywhere.
Step 5: Put RDP Behind a VPN
The cleanest setup is to close 3389 to the internet completely and reach it through a VPN. WireGuard has a Windows client and works well for this: connect the VPN, then RDP to the server's VPN address.
Once the VPN works, restrict the Remote Desktop rule to the VPN subnet:
Set-NetFirewallRule -DisplayGroup "Remote Desktop" -RemoteAddress 10.8.0.0/24Now port 3389 does not answer anyone on the internet, and the bots move on.
What About Changing the RDP Port?
Moving RDP from 3389 to another port cuts the volume of automated guesses, because many bots only try the default. It adds little real security, since anyone scanning all ports finds it. Treat it as noise reduction on top of Steps 1 to 3.
If you do it, open the new port in the firewall before restarting the service, or you will lock yourself out:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name PortNumber -Value 3390
New-NetFirewallRule -DisplayName "RDP 3390" -Direction Inbound -Protocol TCP -LocalPort 3390 -Action Allow -RemoteAddress 203.0.113.10
Restart-Service TermService -ForceCheck Who Is Knocking
Failed logons are recorded in the Security log as event 4625, "An account failed to log on". Failures over Remote Desktop carry logon type 10 (RemoteInteractive), and the event records the source network address. This shows the latest ones:
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 20 | Format-Table TimeCreated, Message -WrapOn a server with RDP open to everyone, expect a steady stream of them. After Step 1 the list should go quiet.
Keep Windows Updated
Microsoft released the BlueKeep fix on 14 May 2019. That bug affected Windows Server 2008 R2 and older, so the 2019, 2022 and 2025 images are not exposed to it, but the next RDP flaw will also arrive as an update. Leave automatic updates on, and let the server reboot when it needs to, at a time you choose under Settings, Windows Update, Advanced options.
What It Costs
None of this needs extra software or a bigger server. On our Windows VPS plans the licence is included in the hourly price, starting at $79/month for the Standard plan (2 vCPU, 4 GB), with Windows Server 2019, 2022 and 2025 to choose from. The browser console on the server page is there if a firewall change goes wrong.