web-dev-qa-db-ja.com

ログイン試行の失敗回数Xに基づいてIPアドレスを禁止しますか?

Windowsサーバーへのログイン試行がX回失敗した後、IPアドレスを禁止することはできますか?方法を知っている特定のアカウントではなく、マシン全体に対するものです。

ユーザー名を推測しようとするブルートフォース攻撃にかなり強く打たれるので、サーバーに負荷をかけるのに役立ちます。

47
HeavyWave

これは、powershellとタスクマネージャーで実行できます。それはおそらく完璧なソリューションではありませんが、それは非常にうまく機能し、2か月で約100のブロックされたIPアドレスを持っています。 EventLogの指定されたイベントから選択するスクリプトを作成しました(「監査失敗」)。任意のIPアドレスからの失敗したログインが多い場合、「手動で作成された」ファイアウォールルールに追加され、指定されたIPアドレスへのトラフィックをブロックする「BlockAttackers」という名前が付けられます。

PS1スクリプト:

$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

スケジューラでタスクを作成し、トリガーをイベント4625に設定します(ターミナルサービスを含むWindowsログイン)。ただし、トリガーを実行するように設定できます。サーバーへの不要なロードを回避するために、1時間に2回。

Scheduler trigger

トリガー後、PowerShellスクリプトを実行します。また、このスクリプトを実行するには、より高い特権を設定する必要があります。そうしないと、セキュリティ例外で失敗します。

runing powershell script

このスクリプトを他のセキュリティイベントにバインドすることもできます。

28
remunda

私はこの質問が古いことを知っていますが、実際には、2週間前にまったく同じことをやろうとしたときに私が偶然見つけた最初のフォーラム投稿でした。 24時間前にイベントログを解析して、不正なログインイベントログエントリのみを検出し、不正なログインが10を超えるものを取得し、次のコマンドを使用してそれらをipsecフィルターリストに配置する作業スクリプトを思い付きました。 netshコマンド。次に、この行powershell .\*scriptname.ps1*を使用してバッチファイルを記述し、24時間ごとにバッチファイルを実行するスケジュールされたタスクを作成しました(何らかの理由で直接実行されません)。

$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}

このスクリプトはおそらく非効率的ですが、私がこれに取り組み始めたとき、私はPowerShellでの経験がまったくなかったので、スクリプトを最適化する私の能力は多くを望んでいません。しかし、この事実にもかかわらず、私はそれを使用できるすべての人と共有したいと思いました。

最初のアイデアを与えてくれたRemundaに感謝します。そのポスターは、Powershellを使用してイベントログを検索するというアイデアに私を導いたポスターです。

7
Keegan

このスクリプトはremundaの回答に基づいて構築されており、少し先に進んでいきます https://serverfault.com/a/397637/155102 「BlockAttackers」ルールのアカウントで、IPがまだ入力されていません(「 * "を文字列として)。また、IPがルールに追加されたときに通知するコメントをログファイルに書き込みます。

良いヒントは、IPアドレスをブロックする「BlockAttackers」ルールを作成することですが、最初はそれを無効にします。次に、このスクリプトを手動で1回実行して、ブロックする必要がある実際のIPアドレスを「RemoteAddresses」フィールドに入力できるようにします。これらのIPアドレスを調べて、重要なものが何も追加されていないことを確認し、ファイアウォールルールを有効にします。説明のとおり、このルールをファイアウォールに追加します。

このスクリプトのgit

#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'}
}
4
Michael Khalili

この答えは信用できませんが、 https://serverfault.com/users/7200/evan-anderson が彼のプロジェクトについて言及しています http://opensource.wellbury.com/projects/windows_sshd_block/newest-release /

3
becomingwisest

一般に、ファイアウォールルールを他の誰かに制御させることはお勧めできません。それは基本的にあなたがここで求めていることです。

2
Thorsten

