Start typing to search across invoices, services, domains, tickets, and more...
A Windows server on the public internet gets scanned on port 3389 and hit by password-guessing within minutes of booting, so Windows VPS security hardening should be your first task. For Windows Server 2016/2019/2022, this guide walks through a strong and renamed Administrator account, an account lockout policy, RDP Network Level Authentication, restricting RDP to your IP, disabling unused services, checking Microsoft Defender and auditing failed logons (event 4625) with Get-WinEvent.
Use at least 16 characters mixing upper and lower case, digits and symbols, and never reuse it elsewhere. Almost every brute-force tool targets the user name Administrator, so renaming it stops most untargeted attacks.
# Set a new strong password (you will be prompted, nothing is echoed)
net user Administrator *
# Rename the built-in Administrator account
Rename-LocalUser -Name "Administrator" -NewName "srvadmin"
Get-LocalUser | Format-Table Name,Enabled,LastLogonA lockout policy temporarily locks accounts after repeated wrong passwords, which slows brute-force attacks dramatically. You can also set it in secpol.msc → Account Policies → Account Lockout Policy.
# Lock an account for 30 minutes after 5 failed attempts within 30 minutes
net accounts /lockoutthreshold:5 /lockoutduration:30 /lockoutwindow:30
net accountsNLA requires authentication before a full Remote Desktop session is created, reducing resource use by unauthenticated connections and mitigating some RDP vulnerabilities. Tick "Allow connections only from computers running Remote Desktop with Network Level Authentication" in System Properties → Remote, or run:
$rdp = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
Set-ItemProperty -Path $rdp -Name UserAuthentication -Value 1
Get-ItemProperty -Path $rdp -Name UserAuthentication, PortNumberThis is the single most effective protection against RDP brute force. The commands edit the built-in Remote Desktop firewall rules so that only your office IP or subnet can connect. The rule names are identical on every OS language. If you changed the RDP port and created a custom rule, set -RemoteAddress on that rule too.
# Built-in Remote Desktop rules (names are the same on every OS language)
Set-NetFirewallRule -Name RemoteDesktop-UserMode-In-TCP, RemoteDesktop-UserMode-In-UDP -RemoteAddress 203.0.113.10, 198.51.100.0/24
Get-NetFirewallRule -Name RemoteDesktop-UserMode-In-TCP | Get-NetFirewallAddressFilter
# Undo: allow RDP from anywhere again
Set-NetFirewallRule -Name RemoteDesktop-UserMode-In-TCP, RemoteDesktop-UserMode-In-UDP -RemoteAddress AnyEvery running service is attack surface. List running services and stop the ones you do not need. The Print Spooler is rarely needed on a server and has had serious vulnerabilities. Leave system services alone if you are unsure what they do.
Get-Service | Where-Object { $_.Status -eq "Running" } | Sort-Object DisplayName | Format-Table Name,DisplayName
# Example: print spooler is rarely needed on a server
Stop-Service -Name Spooler
Set-Service -Name Spooler -StartupType DisabledWindows Server 2016 and later include Microsoft Defender Antivirus. Confirm real-time protection is on, update signatures and run a quick scan.
Get-MpComputerStatus | Select-Object AMServiceEnabled,RealTimeProtectionEnabled,AntivirusSignatureLastUpdated
Set-MpPreference -DisableRealtimeMonitoring $false
Update-MpSignature
Start-MpScan -ScanType QuickScanEvent ID 4625 records a failed logon. The commands below list recent failures and the source IPs with the most attempts in the last 24 hours, so you can see whether you are under attack and block offenders with a firewall rule.
# Make sure failed logons are audited (GUID = "Logon" subcategory, language independent)
auditpol /set /subcategory:"{0CCE9215-69AE-11D9-BED3-505054503030}" /failure:enable
# Last 20 failed logons
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 20 |
Select-Object TimeCreated, @{n='User';e={$_.Properties[5].Value}}, @{n='SourceIP';e={$_.Properties[19].Value}}
# Top attacking IPs in the last 24 hours
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=(Get-Date).AddDays(-1)} |
ForEach-Object { $_.Properties[19].Value } | Group-Object | Sort-Object Count -Descending |
Select-Object -First 10 Count, NameIt reduces automated scan noise but does not replace a strong password and IP restriction. Combine all three; see our "change the Windows RDP port" guide.
Allow your ISP's range, or connect through a jump host or VPN with a fixed IP and open Remote Desktop from there.
Usually the logon was local or the address was not captured during NLA. If you see many, correlate them with firewall logs.
Still stuck after following these steps? Open a support ticket and the IMIDC 24/7 technical team will help. Please include the server IP, OS version, the commands you ran and a screenshot of the error so we can pinpoint the issue faster.