Are you being under attack? Here's a script that will block those attackers out

If you have had a public-facing server in your company, you will know that there are a lot of people without scruples that will try to hack into your server and steal your data (or simply do it for fun). I have had two servers now with different providers and the same thing happened over and over again. Unless the server was locked down to one single access IP, I would have thousands and thousands of hacking attempts per hour, every day, every week. After going through the event logs trying to figure out if any of them were successful, I found the need to automate IP blocking.

I had a list of 200+ IP I would block (mostly from China), and no sooner I would finish the block, another attempt would start. It would last between 1 min and 2h under which the server would receive continuous login attempts with usernames and passwords. I had to change the administrator username as it would be locked out after a few attempts. I could not face this on my own so I found this nice little power shell script to help.



This is trying to find attacking IP address then add it into Firewall block rule.

Server Setup:

  1. You are running a Windows Server 2008 facing the Internet.
  2. You need to have some port open for service, e.g. TCP 21 for FTP; TCP 3389 for Remote Desktop. You can see in my code I’m only dealing with these two since that’s what I opened. You can add further port number if you like, but the way to process might be different with these two.
  3. I strongly suggest you use STRONG password and follow all security best practices, this ps1 code is NOT for adding security to your server, but reduce the nuisance from brute force attack, and make sys admin’s life easier: i.e. your FTP log won’t hold megabytes of nonsense, your Windows system log will not roll back and only can tell you what happened last month.
  4. You are comfortable with setting up Windows Firewall rules, in my code, my rule has a name of “MY BLACKLIST”, you need to setup a similar one, and set it to BLOCK everything.
  5. My rule is dangerous because it has the risk to block myself out as well. I do have a backup plan i.e. the DELL DRAC5 so that if that happens, I still can remote console to my server and reset the firewall.
  6. By no means the code is perfect, the coding style, the use of PowerShell skills, the hard coded part, all can be improved, it’s just that it’s good enough for me already. It has been running on my server for more than 7 MONTHS.
  7. Current code still has problem, I didn’t solve it yet, further on this point after the code. 🙂

#Dong Xie, March 2012

#my simple code to monitor attack and deal with it
#Windows Server 2008 Logon Type
#8: NetworkCleartext, i.e. FTP
#10: RemoteInteractive, i.e. RDP

$tick = 0;
“Start to run at: ” + (get-date);

$regex1 = [regex] “192.168.100.(?:101|102):3389s+(d+.d+.d+.d+)”;
$regex2 = [regex] “Source Network Address:t(d+.d+.d+.d+)”;

