################################################################################ # Created by Petter Angeltveit # 24.04.2020 # This is a free work, you can copy, distribute, and modify it under the terms # of the Creative Common License # ################################################################################ $LogDir = "C:\Program1\Axigen Mail Server\log" $SMTPLog = "$LogDir\SMTP Receiving.txt" $FileContent = Get-Content "$SMTPLog" $keywordPattern = "Authentication failed" $dataPattern = "closing session from" $found = $false $found1 = $false $Today = get-date -format dd.MM.yyyy $IP_Block_Log_Folder = "$env:ProgramData\Axigen\IP_Block" $Logfile = "$LogDir\SMTP Receiving check_$Today.log" [Int]$BlockLimit = 20 [Int]$BlockDays = 90 #Below checks for country and ISP of IP Address function Get-IPGeolocation { Param ( [string]$IPAddress ) $request = Invoke-RestMethod -Method Get -Uri "http://ip-api.com/json/$IPAddress" [PSCustomObject]@{ IP = $request.query City = $request.city Country = $request.country Isp = $request.isp } } #Below checks if IP_Block log folder exists, creates it if it does not if (-Not(Test-Path "$IP_Block_Log_Folder")) { New-Item -ItemType "directory" -Path "$IP_Block_Log_Folder" } #Below goes through the SMTP Receiving Log and checks for failed login attempts and logs them to a log file. # Also blocks the IP in the windows Firewall, if the number of attempts was larger than the BlockLimit foreach ($line in $FileContent) { if ($line.contains($keywordPattern)) { $found = $true } if (($line.contains($dataPattern)) -and ($found)) { # https://stackoverflow.com/questions/11299893/powershell-regex-check-for-string-between-brackets $r = [regex] "\[([^\[]*)\]" $match = $r.match("$line") $text = $match.groups[1].value $text1 = $text.split(':')[0] $Logfile1 = "$IP_Block_Log_Folder\Axigen IP-Block_$($Text1)_$($BlockDays)d.log" if (test-path $Logfile) { $LogContent = Get-Content $Logfile if (-not($LogContent -like "*$text1*")) { Get-IPGeoLocation -ipaddress $text1 >> $LogFile $A = Get-ChildItem -Path $SMTPLog | Select-String -Pattern "$text1" [Int]$CountMatches = [math]::Round($A.Matches.Length/2) Write-Output "Found '$Text1' $CountMatches Times" >> $LogFile If ($CountMatches -ge $BlockLimit) { Write-Output "Blocking IP '$Text1' for $BlockDays Days" >> $LogFile } Write-Output "------------------------------------------------" >> $LogFile } }else { Get-IPGeoLocation -ipaddress $text1 >> $LogFile $A = Get-ChildItem -Path $SMTPLog | Select-String -Pattern "$text1" [Int]$CountMatches = [math]::Round($A.Matches.Length/2) Write-Output "Found '$Text1' $CountMatches Times" >> $LogFile If ($CountMatches -ge $BlockLimit) { Write-Output "Blocking IP '$Text1' for $BlockDays Days" >> $LogFile } Write-Output "------------------------------------------------" >> $LogFile } $found = $false If ($CountMatches -ge $BlockLimit) { $LogCheck = Get-ChildItem $IP_Block_Log_Folder\*.log | Select-Object -ExpandProperty Name If ((-not(Test-Path $IP_Block_Log_Folder\*.log)) -or (-not(Test-Path "$Logfile1"))) { New-NetFirewallRule -DisplayName "Axigen IP-Block_$($Text1)_$($BlockDays)d" -Direction Inbound –LocalPort Any -Action Block -RemoteAddress $Text1/32 > $Logfile1 write-output "Adding firewall rule to block $Text1" } else { write-output "Firewall Rule blocking $Text1 already exists" } } } } #Below checks the IP_Block log files and how old they are, deletes them from the firewall if the IP is older than the number of days in the filename $LogCheck1 = Get-ChildItem $IP_Block_Log_Folder\*.log | Select-Object -ExpandProperty Name foreach ($Logfile in $LogCheck1) { $Logfile2 = $IP_Block_Log_Folder + "\" + $Logfile $lastWrite = (get-item "$Logfile2").LastWriteTime #Below splits the log files into an array and gets the 5th array, and removes any non-number characters #Might need to change the number 5 below, if you change the LogFile name and firewall rule $GetTimespan = "$Logfile".split('_.') [Int]$BlockDays1 = ($GetTimespan[5] -Replace '\D+') #write-output $BlockDays1 $timespan = new-timespan -days $BlockDays1 if (((get-date) - $lastWrite) -ge $timespan) { write-output "$Logfile is older than $timespan" Remove-NetFirewallRule -DisplayName (Get-item $Logfile2).basename Remove-Item $Logfile2 } else { # not older than $timespan } }