これは古いスレッドです。 2014年から2015年にkevinmickeから提供されたスクリプトを使用していました。その後、機能しなくなりました。したがって、セキュリティログにIPアドレスを残さないWindowsネットワークセキュリティ認証を採用するには、少し編集する必要がありました。また、通常のFTPを実行していないため、ログフォルダーがなかったためにエラーが発生していたため、その部分を削除しました。主な変更点は、RDPイベントのソースです。

    $current_date_utc = (Get-Date).ToUniversalTime()

    # Set number of failed login attempts after which an IP address will be blocked
    $int_block_limit = 10

    # Time window during which to check the Security log, which is currently set to check only the last 24 hours
    $dat_time_window = [DateTime]::Now.AddDays(-1)

    $arr_new_bad_ips_all = (get-winevent -filterhashtable @{ logname='Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational'; starttime=$dat_time_window; id=140 }).message |
        % { if ($_ -match "of (.+) failed") { $Matches[1] }} |
        Group-Object |
        Where {$_.Count -ge $int_block_limit} |
        Select -property Name

    # Sort the array, selecting only unique IPs (in case one IP shows up in both the Security and FTP logs)
    $arr_new_bad_ips_all = $arr_new_bad_ips_all | Foreach-Object { [string]$_.Name } | Select-Object -unique

    # Get firewall object
    $firewall = New-Object -comobject hnetcfg.fwpolicy2

    # Get all firewall rules matching "BlockAttackers*"
    $arr_firewall_rules = $firewall.Rules | Where {$_.Name -like 'BlockAttackers*'}

    # If no "BlockAttackers*" firewall rule exists yet, create one and set it to a variable
    if ($arr_firewall_rules -eq $null) {
        $str_new_rule_name = "BlockAttackers (Created " + $current_date_utc.ToString("yyyy-MM-dd HH:mm:ss") + " UTC)"
        netsh advfirewall firewall add rule dir=in action=block name=$str_new_rule_name description="Rule automatically created." enable=yes remoteip="0.0.0.0" | Out-Null
        $arr_firewall_rules = $firewall.Rules | Where {$_.Name -like 'BlockAttackers*'}
    }

    # Split the existing IPs from current "BlockAttackers*" firewall rule(s) into an array so we can easily search them
    $arr_existing_bad_ips = @()
    foreach ($rule in $arr_firewall_rules) {
        $arr_existing_bad_ips += $rule.RemoteAddresses -split(',')
    }

    # Clean subnet masks off of IPs that are currently blocked by the firewall rule(s)
    $arr_existing_bad_ips_without_masks = $arr_existing_bad_ips | ForEach-Object {$_ -replace "/.*", ""}

    # Select IP addresses to add to the firewall, but only ones that...
    $arr_new_bad_ips_for_firewall = $arr_new_bad_ips_all | Where {
        # contain an IP address (i.e. aren't blank or a dash, which the Security log has for systems that failed FTP logins)
        $_.Length -gt 6 -and
        # aren't already in the firewall rule(s)
        !($arr_existing_bad_ips_without_masks -contains $_) -and
        # aren't the local loopback
        !($_.StartsWith('127.0.0.1')) -and
        # aren't part of the local subnet
        !($_.StartsWith('192.168.')) -and
        !($_.StartsWith('0.0.'))
    }

    # If there are IPs to block, do the following...
    if ($arr_new_bad_ips_for_firewall -ne $null) {
        # Write date and time to script-specific log file
        [DateTime]::Now | Out-File -Append -Encoding utf8 C:\Security\blockattackers.txt
        # Write newly-blocked IP addresses to log file
        $arr_new_bad_ips_for_firewall | Out-File -Append -Encoding utf8 C:\Security\blockattackers.txt

        # Boolean to make sure the new IPs are only added on one rule
        $bln_added_to_rule = 0

        # Array to hold bad IPs from each rule one at a time, so we can count to make sure adding the new ones won't exceed 1000 IPs
        $arr_existing_bad_ips_current_rule = @()

        # For each "BlockAttackers*" rule in the firewall, do the following...
        foreach ($rule in $arr_firewall_rules) {
            if ($bln_added_to_rule -ne 1) {
                # Split the existing IPs from the current rule into an array so we can easily count them
                $arr_existing_bad_ips_current_rule = $rule.RemoteAddresses -split(',')

                # If the number of IPs to add is less than 1000 minus the current number of IPs in the rule, add them to this rule
                if ($arr_new_bad_ips_for_firewall.Count -le (1000 - $arr_existing_bad_ips_current_rule.Count)) {
                    # Add new IPs to firewall rule
                    $arr_new_bad_ips_for_firewall | %{$rule.RemoteAddresses += ',' + $_}

                    # Write which rule the IPs were added to to log file
                    echo "New IP addresses above added to Windows Firewall rule:" $rule.Name | Out-File -Append -Encoding utf8 C:\Security\blockattackers.txt

                    # Set boolean so any other rules are skipped when adding IPs
                    $bln_added_to_rule = 1
                }
            }
        }

        # If there wasn't room in any other "BlockAttackers*" firewall rule, create a new one and add the IPs to it
        if ($bln_added_to_rule -ne 1) {
            $str_new_rule_name = "BlockAttackers (Created " + $current_date_utc.ToString("yyyy-MM-dd HH:mm:ss") + " UTC)"
            netsh advfirewall firewall add rule dir=in action=block name=$str_new_rule_name description="Rule automatically created." enable=yes remoteip="0.0.0.0" | Out-Null
            $new_rule = $firewall.rules | Where {$_.Name -eq $str_new_rule_name}

            # Add new IPs to firewall rule
            $arr_new_bad_ips_for_firewall | %{$new_rule.RemoteAddresses += ',' + $_}

            # Write which rule the IPs were added to to log file
            echo "New IP addresses above added to newly created Windows Firewall rule:" $new_rule.Name | Out-File -Append -Encoding utf8 C:\Security\blockattackers.txt
        }
    }

