Windows OS Hub
  • Windows Server
    • Windows Server 2022
    • Windows Server 2019
    • Windows Server 2016
    • Windows Server 2012 R2
    • Windows Server 2012
    • Windows Server 2008 R2
    • SCCM
  • Active Directory
    • Active Directory Domain Services (AD DS)
    • Group Policies
  • Windows Clients
    • Windows 11
    • Windows 10
    • Windows 8
    • Windows 7
    • Windows XP
    • MS Office
    • Outlook
  • Virtualization
    • VMWare
    • Hyper-V
    • KVM
  • PowerShell
  • Exchange
  • Cloud
    • Azure
    • Microsoft 365
    • Office 365
  • Linux
    • CentOS
    • RHEL
    • Ubuntu
  • Home
  • About

Windows OS Hub

  • Windows Server
    • Windows Server 2022
    • Windows Server 2019
    • Windows Server 2016
    • Windows Server 2012 R2
    • Windows Server 2012
    • Windows Server 2008 R2
    • SCCM
  • Active Directory
    • Active Directory Domain Services (AD DS)
    • Group Policies
  • Windows Clients
    • Windows 11
    • Windows 10
    • Windows 8
    • Windows 7
    • Windows XP
    • MS Office
    • Outlook
  • Virtualization
    • VMWare
    • Hyper-V
    • KVM
  • PowerShell
  • Exchange
  • Cloud
    • Azure
    • Microsoft 365
    • Office 365
  • Linux
    • CentOS
    • RHEL
    • Ubuntu

 Windows OS Hub / PowerShell / RDP Brute Force Protection with PowerShell and Windows Firewall Rules

May 21, 2020 PowerShellWindows 10Windows Server 2016

RDP Brute Force Protection with PowerShell and Windows Firewall Rules

I have had an idea to write a simple PowerShell script to automatically block (blacklist) IP addresses, on which RDP brute-force attempts or continuous RDP attacks are detected, in Windows Firewall. The idea is as follows: the PowerShell script analyzes the system event log and if there have been more than 5 failed attempts to authenticate via RDP from the same IP address in the last three hours, the IP address is automatically added to Windows Firewall blocking rule.

So, there is a small office network. To access it, an RDP port is forwarded through NAT to one of the office computers via the Internet gateway running Linux (TCP 15221 is answering from the outside, and the default RDP port 3389 is forwarded inside). From time to time, known user accounts are locked by the domain password policy due to failed attempts to authenticate on the computer via RDP. Our task is to automatically block IP addresses used to brute force our RDP server.

First of all, create a firewall rule on the computer to block inbound RDP connections from the specified IP addresses:

New-NetFirewallRule -DisplayName "BlockRDPBruteForce" –RemoteAddress 1.1.1.1 -Direction Inbound -Protocol TCP –LocalPort 3389 -Action Block

New-NetFirewallRule - create new firewall rule to block incoming RDP requests by an IP address

We will further add the IP addresses, on which RDP brute-force attempts are detected, to this rule firewall.

You can write an additional allowing rule so that the PowerShell script won’t block the IP addresses or subnets you need.

Then you will have to collect the list of IP addresses, on which more than 5 failed authentication attempts have been detected for the last 3 hours, from the Windows event log. To do it, find the events with the EventID 4625 (failed access attempt — An account failed to log on and LogonType = 3, check the article RDP Event Log Forensics) in the Security log. In the events you have found, find the IP address of the user trying to connect and make sure that it appeared in the event log more than 5 times.

I am using the following PowerShell code to select the IP addresses of attackers from the list of events for the last 3 hours (you can change the time period):

$Last_n_Hours = [DateTime]::Now.AddHours(-3)
$badRDPlogons = Get-EventLog -LogName 'Security' -after $Last_n_Hours -InstanceId 4625 | ?{$_.Message -match 'logon type:\s+(3)\s'} | Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]} }
$getip = $badRDPlogons | group-object -property IpAddress | where {$_.Count -gt 5} | Select -property Name

To display the list of found IP addresses, use: $getip

Now add all found IP addresses of attackers to the firewall rule BlockRDPBruteForce created earlier. To manage Windows Firewall, we will use the built-in PowerShell module NetSecurity. First of all, get the list of currently blocked IP addresses and add new ones to it.

