Вопрос: Запретить IP-адрес на основе X неудачных попыток входа в систему?


Можно ли запретить IP-адрес после X числа неудачных попыток входа в Windows Server? Не для конкретной учетной записи, которую я знаю, как это сделать, но для всей машины.

Мы сильно ударяем атаками грубой силы, пытаясь угадать имена пользователей, поэтому это действительно поможет получить некоторую нагрузку с сервера.


45
2018-02-09 11:21


Источник


* nix имеет fial2ban ... не уверен, есть ли эквивалент Windows / порт. fail2ban.org/wiki/index.php/Main_Page - Chris Nava
От Эвана Андерсона: serverfault.com/questions/43360/... ... похоже, является хорошим эквивалентом функциональности fail2ban, но поскольку ваш вопрос недостаточно конкретный, я не знаю, хотите ли вы запретить IP-адреса, пытающиеся войти на хостинг-сайт, ваш сервер (через SSH) или ваш домен. Уточнение пройдет долгий путь. Кроме того, вы можете ограничить лимит на своем брандмауэре, но это зависит от реализации. - kce
Вы можете взглянуть на serverfault.com/questions/216995/... для предыдущего обсуждения о том, насколько полезно автоматическое запрещение на основе IP. - pehrs
Если вы говорите о Terminal Services / Remote Desktop, посмотрите здесь: serverfault.com/a/335976/7200 - Evan Anderson
Я сделал службу Windows на github, чтобы сделать именно это: github.com/jjxtra/Windows-IP-Ban-Service - jjxtra


Ответы:


Вы можете сделать это с помощью powershell и диспетчера задач. Это, вероятно, не идеальное решение, но оно работает довольно хорошо, и через два месяца у меня около 100 заблокированных IP-адресов. Я написал сценарий, который выбирает из событий EventLog определенные события («аудит аудита»). Если с любого IP-адреса много неудачных логинов, оно добавляется в правило брандмауэра (созданное вручную) с именем «BlockAttackers», которое блокирует любой трафик на указанные IP-адреса.

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, включая службы терминалов). Но вы можете настроить запуск запуска, например. дважды в час, чтобы избежать ненужной загрузки сервера.

Scheduler trigger

и после запуска запуска сценария powershell. Вы также должны установить более высокие привилегии для запуска этого скрипта, иначе он будет сбой безопасности.

runing powershell script

Вы также можете привязать этот скрипт к другим событиям безопасности.


27
2018-06-11 15:27



Отличный скрипт @remunda - спасибо! Я получал много 4625-х от FTP, а в журнале безопасности нет IP-адресов, поэтому я расширил ваш скрипт, чтобы он также проверял журнал FTP текущего дня. Пожалуйста, см. Мой ответ ниже для получения дополнительной информации: serverfault.com/a/571903/107701 - kevinmicke
Есть много ошибок и краев с журналами событий, регистрацией IP-адресов и т. Д., Которые я обработал в IPBan - бесплатно и с открытым исходным кодом на github.com/jjxtra/Windows-IP-Ban-Service - jjxtra


Я знаю, что этот вопрос старый, но на самом деле это был первый форум, на который я наткнулся, когда я начал пытаться сделать то же самое пару недель назад. Мне удалось создать рабочий скрипт, который будет обрабатывать журналы событий 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, поэтому моя способность оптимизировать скрипты оставляет желать лучшего. Однако, несмотря на этот факт, я думал, что поделился бы этим с любым, кто мог бы его использовать.

Я благодарю Ремунду за то, что дал мне первоначальную идею, что плакат - это тот, который превратил меня в идею использования powershell для поиска журналов событий.


7
2017-12-04 22:09





Этот сценарий основывается на ответе remunda и идет немного дальше https://serverfault.com/a/397637/155102 В нем учтено, что правило «BlockAttackers» не имеет ни одного введенного IP-адреса (который возвращает «*» в виде строки). Он также пишет комментарий к файлу журнала, чтобы сообщить вам, когда IP был добавлен в правило.

