You can restrict RDP access to your server, either by IP address or a range of IP addresses, using the rules in the Windows firewall. You can actually use this same method for any open port, on any Windows PC, running Windows firewall. Show One thing before we start. If you are thinking about using this so that you can open RDP up to the internet, Dont. Even though it would work, always try to use a VPN first its much safer. You only have to check out the Shodan website to see the internet is being scanned 24/7 and it wont be long before your open RDP is being Brute Forced. If your interested in finding out how easy it is to perform a Brute force attack, check out my tutorial on Brute-Forcing passwords with THC Hydra. I have recently seen a large increase in the number of views I am getting on this tutorial. Guessing, due to lots of people working from home since Covid 19. So I have added a nice PowerShell Automation script after the manual setup, which will automatically block IPs after a specified amount of failed logins and will hopefully help someone out. Manual SetupThis Manual setup runs you through creating the firewall rule, blocking RDP port 3389, through the windows GUI. This while being remotely connected to the Windows device. The problem is when you create the block rule there are no options to specify which IPs you want to block until the rule is created. This effectively blocks your current connection and no one wants to have to talk someone through physically accessing a server to remove the rule and regain RDP access. However, to maintain your existing Remote Desktop connection you need to create an allow rule first. Once the rule is created add the IP addresses you want to block then you can change the rule from allow to block. Create The Firewall Rule
As I said earlier, If we were to set this to Block the connection now, it would block our remote session because you cant specify any connections until the rule is created.
Creating Your IP Restrictions
Adding Single addresses is fine but can be a little time consuming if youre trying to block addresses Add-Hoc. An easier and more secure option is to go with a range of addresses, Blocking every IP except the IP address you want to remotely connect from.
Switch Windows Firewall Rule From Allow to BlockWith all the IP addresses that you want to block added to the rule its time to switch the rule from Allow to Block.
If you are still remotely connected to the server after switching the rule to block. you have successfully locked down RDP without blocking your remote connection. Remember you can use this same procedure to block access to any port with the windows firewall. however, you probably wont need to create it as an allow rule first unless you want to maintain access to the port while its being configured. Automating the Rule with PowerShellWith PowerShell and the NetFirewallRule module, you can create a script that automatically blocks IP addresses, after a specified amount of failed logins. We can even get this to run whenever a failed login event 4635 is generated. The NetFirewallrule is only available in Server 2012\windows 8 and above if your trying to do this in Server 2008\windows7 let me know in the comments below and ill show you how to change the code using netsh advfirewall command instead. Create the Firewall RulePreviously, we used the Windows GUI to create our Custom RDP Block rule. However, We can make the rule even quicker using PowerShell with the NetFirewallRule module. For some reason, you have to add two IPs to the block rule for the PowerShell script to work. Otherwise, if you use a single IP it mashes into the IPs collected from the event and you get an output like 1.1.1.1192.168.0.15. If you know why this happens, please let me know in the comments below.
The PowerShell ScriptNow its time to download the PowerShell Script i created. This basically pulls the IP address out of 4625 failed logon events from event viewer and adds this to our Custom RDP Block rule. You can download failedlogins.ps1 from the Security Tutorials Git Hub page # Past number of hours is how meany hours back you want to search in the security log $Past_n_Hours = [DateTime]::Now.AddHours(-3)# Collect Failed login events (4625) from the security log $badRDPlogons = Get-EventLog -LogName 'Security' -after $Past_n_Hours -InstanceId 4625 | ?{$_.Message -match 'logon type:\s+(3)\s'} | Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]} }# Pull out the Ip Addresses of the failed logins$getip = $badRDPlogons | group-object -property IpAddress | where {$_.Count -gt 5} | Select -property Name# Creates Log$log = "C:\FailedLogins\rdp_blocked_ip.txt"#Takes the current IPs already in the block list$current_ips = (Get-NetFirewallRule -DisplayName "CUSTOM RDP BLOCK" | Get-NetFirewallAddressFilter ).RemoteAddress#Takes each IP captured and adds it to logforeach ($ip in $getip){$current_ips += $ip.name(Get-Date).ToString() + ' ' + $ip.name + ' The IP address has been blocked due to ' + ($badRDPlogons | where {$_.IpAddress -eq $ip.name}).count + ' attempts for 2 hours'>> $log # writing the IP blocking event to the log file}#Adds current ips to the CUSTOM RDP BLOCK ruleSet-NetFirewallRule -DisplayName "CUSTOM RDP BLOCK" -RemoteAddress $current_ipsCreate the Log FolderFor the Script to work you will need to create somewhere for the log files to be saved too. By default this is C:\FailedLogins, However, this can be any location but you will also need to edit the $log location in the Failedlogins.ps1 PowerShell script. Copy the FaliedLogins.ps1 to this log folder once you have created It. This is optional but will make it easier to follow along with this tutorial. Time to TestWith FailedLogins.ps1 downloaded, and the log folder created, its time to test the script.
Remember if you are connecting remotely not to block out your connecting IP and test this from somewhere else.
Once the script runs, the IP address you where spamming, failed logins from will be blocked and you no longer will be able to RDP from that IP. You should also see the IP address in the Custom RDP Block firewall rule. Automating the ScriptNow we could just set up a scheduled task to run the script every few hours, which would work just fine or you could just run the script manually. However, my preferred method is to attach the script to run whenever a 4625 Failed login event is generated. This makes the PowerShell script, work like a very basic IDS (Intrusion Detection System).
Add the arguments listed below to tell the task to bypass the Execution Policy and the location of the FailedLogins.ps1 script. -ExecutionPolicy Bypass -FILE "C:\FailedLogins\FailedLogins.ps1
Final TestNow try spamming the wrong password at the RDP Connection again. This will eventually fire the script and block the IP Address from connecting any more. Let me know in the comments below how you found it Implementing FailedLogins in your environment. Maybe you have found an easier way of implementing this or modified my PowerShell script, I want to hear from you. If you are interested in how to perform a brute force attack on an RDP connection check out my Brute Forcing Passwords with THC Hydra Tutorial. |