$log = "C:\ps\rdp_blocked_ip.txt"
$current_ips = (Get-NetFirewallRule -DisplayName "BlockRDPBruteForce" | Get-NetFirewallAddressFilter ).RemoteAddress
foreach ($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
}
Set-NetFirewallRule -DisplayName "BlockRDPBruteForce" -RemoteAddress $current_ips

powershell script to automatically block RDP attacks in Windows Firewall

Make sure that new IP addresses have been added to the blocking rule in Windows Defender Firewall.

block rdp attacks by IP address in Windows firewall

Now you just have to copy this PowerShell code to the file c:\ps\block_rdp_attack.ps1 and add it to your Task Scheduler to run every 2 hours, for example.

You can create a Scheduler task using a PowerShell script or manually:

$repeat = (New-TimeSpan -Hours 2)
$duration = ([timeSpan]::maxvalue)
$Trigger= New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval $repeat -RepetitionDuration $duration
$User= "NT AUTHORITY\SYSTEM"
$Action= New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "C:\PS\block_rdp_attack.ps1"
Register-ScheduledTask -TaskName "BlockRDPBruteForce_PS" -Trigger $Trigger -User $User -Action $Action -RunLevel Highest –Force

Or you can run your PowerShell script if the EventID 4625 appears in the log (check the blogpost Windows Event Triggers), so you will respond to an RDP brute-force attack more quickly.

You can modify this script according to your needs and use to block RDP attacks.

12 comments
10
Facebook Twitter Google + Pinterest
previous post
Configuring Windows Firewall Rules with PowerShell
next post
How to Install & Configure Repositories in CentOS/RHEL?

Related Reading

Configure User’s Folder Redirection with Group Policy

February 3, 2023

Disable Built-in PDF Viewer in Microsoft Edge

February 3, 2023

Join a Windows Computer to an Active Directory...

February 2, 2023

Using Previous Command History in PowerShell Console

January 31, 2023

How to Install the PowerShell Active Directory Module...

January 31, 2023

12 comments

WS June 13, 2020 - 10:25 pm

Excellent script !
A very minor point is that the script looks for the attempts of the last 3 hours ($Last_n_Hours = [DateTime]::Now.AddHours(-3)) but logs ‘ attempts for 2 hours’. I used a variable instead in order to customise easily and print the corresponding value.
Thank you so much.

Reply
R0man June 21, 2020 - 1:24 pm

Very useful THANK YOU
Only thing I inserted due of error for Set-NetFirewallRule saying “The address is invalid”:

$current_ips = @()
$currentIps = (Get-NetFirewallRule -DisplayName “BlockRDPBruteForce” | Get-NetFirewallAddressFilter ).RemoteAddress
foreach ($cip in $currentIps)
{
$current_ips += $cip
}

Reply
Federico October 27, 2020 - 4:16 pm

Hello, I’m having trouble with this scrip
I get “The address is invalid” when I run it and when add what R0MAN suggest I get no error but nothing is added to the firewall rule… any idea what I’m doing wrong?
Thanks in advance.

Reply
Dean February 11, 2021 - 10:08 am

Hi Federico

Did you ever find the solution. Battling with this aswell

Reply
federico February 11, 2021 - 11:28 am

Sadly no, I never find a solution to this.

Reply
Brett March 10, 2021 - 6:01 am

Replace
$currentIps = (Get-NetFirewallRule -DisplayName “BlockRDPBruteForce” | Get-NetFirewallAddressFilter ).RemoteAddress
With
$current_ips = @((Get-NetFirewallRule -DisplayName “BlockRDPBruteForce” | Get-NetFirewallAddressFilter ).RemoteAddress)

And it should work.

Reply
Sarge February 23, 2021 - 4:49 pm

The script to create the firewall rule works but then the next script to select the offending IPs gives me this error… What is wrong here?

At line:1 char:45
+ $Last_n_Hours = [DateTime]::Now.AddHours(-3)$badRDPlogons = Get-EventLog -LogNam …
+ ~~~~~~~~~~~~~
Unexpected token ‘$badRDPlogons’ in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken

Reply
Rahil Sarwar March 17, 2021 - 12:24 pm