上記のスクリプトはWindows 2012で動作します。Windows2008でネットワークアクセスレベル認証を使用してリモートデスクトップを引き続き使用している場合は、次のトリックを実行する必要があります。 Windows 2008のセキュリティログにはIPアドレスがなく、Microsoft-Windows-RemoteDesktopServices-RdpCoreTSログにもIPアドレスがないようです。そのため、実際には2つのログを使用する必要がありました。セキュリティログのイベントをファイアウォールログのポート3389へのアクセス試行の成功と一致させます。これは当て推量ですが、パスワード攻撃を検出しているようです。違反するIPを収集する部分は次のとおりです。

    $current_date_utc = (Get-Date).ToUniversalTime()

    # Set number of failed login attempts after which an IP address will be blocked
    $int_block_limit = 10

    $dat_time_window = [DateTime]::Now.AddDays(-1)

    $logfn = (netsh advfirewall show allprofiles | Select-String Filename | select-object -unique | % { $_ -replace "%systemroot%",$env:systemroot }).substring(10).trimstart().trimend()

    $badevts = Get-EventLog -LogName 'Security' -InstanceId 4625 -After $dat_time_window | foreach-object { [datetime]$_.TimeWritten } | sort-object

    $fwlog = Select-String -Path $logfn -Pattern "ALLOW TCP" |
        % {
            if ($_ -match "(201.-..-..) (.+) ALLOW TCP (.+) (.+) (.+) 3389") 
            {
                new-object psobject -property @{ 
                  dt = $Matches[1] + ' ' + $Matches[2]
                  ip = $Matches[3]
                }
            }
        }

    $ipa = @()
    $j = 0

    for ($i=0; $i -lt $fwlog.Count; $i++)
    {
        $conn = ([datetime]$fwlog[$i].dt).ticks
        while (($j -lt $badevts.Count) -and (($badevts[$j]).ticks -lt $conn)) { $j++ }
        if ($j -ge $badevts.Count) { break }
        if ((($badevts[$j]).ticks - $conn) -le 30000000) { $ipa += ,($fwlog[$i].ip) }
    }

    $arr_new_bad_ips_all = $ipa |
        Group-Object |
        Where {$_.Count -ge $int_block_limit} |
        Select -property Name

注:ファイアウォールログを有効にすることを忘れないでください。注2:私はpowershellのエキスパートではないので、一部の教祖が私のコードを修正/改善できればいいと思います。

2
Calm Down

私は ts_block freebyを使用しています。

基本的には、「無効なターミナルサービスログオンへの応答としてWindowsによってログに記録されたイベントを受信するWMIイベントシンクとして機能するVBScriptプログラム」です。

