On this page
- Give Administrator a password nothing else uses
- Create a separate admin account
- Require Network Level Authentication
- Set an account lockout policy
- Restrict Remote Desktop to addresses you control
- Find the address you are connecting from
- Scope the rule in Windows Firewall
- What the panel can and cannot do here
- Changing the Remote Desktop port
- If you lock yourself out
- Related
Remote Desktop on a public address is the single most attacked thing on a Windows server. Port 3389 is scanned constantly, the attempts are automated, and they start within hours of the server getting an address. This page is the work that takes your server out of that funnel: a password nothing can guess, an account name nothing can assume, authentication that happens before a desktop is ever built, and a rule that says which addresses may knock at all.
If you have not connected yet, start at Connecting to your server. If this server is new, do First steps first, because the password change belongs there and everything below assumes it is done.
Give Administrator a password nothing else uses
The account the attempts target by name is Administrator, and the passwords
they try come from breach lists. That makes two properties matter, and only two:
the password is long and random, and it has never been used anywhere else.
$pw = Read-Host -Prompt "New password" -AsSecureString
Set-LocalUser -Name Administrator -Password $pwGenerate it in a password manager and never type it from memory. Reusing the password from another server means one compromised machine hands over the rest, which is the usual way a single incident becomes a bad week.
Create a separate admin account
The default account is guessable by name on every Windows machine in the world. Signing in as a named account of your own removes that starting point, and it gives you a second way in while you change things.
Create the account
$pw = Read-Host -Prompt "Password for the new account" -AsSecureString New-LocalUser -Name "cxadmin" -Password $pw -FullName "Operations" -PasswordNeverExpiresPick a name that is not
admin,administrator,user, or the company name. The point of the exercise is that it cannot be guessed.Give it the rights it needs
Add-LocalGroupMember -Group "Administrators" -Member "cxadmin" Add-LocalGroupMember -Group "Remote Desktop Users" -Member "cxadmin"Members of Administrators can already sign in over Remote Desktop, so the second command is not strictly required for an admin account. Add it anyway if you later drop the account out of Administrators, and use Remote Desktop Users alone for any account that should be able to connect without administering the machine.
Prove it works before you touch the default account
Open a second Remote Desktop session as the new account, from scratch, with the password typed in. Do not skip this. The next step removes your fallback, and the only safe moment to do that is when you have already used the replacement.
Disable or rename the built-in Administrator
Disabling it is the stronger option, because a disabled account cannot be signed in to no matter what the password is:
Disable-LocalUser -Name AdministratorRenaming it is the weaker option, and it is the one to pick when something on the machine expects the account to exist:
Rename-LocalUser -Name Administrator -NewName "cxroot"Undo either with
Enable-LocalUser -Name Administratoror by renaming it back, from your new account or from the console.
Renaming does not change the account's underlying identifier, so software already running on the machine still recognises it. What renaming buys you is narrow and worth stating plainly: automated sign-in attempts from the internet have to guess a username as well as a password, and almost none of them do.
Require Network Level Authentication
Network Level Authentication makes the client prove who it is before the server builds a session for it. Without it, every connection attempt gets a desktop session and a sign-in screen, which costs the server real work and gives an attacker something to hammer. With it, an unauthenticated attempt is turned away at the front door.
It is on by default on current Windows Server images. Check rather than assume:
$rdp = "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
Get-ItemProperty -Path $rdp | Select-Object UserAuthentication, SecurityLayerUserAuthentication should be 1. SecurityLayer should be 2, which
requires TLS for the connection rather than the older RDP security layer. Set
either if it is wrong:
Set-ItemProperty -Path $rdp -Name UserAuthentication -Value 1
Set-ItemProperty -Path $rdp -Name SecurityLayer -Value 2In the GUI the same switch is in System Properties. Run sysdm.cpl, open the
Remote tab, and tick Allow connections only from computers running Remote
Desktop with Network Level Authentication (recommended).
Very old clients cannot do NLA. In practice that means a client older than Windows 7, or a third-party client that has not been updated in a decade. Update the client rather than turning this off.
Set an account lockout policy
A lockout policy puts a ceiling on guessing. Without one, an attacker gets unlimited attempts at your password; with one, they get ten and then wait.
net accounts /lockoutthreshold:10 /lockoutduration:15 /lockoutwindow:15That reads as: ten failed attempts within a 15 minute window locks the account
for 15 minutes. Confirm what is in force with net accounts on its own, or open
secpol.msc and look under Account Policies, then Account Lockout
Policy.
Two things to understand before you rely on it.
On older Windows builds the built-in Administrator account is exempt from
lockout. Newer builds ship a setting that includes it, but the exemption is
another reason to sign in as a named account of your own rather than as
Administrator. A lockout policy protects the accounts it applies to, and on an
older image that may not include the one being attacked.
A lockout policy is also a way to be locked out. Anyone who can reach port 3389 can trigger the threshold on an account whose name they know, deliberately or as a side effect of scanning. That is not a reason to skip it, it is a reason to also restrict who can reach the port, which is the next section, and to keep the console available.
Restrict Remote Desktop to addresses you control
This is the change with the largest effect on this page. If port 3389 only answers the handful of addresses you actually connect from, the automated attempts never reach a password prompt at all.
Find the address you are connecting from
Ask the server. It can see exactly where your current session comes from, which is more reliable than what your router reports:
Get-NetTCPConnection -LocalPort 3389 -State Established |
Select-Object RemoteAddress, RemotePortThe RemoteAddress value is the address to put in the rule. If you have already
moved Remote Desktop to another port, use that port number instead.
Scope the rule in Windows Firewall
Windows ships a group of rules that open Remote Desktop. Scoping that group is better than adding a rule of your own, because a new allow rule would sit alongside the existing open ones rather than replacing them.
Look at what is there first:
Get-NetFirewallRule -DisplayGroup "Remote Desktop" |
Format-Table Name, DisplayName, Enabled, ProfileThen scope every rule in the group to the addresses you use:
Set-NetFirewallRule -DisplayGroup "Remote Desktop" -RemoteAddress "203.0.113.10"For more than one source, pass an array. A CIDR range is accepted, which is how you cover an office or a VPN exit:
Set-NetFirewallRule -DisplayGroup "Remote Desktop" -RemoteAddress @("203.0.113.10", "203.0.113.0/24")Confirm what is now in force:
Get-NetFirewallRule -DisplayGroup "Remote Desktop" | Get-NetFirewallAddressFilterTo undo it, put the scope back to everything:
Set-NetFirewallRule -DisplayGroup "Remote Desktop" -RemoteAddress Any-DisplayGroup "Remote Desktop" is the English name for the group. On a
localised Windows install, find the rules by pattern instead:
Get-NetFirewallRule | Where-Object { $_.DisplayName -like "*Remote Desktop*" }More on rule syntax, profiles, and outbound rules is on Using Windows Firewall.
What the panel can and cannot do here
The panel filters at the network edge, before traffic reaches your server, so it is the right place to stop an abusive source outright. On the Firewall tab, Source IPs holds two lists. Block IP drops everything from a single address at the edge, with an optional expiry, and it bypasses your port rules. That is the panel-side answer to one host hammering your Remote Desktop port: block it and it stops arriving at all.
The second list, Whitelist, is not an access restriction. It marks a source as known-good so it bypasses rate limits and behavioural filtering, which is the opposite direction of travel. Adding your own address there does not close the port to anyone else.
So the two controls do different jobs, and you want both: the Windows Firewall scope decides who may reach Remote Desktop at all, and the panel's block list takes a specific bad source out of the picture earlier, before it costs your server anything. Full detail on Blocking and allowing IPs.
Changing the Remote Desktop port
Moving Remote Desktop off 3389 is worth doing for one honest reason: it takes your logs from thousands of failed attempts a day to almost none, which makes a real attack visible instead of buried. It is not a security control. Anything that scans the whole port range finds the new port in seconds, and a scan of all 65,535 ports takes very little time. Do it for the quiet, and keep the password, NLA, lockout, and source scoping doing the actual work.
Pick a port that is free
Choose a high port and check nothing is on it:
Get-NetTCPConnection -State Listen | Sort-Object LocalPort | Select-Object LocalAddress, LocalPortOpen the new port first
Add the rule before you move the service, scoped the same way as the old one:
New-NetFirewallRule -DisplayName "Remote Desktop on 34567" -Direction Inbound -Protocol TCP -LocalPort 34567 -Action Allow -RemoteAddress "203.0.113.10"Change the port
$rdp = "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" Set-ItemProperty -Path $rdp -Name PortNumber -Value 34567Restart, and connect on the new port
The setting is read when the Remote Desktop service starts, so restart the server:
Restart-ComputerThen connect with the port on the end of the address:
mstsc /v:203.0.113.10:34567Close the old port only after the new one works
Once a fresh session on the new port succeeds, remove the old opening:
Disable-NetFirewallRule -DisplayGroup "Remote Desktop"
If you have an inbound rule for TCP 3389 in the panel, add one for the new port as well, otherwise the port's rate limits and protocol checks do not apply to it. See Port rules.
If you lock yourself out
Open Console access. It is a screen attached to the machine and it does not depend on Remote Desktop, on Windows Firewall, or on the network configuration inside the server, which is precisely the situation you are in.
From the console, sign in locally and undo the change:
Set-NetFirewallRule -DisplayGroup "Remote Desktop" -RemoteAddress Any
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
Enable-LocalUser -Name AdministratorIf the console gives you a sign-in prompt you cannot get past, the password itself is the problem rather than the firewall, and Resetting the root password is the route back, with the caveat above about disabled and renamed accounts. If none of that gets you in, open a ticket and say what you changed and when, because that is what makes it fixable.
Related
Rule syntax, inbound versus outbound, profiles, and how the on-machine firewall relates to the panel's port rules.
Blocking and allowing IPsBlocking a source at the network edge, expiries, and what the whitelist actually does.
Console accessThe way back in when Remote Desktop stops answering.