it-swarm-pt.tech

Proibir o endereço IP com base no número X de tentativas malsucedidas de login?

É possível banir um endereço IP após um número X de tentativas malsucedidas de logon no Windows Server? Não para uma conta específica, que eu sei fazer, mas para toda a máquina.

Somos atingidos por ataques de força bruta tentando adivinhar nomes de usuários, de modo que isso realmente ajudaria a obter alguma carga do servidor.

47
HeavyWave

Você pode fazer isso com o PowerShell e o Gerenciador de tarefas. Provavelmente não é uma solução perfeita, mas funciona muito bem e tenho cerca de 100 endereços IP bloqueados em dois meses. Eu escrevi um script que seleciona eventos especificados do EventLog ("falha de auditoria"). Se houver muitos logins com falha de qualquer endereço IP, ele será adicionado à regra de firewall (criada manualmente) denominada "BlockAttackers", que bloqueia qualquer tráfego para os endereços IP especificados.

Script 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

Crie uma tarefa no planejador e defina o gatilho para o evento 4625 (logon no Windows, incluindo serviços de terminal). Mas você pode definir o gatilho para ser executado, por exemplo. duas vezes por hora para evitar o carregamento desnecessário do servidor.

Scheduler trigger

e após o gatilho, execute o script powershell. Você também deve definir privilégios mais altos para executar este script, caso contrário, ele falhará com exceção de segurança.

runing powershell script

Você também pode vincular esse script a outros eventos de segurança.

28
remunda

Eu sei que essa pergunta é antiga, mas foi realmente o primeiro post do fórum que eu tropecei quando comecei a tentar fazer exatamente a mesma coisa algumas semanas atrás. Eu consegui criar um script de trabalho que analise os logs de eventos 24 horas atrás, apenas para entradas incorretas de log de eventos, pegue as que têm mais de 10 logins incorretos e coloque-as em uma lista de filtros ipsec usando o comando netsh. Então eu escrevi um arquivo em lotes com esta linha powershell .\*scriptname.ps1* e criou uma tarefa agendada para executar o arquivo em lotes a cada 24 horas (por algum motivo, ele não seria executado diretamente).

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

Sei que esse script provavelmente é ineficiente, mas quando comecei a trabalhar nele não tinha absolutamente nenhuma experiência em PowerShell, portanto, minha capacidade de otimizar scripts deixa muito a desejar. No entanto, apesar desse fato, pensei em compartilhar isso com qualquer pessoa que pudesse usá-lo.

Agradeço a Remunda por me dar a idéia inicial, foi o pôster que me levou à ideia de usar o PowerShell para pesquisar os logs de eventos.

7
Keegan

Este script baseia-se na resposta do remunda e vai um pouco mais longe https://serverfault.com/a/397637/155102 Ele é responsável pela regra "BlockAttackers" que ainda não possui nenhum IP inserido (o que retorna um " * "como uma string). Ele também grava um comentário em um arquivo de log para informar quando o IP foi adicionado à regra.

Uma boa dica é criar a regra "BlockAttackers" que bloqueia os endereços IP, mas torne-os desativados primeiro. Em seguida, execute esse script uma vez manualmente para poder preencher o campo "RemoteAddresses" com endereços IP reais que devem ser bloqueados. Dê uma olhada nesses endereços IP para garantir que nada de crítico tenha sido adicionado e ative a regra do firewall. Adicione esta regra ao seu firewall, conforme descrito na remunda.

O git para este script

#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
3
becomingwisest

Geralmente, não é uma boa ideia deixar outra pessoa controlar suas regras de firewall. É basicamente o que você está pedindo aqui.

2
Thorsten

Este é um tópico antigo. Eu estava usando o script fornecido por kevinmicke em 2014-2015. Então parou de funcionar. Portanto, tive que editá-lo um pouco para adotar a autenticação do Windows Network Security que não deixa endereços IP no log de segurança. Além disso, como não tenho FTP normal em execução, removi essa parte, pois estava causando erros porque não havia pasta de log. A principal mudança está na origem dos eventos 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
        }
    }

O script acima funcionará no Windows 2012. Se você ainda estiver usando a Área de Trabalho Remota com autenticação no nível de acesso à rede no Windows 2008, poderá executar o seguinte truque. O Windows 2008 também não possui endereços IP no log de segurança e também não os possui no log Microsoft-Windows-RemoteDesktopServices-RdpCoreTS. Então, eu tive que realmente usar 2 logs - corresponder eventos do log de segurança às tentativas de acesso bem-sucedidas à porta 3389 no log do firewall. Este é um trabalho de adivinhação, mas parece estar detectando ataques de senha. Aqui está a parte que coleta IPs violadores:

    $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