完璧に機能しているようで、スクリプトを変更する必要がある場合、スクリプトは簡単です。試行をログに記録させ、許可された試行の回数に基づいて禁止したり、アクセスを許可したくないログイン名をハードコーディングしたりできます。

私は誤って同じ名前を2回追加したことに気づき、サービスは1500msごとに再起動する無限ループに入りますが、vbsに問題がなければ、修正/変更が非常に簡単です。

私の現在の設定は1回の再試行であり、2日間禁止されています。「admin」「Admin」「Administrator」「guest」などのログインは自動的に禁止されます。 IPに変更するのは簡単ですか?

中に入って、どの生き物が一晩禁止されているかを見るのは中毒性があります...

1
chipbug

サーバー/ドメインへのログオンまたはサーバーで実行されているWebサイトへのログオンを意味しますか?サーバー/ドメインにログオンするつもりなら、答えはノーです。 IPアドレスはセキュリティエンティティではないため、Windowsには、失敗したログオン試行に基づいてIPアドレスをブロックする概念がありません。これを行うことができるサードパーティのツールがあるかもしれませんが、私はそれを調べたことがないので、私は知りません。

0
joeqwerty

攻撃されているWebサーバーがある場合は、 動的IP制限の拡張 をインストールできます。これがサーバーへの標準認証用である場合、 ドメインとサーバーの分離 を実装できるはずです。これにより、攻撃の範囲がドメインに参加しているコンピューターに限定され、サーバーへのアクセスが必要なシステム。 Windowsでのブルートフォース攻撃の防止は、アカウントロックアウトポリシーを10分のような設定に設定し、不正なパスワードポリシーを3回の試行に設定することです。これは、攻撃されたアカウントが3回の試行後に10分間ロックすることを意味します。 Windowsでは、デフォルトでIP接続をロックできません。 (余談ですが、システムに影響を与えるために1秒間に何回ログオンが試行されるかについても知りたいです)

0
Jim B

http://nerderies.blogspot.co.at/2012/12/automatically-banning-ips-with-windows.html

必要なものがすぐに使えるソリューション(インストール&完了)である場合は、ここで無料のツールを見つけることができます。おそらくこれを読み続ける必要があります。

現在のバージョン:1.2(.NET Framework 4.0クライアントプロファイル)-> EvlWatcherの現在のバージョンをダウンロード(個人および商用での使用は無料)

1.2の新機能(ドキュメントの詳細):

  • 管理コンソール
  • WCFサービスパターン
  • ブラックリスト
  • 3ストライク後のブラックリストへの自動移動(デフォルト)

古いサーバー(.NET Framework 2.0)

-> EvlWatcherの縮小版をダウンロードしてください(個人および商用の場合は無料)

0
Mastro

remunda の優れたスクリプトを開始点として使用して、欠落していた1つの重要なことを追加しました:失敗したFTPログインからのIPアドレスのブロック。 Windows Serverは、誰かがFTP経由でログインに失敗した場合、IPアドレスをセキュリティログに記録せず、代わりに「ソースネットワークアドレス」をダッシュ​​に設定します。 FTPはブルートフォース攻撃の非常に一般的な攻撃ベクトルであるため、今日のFTPログをスキャンして複数のログインエラーを検出し、それらのIPアドレスもブロックする機能を彼のスクリプトに追加しました。

2014/02/07の更新:これを調整してすべての古いFTPログを処理したところ、膨大な試行回数があったことに気付きました( 50,000以上)、それが作成した配列は巨大になり、処理が非常に遅くなります。それ以来、FTPログを処理する際の効率を高めるために書き直しました。

1つのWindowsファイアウォールルールに含めることができるIPの数には、1000という任意のハード制限があることもわかりました。その制限のため、最新のルールがいっぱいになったときに自動的に新しいルールを作成する必要がありました。これにより、最初のファイアウォールルールが作成され(独自のファイアウォールルールを作成しない場合)、イベント4625が発生したときに実行するようにスケジューラに追加するだけの設定になります。

以下は、Windows Server 2008 R2とWindows 7の両方でテストされたコードです。

