Port 3389 is the most scanned port on the internet after 22 and 445. A Windows server on a public IP gets its first RDP login attempt within minutes and thousands per day after that. Almost all of them are stopped by five settings that take fifteen minutes to apply. This is the list we apply to our RDP images by default, explained so you can verify it and extend it.
What the attacks look like
Open the Security event log on any Windows server that has been online for a day and filter on event ID 4625 (failed logon). You will see a steady stream of attempts against Administrator, admin, user, test and a few hundred first names, from IP addresses in every country. They are not targeted; a botnet tries every IPv4 address and moves on. The defence is not to be the easy one.
1. Network Level Authentication
NLA requires the client to authenticate before a session is created. Without it, every attempt spins up a login screen on the server, which costs CPU and exposes the pre-login surface where several historic RDP vulnerabilities lived. Our images ship with it on; check it under System → Remote Desktop → Advanced settings, or:
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication
# 1 = NLA required
2. Account lockout policy
A lockout policy makes guessing slow. Ten failed attempts in ten minutes, locked for fifteen, turns a bot that tries thousands of passwords an hour into one that tries forty. Set it with the local security policy or in one command:
net accounts /lockoutthreshold:10 /lockoutduration:15 /lockoutwindow:10
The built-in Administrator account is exempt from lockout by design, which is the next point.
3. A standard user for daily work, and a renamed Administrator
Every attack tries Administrator first. Renaming it does not make the account invisible (its SID still ends in 500), but it defeats every automated guess we see in practice. Create a separate standard user for daily use, add it to the Remote Desktop Users group, and reserve the administrator account for maintenance sessions.
Rename-LocalUser -Name Administrator -NewName ops-admin
New-LocalUser -Name jane -PasswordNeverExpires:$false
Add-LocalGroupMember -Group 'Remote Desktop Users' -Member jane
Use a long passphrase or, better, a password manager's 24-character random string for each account. The whole guessing threat rests on passwords a human can remember.
4. Restrict RDP to your own address
This is the setting that does the most. If port 3389 only answers to your office or home IP, the botnets never even see a login screen. Windows Firewall can scope the built-in rule to a remote address list:
Set-NetFirewallRule -DisplayGroup 'Remote Desktop' -RemoteAddress 203.0.113.5,198.51.100.0/24
If your address changes (home connections often do), a WireGuard or Tailscale tunnel gives you a fixed private address to allow instead; the Tailscale add-on installs the client during provisioning. The panel console remains available if you lock yourself out, so this change is safe to make.
5. The port change, and what it is worth
Moving RDP off 3389 stops the dumbest scanners and none of the smart ones, since a full port scan finds it in seconds. Do it anyway: it cuts the noise in your event log by 95%, which makes real attacks visible. Change the port in the registry, add a firewall rule for the new port, restart the service, and only then remove the old rule.
Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name PortNumber -Value 33890
New-NetFirewallRule -DisplayName 'RDP 33890' -Direction Inbound -Protocol TCP -LocalPort 33890 -Action Allow -RemoteAddress 203.0.113.5
Restart-Service TermService -Force
6. Windows Update, on a schedule
Most RDP compromises in the wild use vulnerabilities patched months earlier. Leave automatic updates on, set active hours so the reboot happens at night in your time zone, and check Settings → Windows Update once a month. The Windows Update add-on on dedicated servers configures the schedule for you.
The rest, in priority order
- Defender on, with cloud protection. It is already there; do not disable it to make a tool run faster.
- No shared accounts. One person, one user; it is the only way the event log tells you anything.
- Disable SMBv1 and, if you do not use file sharing, close 445 entirely.
Set-SmbServerConfiguration -EnableSMB1Protocol $false. - Log off, do not just disconnect. Disconnected sessions keep running with your credentials in memory.
- Watch event 4625. A spike after you locked things down means someone found the new port, which is fine, or that the firewall scope was lost after an update, which is not.
What our RDP images do out of the box
NLA on, the account lockout policy above, Defender and Windows Update enabled, SMBv1 off, and a random 20-character administrator password shown once in the panel. Steps 3 to 5 need your own address or your own naming, so they are yours to apply; with them done, an RDP server on a public IP is a boring server, which is the goal.