$Last_n_Hours = [DateTime]::Now.AddHours(-3)
$badRDPlogons = Get-EventLog -LogName ‘Security’ -after $Last_n_Hours -InstanceId 4625 | ?{$_.Message -match ‘logon type:\s+(3)\s’} | Select-Object @{n=’IpAddress’;e={$_.ReplacementStrings[-2]} }
$getip = $badRDPlogons | group-object -property IpAddress | where {$_.Count -gt 5} | Select -property Name
$log = “C:\ps\rdp_blocked_ip.txt”
$current_ips = @((Get-NetFirewallRule -DisplayName “BlockRDPBruteForce” | Get-NetFirewallAddressFilter ).RemoteAddress)
foreach ($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
}
$current_ips = $current_ips | select -Unique
Set-NetFirewallRule -DisplayName “BlockRDPBruteForce” -RemoteAddress $current_ips

Reply
Joshua September 2, 2021 - 12:36 pm

Can anyone post the whole script in its entirety once its working?

Reply
xcx June 6, 2022 - 8:49 pm

$Last_n_Hours = [DateTime]::Now.AddHours(-6)
$badRDPlogons = Get-EventLog -LogName ‘Security’ -after $Last_n_Hours -InstanceId 4625 | Where-Object { $_.Message -match ‘logon type:\s+(3)\s’ } | Select-Object @{n = ‘IpAddress’; e = { $_.ReplacementStrings[-2] } }
$getip = $badRDPlogons | group-object -property IpAddress | Where-Object { $_.Count -gt 10 } | Select-Object -property Name
$log = “C:\ps\rdp_blocked_ip.txt”
$current_ips = @(Get-NetFirewallRule -DisplayName “_BlockRDPBruteForce” | Get-NetFirewallAddressFilter ).RemoteAddress | Sort-Object -Unique
foreach ($ip in $getip) {
$current_ips += $ip.name
(Get-Date).ToString() + ‘ ‘ + $ip.name + ‘ The IP address has been blocked due to ‘ + ($badRDPlogons | Where-Object { $_.IpAddress -eq $ip.name }).count + ‘ attempts for 6 hours’>> $log # writing the IP blocking event to the log file
}
‘Script ran’ >> $log
Set-NetFirewallRule -DisplayName “_BlockRDPBruteForce” -RemoteAddress $current_ips

Reply
José October 19, 2022 - 5:17 pm

On the last part:
Set-NetFirewallRule -DisplayName “BlockRDPBruteForce” -RemoteAddress $current_ips
I’m getting the error: The address is invalid. Addresses may be specified as IP addresses, ranges, or subnets.
somehow it’s not parsing it correctly, anyone has run to this?

Reply
Prescott Chartier December 29, 2022 - 5:49 pm

$getip returns nothing. Looking at the log entries and none of the 4625 entries have an IP address in them, how is this possible?

Reply

Leave a Comment Cancel Reply

Categories

  • Active Directory
  • Group Policies
  • Exchange Server
  • Microsoft 365
  • Azure
  • Windows 11
  • Windows 10
  • Windows Server 2022
  • Windows Server 2019
  • Windows Server 2016
  • PowerShell
  • VMWare
  • Hyper-V
  • Linux
  • MS Office

Recent Posts

  • Configure User’s Folder Redirection with Group Policy

    February 3, 2023
  • Using Previous Command History in PowerShell Console

    January 31, 2023
  • How to Install the PowerShell Active Directory Module and Manage AD?

    January 31, 2023
  • Finding Duplicate E-mail (SMTP) Addresses in Exchange

    January 27, 2023
  • How to Delete Old User Profiles in Windows?

    January 25, 2023
  • How to Install Free VMware Hypervisor (ESXi)?

    January 24, 2023
  • How to Enable TLS 1.2 on Windows?

    January 18, 2023
  • Allow or Prevent Non-Admin Users from Reboot/Shutdown Windows

    January 17, 2023
  • Fix: Can’t Extend Volume in Windows

    January 12, 2023
  • Wi-Fi (Internet) Disconnects After Sleep or Hibernation on Windows 10/11

    January 11, 2023

Follow us

woshub.com
  • Facebook
  • Twitter
  • RSS
Popular Posts
  • Installing RSAT Administration Tools on Windows 10 and 11
  • Get-ADUser: Find Active Directory User Info with PowerShell
  • How to Hide Installed Programs in Windows 10 and 11?
  • Managing Printers and Drivers with PowerShell in Windows 10 / Server 2016
  • How to Create a UEFI Bootable USB Drive to Install Windows 10 or 7?
  • PowerShell: Get Folder Sizes on Disk in Windows
  • Deploy PowerShell Active Directory Module without Installing RSAT
Footer Logo

@2014 - 2023 - Windows OS Hub. All about operating systems for sysadmins


Back To Top