Ban IP address based on X number of unsuccessful login attempts?
Solution 1
You can do this with powershell and task manager. It's probably not perfect solution, but it works quite well and i have about 100 blocked IP addresses in two months. I wrote script, that select from EventLog specified events ("audit failure"). If there are many failed logins from any IP address, then it's added to firewall rule (created manually) named "BlockAttackers" which blocks any traffic to specified ip addresses.
PS1 Script:
$DT = [DateTime]::Now.AddDays(-1) # check only last 24 hours
$l = Get-EventLog -LogName 'Security' -InstanceId 4625 -After $DT | Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]} } # select Ip addresses that has audit failure
$g = $l | group-object -property IpAddress | where {$_.Count -gt 20} | Select -property Name # get ip adresses, that have more than 20 wrong logins
$fw = New-Object -ComObject hnetcfg.fwpolicy2 # get firewall object
$ar = $fw.rules | where {$_.name -eq 'BlockAttackers'} # get firewall rule named 'BlockAttackers' (must be created manually)
$arRemote = $ar.RemoteAddresses -split(',') #split the existing IPs into an array so we can easily search for existing IPs
$w = $g | where {$_.Name.Length -gt 1 -and !($arRemote -contains $_.Name + '/255.255.255.255') } # get ip addresses that are not already in firewal rule. Include the subnet mask which is automatically added to the firewall remote IP declaration.
$w| %{$ar.remoteaddresses += ',' + $_.Name} # add IPs to firewall rule
Create task in scheduler and set trigger to event 4625 (windows login including terminal services). But you can set trigger to run e.g. twice per hour to avoid unnecessary loading the server.
and after trigger run powershell script. You must also set higher privileges to run this script, otherwise it will fail with security exception.
You can also bind this script to other security events.
Solution 2
I know this question is old but it was actually the first forum post I stumbled across when I started trying to do this exact same thing a couple weeks ago. I've managed to come up with a working script that will parse the event logs 24 hours back for only bad login event log entries, grab the ones that have more than 10 bad logins, and then put them into an ipsec filter list using the netsh command. Then I wrote a batch file with this line powershell .\*scriptname.ps1*
and created a scheduled task to run the batch file every 24 hours (for some reason it wouldn't execute directly).
$DATE = [DateTime]::Now.AddDays(-1)
$EVS = Get-EventLog Security -InstanceId 529 -after $DATE
$EVS | select-string -inputobject {$_.message} -pattern "Source Network Address:(.)*\.*\.*\.*" -allmatches | foreach-object {$_.Matches} | foreach-object {$_.Value} | foreach-object {$_.replace("Source Network Address:", "")} | group-object -property $_ | where-object {$_.count -gt 10} | select-object -property name | format-list | out-file c:\rdpblock.txt
get-content -path c:\rdpblock.txt | foreach-object {$_.replace("Name :", "")} | out-file c:\rdpblockcleaned.txt
get-content -path c:\rdpblockcleaned.txt | select-object -unique | out-file c:\rdpblocknospaces.txt
$RDPIP = get-content -path c:\rdpblocknospaces.txt | select-object -skip 1
$RDPIP | foreach-object {$_.replace(" ", "")} | foreach-object {netsh ipsec static add filter filterlist=RDP_BLOCK srcaddr=$($_) dstaddr=any}
I know that this script is probably inefficient but when I started working on this I had absolutely no experience in powershell, so my ability to optimize scripts leaves alot to be desired. However, despite this fact I thought I would share this with anyone who could use it.
I thank Remunda for giving me the initial idea, that poster is the one that turned me on to the idea of using powershell to search the event logs.
Solution 3
This script builds on remunda's answer and goes a little further https://serverfault.com/a/397637/155102 It accounts for the "BlockAttackers" rule not have any IPs entered yet (which returns a "*" as a string). It also writes a comment to a log file to let you know when the IP was added to the rule.
A good tip is to create the "BlockAttackers" rule that blocks the IP addresses BUT make it disabled at first. Then, run this script once manually so it can populate the "RemoteAddresses" field with actual IP addresses that should be blocked. Take a look at those IP addresses to make sure nothing critical has been added and then enable the firewall rule. Add this rule to your firewall as remunda described.
#Checks for IP addresses that used incorrect password more than 10 times
#within 24 hours and blocks them using a firewall rule 'BlockAttackers'
#Check only last 24 hours
$DT = [DateTime]::Now.AddHours(-24)
#Select Ip addresses that has audit failure
$l = Get-EventLog -LogName 'Security' -InstanceId 4625 -After $DT | Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]} }
#Get ip adresses, that have more than 10 wrong logins
$g = $l | group-object -property IpAddress | where {$_.Count -gt 10} | Select -property Name
#Get firewall object
$fw = New-Object -ComObject hnetcfg.fwpolicy2
#Get firewall rule named 'BlockAttackers' (must be created manually)
$ar = $fw.rules | where {$_.name -eq 'BlockAttackers'}
#Split the existing IPs into an array so we can search it for existing IPs
$arRemote = $ar.RemoteAddresses -split(',')
#Only collect IPs that aren't already in the firewall rule
$w = $g | where {$_.Name.Length -gt 1 -and !($arRemote -contains $_.Name + '/255.255.255.255') }
#Add the new IPs to firewall rule
$w| %{
if ($ar.RemoteAddresses -eq '*') {
$ar.remoteaddresses = $_.Name
}else{
$ar.remoteaddresses += ',' + $_.Name
}
}
#Write to logfile
if ($w.length -gt 1) {
$w| %{(Get-Date).ToString() + ' ' + $_.Name >> '.\blocked.txt'}
}
Solution 4
I can't take credit for this answer, but https://serverfault.com/users/7200/evan-anderson has mentioned his project http://opensource.wellbury.com/projects/windows_sshd_block/newest-release/
Solution 5
It's generally not a good idea to let somebody else control your firewall rules. That's basically what you're asking for here.
Related videos on Youtube
HeavyWave
Updated on September 17, 2022Comments
-
HeavyWave almost 2 years
Is it possible to ban an IP address after X number of unsuccessful login attempts to a Windows Server? Not to a particular account, which I know how to do, but to the whole machine.
We get hit pretty hard by brute force attacks trying to guess usernames, so this would really help get some load off the server.
-
Chris Nava over 13 years*nix has fial2ban... not sure if there's a Windows equivalent/port. fail2ban.org/wiki/index.php/Main_Page
-
Admin over 13 yearsFrom Evan Anderson: serverfault.com/questions/43360/… ...looks to be a good equivalent of fail2ban's functionality but as your question is not specific enough, I don't know if you're looking to ban IPs attempting to login to a hosted website, your server (via SSH) or your domain. Clarification would go a long way. Additionally you could rate limit at your firewall, but that is implementation-dependent.
-
pehrs over 13 yearsYou might want to have a look at serverfault.com/questions/216995/… for a previous discussion about how useful automated banning based on IP is.
-
Spence over 12 yearsIf you're talking about Terminal Services / Remote Desktop have a look here: serverfault.com/a/335976/7200
-
jjxtra over 12 yearsI made a windows service on github to do just that: github.com/jjxtra/Windows-IP-Ban-Service
-
Joel Coel over 11 yearsIf you get "hit hard" by these, would this end up effectively perpetually locking you out of your own server?
-
kevinmicke over 10 years@HeavyWave - were you getting hit via RDP, FTP, or something else? If it's RDP and/or FTP, I posted a Powershell script [below][serverfault.com/a/571903/107701] that will automatically block IPs after X attempts.
-
-
devicenull over 13 yearsAutomatically banning IPs after a certain number of failed logins is very common practice. I see hosts being banned on an hourly basis after trying to guess FTP passwords. The only way this can be a DoS attack is if someone managed to spoof your IP (impossible on TCP connections), or if you repeatedly mistype your password (in which case it's not someone else controlling firewall rules, it's you)
-
HeavyWave over 13 yearsSorry, but I didn't ask if it was a good idea.
-
John Gardeniers over 13 yearsOf course there is no reason exceptions couldn't be set for one or more specific IP addresses, which would pretty much eliminate the DoS concern.
-
RomanSt over 12 yearsOn my AWS small instance, 1 attempt every 4 seconds is enough to consume 50% CPU. Pretty crap if you ask me...
-
raja over 12 yearsWow, I wonder why the utilization is so high. I'll have to do some testing to see how many attempts it takes on my VMs to register.
-
RomanSt over 12 yearsI think it’s because I’m not using Network Level Authentication, so every login attempt spins up a logon UI to actually present to the attacker through a remote desktop session. I can see why that might be expensive.
-
kevinmicke over 10 yearsFYI: For those that haven't run a powershell script on a system before, you'll need to first open a new powershell and run
Set-ExecutionPolicy RemoteSigned
so you can run local scripts. Otherwise you'll get an error: "blockattackers.ps1 cannot be loaded because the execution of scripts is disabled on this system." -
kevinmicke over 10 yearsExcellent script @remunda - thanks! I was getting a lot of 4625s from FTP as well, which the Security log doesn't have IP addresses for, so I expanded upon your script to have it check the current day's FTP log as well. Please see my answer below for more info: serverfault.com/a/571903/107701
-
jjxtra over 6 yearsThere are a lot of gotchas and edge cases with the event logs, ip address logging, etc. that I've handled in IPBan - free and open source at github.com/jjxtra/Windows-IP-Ban-Service