# This Windows Powershell script will automatically block IP addresses that attempt to login to the system
# and fail the number of times set below with the $int_block_limit variable or more. Is scans both the Security
# log, which covers Remote Desktop and other attempts, as well as the current day's FTP log. If the $int_block_limit
# limit is hit on either of those logs (separately, not combined), then the IP address will be added to the
# firewall rule.
#
# The script will automatically create a firewall rule named "BlockAttackers (Created yyyy-MM-dd HH:mm:ss UTC)" using
# the current time if one with a name that includes "BlockAttackers" doesn't already exist. Because there's a hard
# limit of 1000 entries (IP addresses) you can block per rule, it will also create similarly-named rules once that
# limit is reached for the latest one.
#
# I recommend setting the script to run as a scheduled task triggered by event 4625 login audit failures from the
# Security log, or alternatively you could set it to run after some amount of time (i.e. every 10 minutes).
#
# Authors:
# Majority of script written by serverfault.com user kevinmicke
# Windows Security Log portion written by serverfault.com user remunda, which provided the starting point for kevinmicke
#
# Details: https://serverfault.com/questions/233222/ban-ip-address-based-on-x-number-of-unsuccessful-login-attempts


# Set number of failed login attempts after which an IP address will be blocked
$int_block_limit = 10

# Time window during which to check the Security log, which is currently set to check only the last 24 hours
$dat_time_window = [DateTime]::Now.AddDays(-1)

# Select from the Security log all IP addresses that have more than $int_block_limit audit failures (event 4625) within $dat_time_window
$arr_new_bad_ips_security_log = @()
$arr_new_bad_ips_security_log = Get-EventLog -LogName 'Security' -InstanceId 4625 -After $dat_time_window |
    Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]}} |
    Group-Object -property IpAddress |
    Where {$_.Count -ge $int_block_limit} |
    Select -property Name

# Get current time UTC to figure out filename for current FTP log
$current_date_utc = (Get-Date).ToUniversalTime()

# Set path to today's FTP log file
$str_log_file_name = "C:\inetpub\logs\LogFiles\FTPSVC2\u_ex" + $current_date_utc.ToString("yyMMdd") + ".log"

# Search today's FTP log file for "530 1326" to find lines that contain IPs of systems that failed to log in,
# get just the IP from each line, group the IPs by IP to count the attempts from each one, and select only the
# IPs that have $int_block_limit or more bad logins today
$arr_new_bad_ips_ftp = @()
$arr_new_bad_ips_ftp = Select-String $str_log_file_name -pattern "530 1326" |
    ForEach-Object {$_.Line.Substring(20,15) -replace " .*", ""} |
    Group |
    Where {$_.Count -ge $int_block_limit} |
    Select -property Name

# Concatenate the two arrays of IPs (one from Security log, one from FTP log)
$arr_new_bad_ips_all = @()
# $arr_new_bad_ips_all = @($arr_new_bad_ips_security_log) + @($arr_new_bad_ips_ftp_over_limit)
$arr_new_bad_ips_all = @($arr_new_bad_ips_security_log) + @($arr_new_bad_ips_ftp)

# Sort the array, selecting only unique IPs (in case one IP shows up in both the Security and FTP logs)
$arr_new_bad_ips_all_sorted = @()
$arr_new_bad_ips_all_sorted = $arr_new_bad_ips_all |
    Foreach-Object { [string]$_.Name } |
    Select-Object -unique

# Get firewall object
$firewall = New-Object -comobject hnetcfg.fwpolicy2

# Get all firewall rules matching "BlockAttackers*"
$arr_firewall_rules = $firewall.Rules | Where {$_.Name -like 'BlockAttackers*'}

# If no "BlockAttackers*" firewall rule exists yet, create one and set it to a variable
if ($arr_firewall_rules -eq $null) {
    $str_new_rule_name = "BlockAttackers (Created " + $current_date_utc.ToString("yyyy-MM-dd HH:mm:ss") + " UTC)"
    netsh advfirewall firewall add rule dir=in action=block name=$str_new_rule_name description="Rule automatically created by BlockAttackers Powershell script written by Kevin Micke." enable=yes remoteip="0.0.0.0" | Out-Null
    $arr_firewall_rules = $firewall.Rules | Where {$_.Name -like 'BlockAttackers*'}
}