Хорошим советом является создание правила «BlockAttackers», которое блокирует IP-адреса, но сначала отключите его. Затем запустите этот скрипт один раз вручную, чтобы он мог заполнить поле «RemoteAddresses» фактическими IP-адресами, которые должны быть заблокированы. Взгляните на эти IP-адреса, чтобы убедиться, что ничего не было добавлено, а затем включите правило брандмауэра. Добавьте это правило в свой брандмауэр в качестве описанного remunda.

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
2018-01-20 20:59





Я не могу взять на себя ответственность за этот ответ, но https://serverfault.com/users/7200/evan-anderson упомянул о своем проекте http://opensource.wellbury.com/projects/windows_sshd_block/newest-release/


3
2018-02-18 18:14





Как правило, не рекомендуется, чтобы кто-то другой контролировал ваши правила брандмауэра. Это в основном то, о чем вы просите здесь.


2
2018-02-10 22:09



+1, это отличный способ настроить атаку на отказ в обслуживании. И если вы используете ограничение скорости, большинство автоматизированных инструментов переборки запирают свои попытки входа достаточно далеко друг от друга, чтобы не попасться. - kce
Автоматическое запрещение IP-адресов после определенного количества неудачных логинов очень Общая практика. Я вижу, что хосты запрещаются на почасовой основе, пытаясь угадать пароли FTP. Единственный способ, которым это может быть атака DoS, заключается в том, что кому-то удалось подделать ваш IP-адрес (невозможно при подключении TCP) или если вы неоднократно ошибочно вводите свой пароль (в этом случае это не кто-то, кто контролирует правила брандмауэра, это вы) - devicenull
Извините, но я не спросил, была ли это хорошая идея. - HeavyWave
Разумеется, исключений не может быть установлено для одного или нескольких конкретных IP-адресов, что в значительной степени устранит проблему DoS. - John Gardeniers


Это старая нить. Я использовал сценарий, предоставленный kevinmicke в 2014-2015 годах. Тогда он просто прекратил работать. Поэтому мне пришлось немного его отредактировать, чтобы применить аутентификацию Windows Network Security, которая не оставляет IP-адреса в журнале безопасности. Кроме того, поскольку у меня нет обычного 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. Если вы все еще используете Remote Desktop с аутентификацией уровня доступа к сети в Windows 2008, вам может понадобиться сделать следующий трюк. Windows 2008 не имеет IP-адресов в журнале безопасности и, похоже, не содержится в журнале Microsoft-Windows-RemoteDesktopServices-RdpCoreTS. Поэтому мне пришлось фактически использовать 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
2017-11-15 19:01





я использую ts_block freeby.

В основном это «программа VBScript, которая действует как приемник событий WMI для получения событий, зарегистрированных в Windows в ответ на недействительные службы терминалов вход в систему «.

Кажется, что он отлично работает, и сценарий прост, если вам нужно его модифицировать. Вы можете либо разрешить им попытки входа в систему, а затем запретить на основе количества разрешенных попыток и / или вы можете жестко запрограммировать имена пользователей, к которым вы не хотите предоставлять доступ.

Меня поймали, случайно добавив одно и то же имя дважды, и служба просто переходит в бесконечный цикл, перезагружающий каждые 1500 мс, но очень легко исправлять / модифицировать, если вы в порядке с vbs.

Мои текущие настройки - это всего лишь один повтор, и вы заблокированы на 2 дня, при этом логины, такие как «Администратор», «Администратор», «Гость» и т. Д., Автоматически запрещены. Должно быть просто изменить ip?

Привыкание, чтобы зайти и посмотреть, какие твари были запрещены в одночасье ...


1
2018-05-01 06:52





Вы имеете в виду вход на сервер / домен или вход на веб-сайт, запущенный на сервере? Если вы имеете в виду вход на сервер / домен, тогда ответ будет отрицательным. Windows не имеет понятия блокировки IP-адресов на основе неудачных попыток входа в систему, поскольку IP-адреса не являются объектами безопасности. Там могут быть сторонние инструменты, которые могут это сделать, но я не знаю никого, поскольку я никогда не смотрел на него.


0
2018-02-09 13:17