NOTA: Não esqueça de ativar os logs do firewall. NOTA 2: Eu não sou um especialista em PowerShell, então seria legal se alguns gurus pudessem corrigir/melhorar meu código.

2
Calm Down

Estou usando ts_block freeby.

Basicamente, é um "programa VBScript que atua como um coletor de eventos WMI para receber eventos registrados pelo Windows em resposta a logons inválidos dos Serviços de Terminal".

Parece funcionar perfeitamente, e o script é direto se você precisar modificá-lo. Você pode permitir que ele registre tentativas e depois banir com base no número de tentativas permitidas, e/ou pode codificar os nomes de login aos quais não deseja dar acesso.

Fui pego adicionando acidentalmente o mesmo nome duas vezes e o serviço entra em um loop sem fim reiniciando a cada 1500ms, mas muito fácil de corrigir/mod se você estiver de acordo com o vbs.

Minhas configurações atuais são apenas uma nova tentativa e você é banido por 2 dias, com logins como 'admin' 'Admin' 'Administrator' 'guest' 'etc automaticamente banidos. Deve ser simples mudar para ip?

Meio viciante entrar e ver quais criaturas foram banidas da noite para o dia ...

1
chipbug

Você quer dizer logon no servidor/domínio ou logon em um site em execução no servidor? Se você quer fazer logon no servidor/domínio, a resposta é não. O Windows não tem o conceito de bloquear endereços IP com base em tentativas falhas de logon, pois os endereços IP não são entidades de segurança. Pode haver ferramentas de terceiros que podem fazer isso, mas não conheço nenhuma, pois nunca a examinei.

0
joeqwerty

Se houver um servidor da Web que está sendo atacado, você pode instalar o extensão dinâmica de restrições de IP . Se for para autenticação padrão no servidor, você poderá implementar isolamento do domínio e do servidor , o que limitaria o escopo dos ataques aos computadores ingressados ​​no domínio e poderia ser definido para permitir apenas tentativas do sistemas que você precisa ter acesso ao servidor. No Windows, a prevenção de ataques de força bruta é definir a política de bloqueio de conta para uma configuração de 10 minutos e uma política de senha incorreta para 3 tentativas - isso significa que a conta sendo atacada será bloqueada por 10 minutos após 3 tentativas. As conexões IP não são bloqueáveis ​​por padrão no Windows. (Além disso, também estou curioso para saber quantas tentativas de logon são necessárias por segundo para impactar o sistema)

0
Jim B

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

Se o que você deseja é uma solução pronta para uso (Instalação e execução), você pode encontrar uma ferramenta gratuita aqui e provavelmente deve continuar lendo isso:

Versão atual: 1.2 (Perfil do Cliente .NET Framework 4.0) -> Faça o download da versão atual do EvlWatcher (gratuita para uso pessoal e comercial)

Novo no 1.2 (mais informações na documentação):

  • Console de Gerenciamento
  • Padrão de Serviço WCF
  • Lista negra
  • Movendo-se automaticamente para a lista negra após três advertências (por padrão)

Para servidores mais antigos (.NET Framework 2.0)

-> Baixe a versão reduzida do EvlWatcher (grátis para uso pessoal e comercial)

0
Mastro

Usando o ótimo script de remunda como ponto de partida, adicionei o que estava faltando: bloqueando endereços IP de logins FTP com falha O Windows Server não registra o endereço IP no log de segurança quando alguém falha no logon via FTP, mas define o "Endereço de rede de origem" como um traço. O FTP é um vetor de ataque muito comum para ataques de força bruta, então eu adicionei ao seu script a capacidade de verificar os logs de FTP do dia atual em busca de várias falhas de login e bloquear esses endereços IP também.

Atualização 2014/02/07: Quando fiz alguns ajustes para processar todos os meus logs antigos de FTP, percebi que eles tinham um número imenso de tentativas ( Mais de 50.000), as matrizes criadas seriam enormes e tornariam o processamento incrivelmente lento. Desde então, eu o reescrevi para torná-lo muito mais eficiente ao processar logs de FTP.

Também descobri que há um limite rígido arbitrário de 1000 para quantos IPs podem estar em uma regra do Firewall do Windows. Por causa desse limite, eu precisava que ela criasse automaticamente uma nova regra quando a mais recente fosse preenchida. Agora ele faz isso e também cria a regra inicial do firewall (se você não criar sua própria), de modo que a única configuração a ser feita é adicioná-la ao Agendador para execução quando houver um evento 4625.

Aqui está o código, que foi testado no Windows Server 2008 R2 e no 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