while($True) {
$blacklist = @();

“Running… (tick:” + $tick + “)”; $tick+=1;

#Port 3389
$a = @()
netstat -no | Select-String “:3389” | ? { $m = $regex1.Match($_); `
$ip = $m.Groups[1].Value; if ($m.Success -and $ip -ne “”) {$a = $a + $ip;} }

if ($a.count -gt 0) {
$ips = get-eventlog Security -Newest 1000 | Where-Object {$_.EventID -eq 4625 -and $_.Message -match “Logon Type:s+10”} | foreach { `
$m = $regex2.Match($_.Message); $ip = $m.Groups[1].Value; $ip; } | Sort-Object | Tee-Object -Variable list | Get-Unique

foreach ($ip in $a) { if ($ips -contains $ip) {
if (-not ($blacklist -contains $ip)) {
$attack_count = ($list | Select-String $ip -SimpleMatch | Measure-Object).count;
“Found attacking IP on 3389: ” + $ip + “, with count: ” + $attack_count;
if ($attack_count -ge 20) {$blacklist = $blacklist + $ip;}

$now = (Get-Date).AddMinutes(-5); #check only last 5 mins.
#Get-EventLog has built-in switch for EventID, Message, Time, etc. but using any of these it will be VERY slow.
$count = (Get-EventLog Security -Newest 1000 | Where-Object {$_.EventID -eq 4625 -and $_.Message -match “Logon Type:s+8” -and `
$_.TimeGenerated.CompareTo($now) -gt 0} | Measure-Object).count;
if ($count -gt 50) #threshold
$ips = @();
$ips1 = dir “C:inetpublogsLogFilesFPTSVC2” | Sort-Object -Property LastWriteTime -Descending `
| select -First 1 | gc | select -Last 200 | where {$_ -match “An+error+occured+during+the+authentication+process.”} `
| Select-String -Pattern “(d+.d+.d+.d+)” | select -ExpandProperty Matches | select -ExpandProperty value | Group-Object `
| where {$_.Count -ge 10} | select -ExpandProperty Name;

$ips2 = dir “C:inetpublogsLogFilesFTPSVC3” | Sort-Object -Property LastWriteTime -Descending `
| select -First 1 | gc | select -Last 200 | where {$_ -match “An+error+occured+during+the+authentication+process.”} `
| Select-String -Pattern “(d+.d+.d+.d+)” | select -ExpandProperty Matches | select -ExpandProperty value | Group-Object `
| where {$_.Count -ge 10} | select -ExpandProperty Name;
$ips += $ips1; $ips += $ips2; $ips = $ips | where {$_ -ne “”} | Sort-Object | Get-Unique;

foreach ($ip in $ips) {
if (-not ($blacklist -contains $ip)) {
“Found attacking IP on FTP: ” + $ip;
$blacklist = $blacklist + $ip;

#Firewall change

<# $current = (netsh advfirewall firewall show rule name=”MY BLACKLIST” | where {$_ -match “RemoteIP”}).replace(“RemoteIP:”, “”).replace(” “,””).replace(“/″,””); #inside $current there is no r or n need remove. foreach ($ip in $blacklist) { if (-not ($current -match $ip) -and -not ($ip -like “10.0.0.*”)) {“Adding this IP into firewall blocklist: ” + $ip; $c= ‘netsh advfirewall firewall set rule name=”MY BLACKLIST” new RemoteIP=”{0},{1}”‘ -f $ip, $current; Invoke-Expression $c; } } #>

foreach ($ip in $blacklist) {

$fw=New-object –comObject HNetCfg.FwPolicy2; #
$myrule = $fw.Rules | where {$_.Name -eq “MY BLACKLIST”} | select -First 1; # Potential bug here?

if (-not ($myrule.RemoteAddresses -match $ip) -and -not ($ip -like “10.0.0.*”))
{“Adding this IP into firewall blocklist: ” + $ip;

Wait-Event -Timeout 30 #pause 30 secs

} # end of top while loop.


Further points:

1, I suppose the server is listening on port 3389 on server IP: and, you need to replace that with your real IP.

2, I suppose you are Remote Desktop to this server from a workstation with IP: Please replace as well.

3, The threshold for 3389 attack is 20, you don’t want to block yourself just because you typed your password wrong 3 times, you can change this threshold by your own reasoning.

4, FTP is checking the log for attack only to the last 5 mins, you can change that as well.

5, I suppose the server is serving FTP on both IP address and their LOG path are C:inetpublogsLogFilesFPTSVC2 and C:inetpublogsLogFilesFPTSVC3. Change accordingly.

6, FTP checking code is only asking for the last 200 lines of log, and the threshold is 10, change as you wish.

7, the code runs in a loop, you can set the loop time at the last line.

To run this code, copy and paste to your editor, finish all the editing, get it to your server, and open an CMD window, then type powershell.exe –file your_powershell_file_name.ps1, it will start running, you can Ctrl-C to break it.

This is what you see when it’s running:


This is when it detected attack and adding the firewall rule:


Regarding the design of the code:

1, There are many ways you can detect the attack, but to add an IP into a block rule is no small thing, you need to think hard before doing it, reason for that may include: You don’t want block yourself; and not blocking your customer/user, i.e. the good guy.

2, Thus for each service/port, I double check. For 3389, first it needs to show in netstat.exe, then the Event log; for FTP, first check the Event log, then the FTP log files.

3, At three places I need to make sure I’m not adding myself into the block rule. –ne with single IP, –like with subnet.

Now the final bit:

1, The code will stop working after a while (depends on how busy you are attacked, could be weeks, months, or days?!) It will throw Red error message in CMD, don’t Panic, it does no harm, but it also no longer blocking new attack. THE REASON is not confirmed with MS people: the COM object to manage firewall, you can only give it a list of IP addresses to the length of around 32KB I think, once it reaches the limit, you get the error message.

2, This is in fact my second solution to use the COM object, the first solution is still in the comment block for your reference, which is using netsh, that fails because being run from CMD, you can only throw it a list of IP to 8KB.

3, I haven’t worked the workaround yet, some ideas include: wrap that RemoteAddresses setting line with error checking and once it reaches the limit, use the newly detected IP to be the list, not appending to it. This basically reset your block rule to ground zero and lose the previous bad IPs. This does no harm as it sounds, because given a certain period has passed, any these bad IPs still not repent and continue the attack to you, it only got 30 seconds or 20 guesses of your password before you block it again. And there is the benefit that the bad IP may turn back to the good hands again, and you are not blocking a potential customer or your CEO’s home pc because once upon a time, it’s a zombie. Thus the ZEN of blocking: never block any IP for too long.

4, But if you insist to block the ugly forever, my other ideas include: You call MS support, ask them how can we set an arbitrary length of IP addresses in a rule; at least from my experiences at the Forum, they don’t know and they don’t care, because they think the dynamic blocking should be done by some expensive hardware. Or, from programming perspective, you can create a new rule once the old is full, then you’ll have MY BLACKLIST1, MY  BLACKLIST2, MY BLACKLIST3, … etc. Once in a while you can compile them together and start a business to sell your blacklist on the market!

Enjoy the code!

p.s. (PowerShell is REALLY REALLY GREAT!)


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.