# Split the existing IPs from current "BlockAttackers*" firewall rule(s) into an array so we can easily search them
$arr_existing_bad_ips = @()
foreach ($rule in $arr_firewall_rules) {
    $arr_existing_bad_ips += $rule.RemoteAddresses -split(',')
}

# Clean subnet masks off of IPs that are currently blocked by the firewall rule(s)
$arr_existing_bad_ips_without_masks = @()
$arr_existing_bad_ips_without_masks = $arr_existing_bad_ips | ForEach-Object {$_ -replace "/.*", ""}

# Select IP addresses to add to the firewall, but only ones that...
$arr_new_bad_ips_for_firewall = @()
$arr_new_bad_ips_for_firewall = $arr_new_bad_ips_all_sorted | Where {
    # contain an IP address (i.e. aren't blank or a dash, which the Security log has for systems that failed FTP logins)
    $_.Length -gt 6 -and
    # aren't already in the firewall rule(s)
    !($arr_existing_bad_ips_without_masks -contains $_) -and
    # aren't the local loopback
    !($_.StartsWith('127.0.0.1')) -and
    # aren't part of the local subnet
    !($_.StartsWith('192.168.')) -and
    !($_.StartsWith('10.0.'))
}

# If there are IPs to block, do the following...
if ($arr_new_bad_ips_for_firewall -ne $null) {
    # Write date and time to script-specific log file
    [DateTime]::Now | Out-File -Append -Encoding utf8 C:\blockattackers.txt
    # Write newly-blocked IP addresses to log file
    $arr_new_bad_ips_for_firewall | Out-File -Append -Encoding utf8 C:\blockattackers.txt

    # Boolean to make sure the new IPs are only added on one rule
    $bln_added_to_rule = 0

    # Array to hold bad IPs from each rule one at a time, so we can count to make sure adding the new ones won't exceed 1000 IPs
    $arr_existing_bad_ips_current_rule = @()

    # For each "BlockAttackers*" rule in the firewall, do the following...
    foreach ($rule in $arr_firewall_rules) {
        if ($bln_added_to_rule -ne 1) {
            # Split the existing IPs from the current rule into an array so we can easily count them
            $arr_existing_bad_ips_current_rule = $rule.RemoteAddresses -split(',')

            # If the number of IPs to add is less than 1000 minus the current number of IPs in the rule, add them to this rule
            if ($arr_new_bad_ips_for_firewall.Count -le (1000 - $arr_existing_bad_ips_current_rule.Count)) {
                # Add new IPs to firewall rule
                $arr_new_bad_ips_for_firewall | %{$rule.RemoteAddresses += ',' + $_}

                # Write which rule the IPs were added to to log file
                echo "New IP addresses above added to Windows Firewall rule:" $rule.Name | Out-File -Append -Encoding utf8 C:\blockattackers.txt

                # Set boolean so any other rules are skipped when adding IPs
                $bln_added_to_rule = 1
            }
        }
    }

    # If there wasn't room in any other "BlockAttackers*" firewall rule, create a new one and add the IPs to it
    if ($bln_added_to_rule -ne 1) {
        $str_new_rule_name = "BlockAttackers (Created " + $current_date_utc.ToString("yyyy-MM-dd HH:mm:ss") + " UTC)"
        netsh advfirewall firewall add rule dir=in action=block name=$str_new_rule_name description="Rule automatically created by BlockAttackers Powershell script written by Kevin Micke." enable=yes remoteip="0.0.0.0" | Out-Null
        $new_rule = $firewall.rules | Where {$_.Name -eq $str_new_rule_name}

        # Add new IPs to firewall rule
        $arr_new_bad_ips_for_firewall | %{$new_rule.RemoteAddresses += ',' + $_}

        # Write which rule the IPs were added to to log file
        echo "New IP addresses above added to newly created Windows Firewall rule:" $new_rule.Name | Out-File -Append -Encoding utf8 C:\blockattackers.txt
    }
}
0
kevinmicke