Запретить IP-адрес на основании количества неудачных попыток входа в систему?
Можно ли забанить IP-адрес после Х числа неудачных попыток входа на Windows Server? Не для конкретного аккаунта, который я умею делать, а для всей машины.
Мы очень сильно пострадали от атак грубой силы, пытаясь угадать имена пользователей, так что это действительно помогло бы получить некоторую нагрузку на сервер.
13 ответов
Вы можете сделать это с 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, включая службы терминалов). Но вы можете установить запуск триггера, например, два раза в час, чтобы избежать ненужной загрузки сервера.
и после триггера запустить скрипт powershell. Вы также должны установить более высокие привилегии для запуска этого скрипта, иначе он завершится с ошибкой безопасности.
Вы также можете привязать этот скрипт к другим событиям безопасности.
Я знаю, что этот вопрос старый, но это было первое сообщение на форуме, с которым я столкнулся, когда начал пытаться делать то же самое пару недель назад. Мне удалось придумать рабочий скрипт, который 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 для поиска в журналах событий.
Этот сценарий основан на ответе remunda и идет немного дальше /questions/484625/zapretit-ip-adres-na-osnovanii-kolichestva-neudachnyih-popyitok-vhoda-v-sistemu/484637#484637 Он учитывает правило "BlockAttackers", для которого еще не введены IP-адреса (что возвращает "*" в виде строки). Он также записывает комментарий в файл журнала, чтобы сообщить, когда IP-адрес был добавлен в правило.
Хороший совет - создать правило "BlockAttackers", которое блокирует IP-адреса, НО сначала отключить его. Затем запустите этот скрипт один раз вручную, чтобы он мог заполнить поле "Удаленные адреса" фактическими IP-адресами, которые должны быть заблокированы. Посмотрите на эти IP-адреса, чтобы убедиться, что ничего критического не было добавлено, а затем включите правило брандмауэра. Добавьте это правило в брандмауэр, как описано в remunda.
#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'}
}
Я не могу взять кредит на этот ответ, но Evan Anderson упомянул его проект http://opensource.wellbury.com/projects/windows_sshd_block/newest-release/
Как правило, не стоит позволять кому-то еще контролировать ваши правила брандмауэра. Это в основном то, что вы просите здесь.
Это старая ветка. Я использовал сценарий, предоставленный 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. Если вы все еще используете удаленный рабочий стол с проверкой подлинности на уровне доступа к сети в 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, поэтому было бы неплохо, если бы некоторые гуру могли исправить / улучшить мой код.
Я использую ts_block freeby.
По сути, это "программа VBScript, которая действует как приемник событий WMI для получения событий, регистрируемых Windows в ответ на недопустимые входы в систему служб терминалов".
Кажется, работает отлично, и сценарий прост, если вам нужно изменить его. Вы можете либо разрешить ему регистрировать попытки, а затем запретить в зависимости от количества разрешенных попыток, и / или вы можете жестко закодировать имена входа, к которым вы не хотите предоставлять доступ.
Я был пойман, случайно добавив одно и то же имя дважды, и сервис просто переходит в бесконечный цикл, перезапускающийся каждые 1500 мс, но его очень легко исправить / изменить, если вы согласны с vbs.
Мои текущие настройки - только одна повторная попытка, и вы забанены на 2 дня, а такие логины, как "admin", "Admin", "Administrator", "guest" и т. Д., Автоматически заблокированы. Должно быть легко перейти на IP?
Какая-то захватывающая, чтобы пойти и посмотреть, какие твари были забанены за одну ночь...
Используя отличный сценарий remunda в качестве отправной точки, я добавил одну важную вещь, которой не хватало: блокировка IP-адресов от неудачных входов на FTP. Windows Server не регистрирует IP-адрес в журнале безопасности, когда кто-то не может войти в систему через FTP, но вместо этого устанавливает "Исходный сетевой адрес" на тире. FTP является очень распространенным вектором атак для атак методом перебора, поэтому я добавил к его сценарию возможность сканировать журналы FTP текущего дня на наличие множества ошибок входа и блокировать эти IP-адреса.
Обновление 2014/02/07: Когда я сделал несколько настроек для обработки всех моих старых журналов FTP, я понял, что когда у них было огромное количество попыток (более 50 000), создаваемые им массивы были бы огромными и делали обработку невероятно медленной. С тех пор я переписал его, чтобы сделать его намного более эффективным при обработке журналов FTP.
Я также обнаружил, что существует произвольное жесткое ограничение в 1000 для количества IP-адресов в одном правиле брандмауэра Windows. Из-за этого ограничения мне нужно было автоматически создавать новое правило при заполнении последнего. Теперь он это делает, а также создает исходное правило брандмауэра (если вы не создаете свое собственное), так что единственная настройка, которую нужно сделать, - это добавить его в планировщик для запуска при возникновении события 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 faultserver.ru user kevinmicke
# Windows Security Log portion written by faultserver.ru user remunda, which provided the starting point for kevinmicke
#
# Details: https://faultserver.ru/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
}
}
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 (бесплатно для личного и коммерческого использования)
Скрипт remuda, отредактированный kevinmicke (7 февраля в 21:59), не проверял канал управления FTP, который имеет собственную папку в моей системе (Windows Server 2008 R2). Также 530 11001
- события не были распознаны, которые появляются, когда хакер пытается получить доступ только к каналу управления. Поэтому я добавил несколько строк в скрипт, чтобы проверить вторую папку FTP-log:
# Этот сценарий Windows Powershell автоматически блокирует IP-адреса, которые пытаются войти в систему, # и завершает работу в течение указанного ниже числа раз с переменной $int_block_limit или более. Is сканирует как журнал Security #, который охватывает Remote Desktop и другие попытки, так и журнал FTP текущего дня. Если предел $int_block_limit # достигнут в любом из этих журналов (отдельно, а не вместе), тогда IP-адрес будет добавлен к правилу # firewall. # # Сценарий автоматически создаст правило брандмауэра с именем "BlockAttackers (Создано гггг-ММ-дд ЧЧ: мм: сс UTC)", используя # текущее время, если того, чье имя содержит "BlockAttackers", еще не существует. Поскольку существует жесткое ограничение # в 1000 записей (IP-адресов), которое вы можете заблокировать для каждого правила, оно также создаст правила с аналогичными именами, как только этот предел будет достигнут для самого последнего. # # Рекомендую настроить запуск сценария как запланированной задачи, вызванной ошибками аудита входа в систему события 4625 из # журнала безопасности, или, в качестве альтернативы, можно настроить его выполнение через некоторое время (т. Е. Каждые 10 минут). # # Авторы: # Большинство сценариев, написанных пользователем faultserver.ru kevinmicke # Часть журнала безопасности Windows, написанная remunda пользователя faultserver.ru, которая послужила отправной точкой для kevinmicke # Проверка канала управления FTP, добавленная пользователем faultserver.ru Уве Мартенсом # # Подробности: https://faultserver.ru/questions/233222/ban-ip-address-based-on-x-number-of-unsuccessful-login-attempts # Установить количество неудачных попыток входа в систему, после которых будет получен IP-адрес быть заблокированным $int_block_limit = 3 # Временное окно, в течение которого проверяется журнал безопасности, который в настоящее время настроен на проверку только за последние 24 часа $dat_time_window = [DateTime]::Now.AddDays(-1) # Выбрать из журнала безопасности все IP-адреса, которые имеют более $int_block_limit сбоев аудита (событие 4625) в пределах $dat_time_window $arr_new_bad_ips_security_log = @() $arr_new_bad_ips_security_log = Get-EventLog -LogName 'Security' -InstanceId 4625 -After_indow_time | Select-Object @{n='IpAddress';e={$_.ReplacementStrings[-2]}} | Групповой объект -свойство IpAddress | Где {$_.Count -ge $int_block_limit} | Выберите -property Name # Получить текущее время UTC для определения имени файла для текущего журнала FTP. $ Current_date_utc = (Get-Date).ToUniversalTime() # Установить путь к текущему файлу журнала канала управления FTP $str_log_file_name_control_channel = "C:\inetpub\logs\" LogFiles\FTPSVC\u_ex" + $current_date_utc.ToString("yyMMdd") + ".log" # Искать в текущем файле журнала канала управления FTP"530 1", чтобы найти строки, содержащие IP-адреса систем, которые не смогли войти в систему, # get просто IP-адрес из каждой строки, сгруппируйте IP-адреса по IP-адресу, чтобы подсчитать количество попыток каждого из них, и выберите только # IP-адресов, которые имеют $int_block_limit или более неправильных входов в систему сегодня узор "530 1" | ForEach-Object {$_.Line.Substring(20,15) -replace " .*", ""} | Группа | Где {$_.Count -ge $int_block_limit} | Выберите -property Name # Установить путь к текущему файлу журнала FTP $str_log_file_name = "C:\inetpub\logs\LogFiles\FTPSVC*\u_ex" + $current_date_utc.ToString("yyMMdd") + ".log" # Искать в сегодняшнем журнале FTP файл для "530 1", чтобы найти строки, содержащие IP-адреса систем, которые не смогли войти в систему, # получить только IP-адрес из каждой строки, сгруппировать IP-адреса по IP-адресу для подсчета попыток каждой из них и выбрать только # IP-адреса, которые имеют $int_block_limit или более неудачных входов в систему сегодня # В FTPSVC * необходимо добавить идентификатор FTP-сервера вместо * или просто взять нужную папку журнала $arr_new_bad_ips_ftp = @() $arr_new_bad_ips_ftp = Select-String $str_log_file_name -pattern "530 1" | ForEach-Object {$_.Line.Substring(20,15) -replace " .*", ""} | Группа | Где {$_.Count -ge $int_block_limit} | Выберите -property Name # Объединить два массива IP-адресов (один из журнала безопасности, один из журнала FTP) $arr_new_bad_ips_all = @() # $arr_new_bad_ips_all = @($arr_new_bad_ips_security_log) + @($arr_new_bad_ips__p______x_pile_ips_ip__p___in__p__x__x__x__x__x__x__x_px_px_px_px_p_p_p_S_P_S_P_S_P_P_S_P_P_S_p_P_S_p_P_S_p_P_S_p_S_S_S_S_p_S_S_R_p_P_S_S_P_P_P_P_P_P_P_S_p_p_p_x_p_p_P_P_P_P_P_P_P_S_p=) + @($arr_new_bad_ips_ftp_control_channel) + @($arr_new_bad_ips_ftp) # Сортировать массив, выбрав только уникальные IP-адреса (в случае, если один IP-адрес обнаруживается в журналах безопасности и FTP) $arr_new_bad_ips_all_sorted = @()_r__________ __________#_all_ips_ip__all_ip__r__r=_r=_r=_r=_r&_r=_r&_r=_rus Foreach-Object { [string]$_.Name } | Select-Object -unique # Получить объект брандмауэра $firewall = New-Object -comobject hnetcfg.fwpolicy2 # Получить все правила брандмауэра, соответствующие "BlockAttackers*" $arr_firewall_rules = $firewall.Rules | Где {$_.Name -like 'BlockAttackers*'} # Если еще не существует правила брандмауэра "BlockAttackers *", создайте его и установите его в переменную, если ($arr_firewall_rules -eq $null) { $str_new_rule_name = "BlockAttackers (создано "+ $ current_date_utc.ToString (" гггг-ММ-дд ЧЧ: мм: сс ") + " UTC)"межсетевой экран netsh advfirewall добавить правило dir= в действии = имя блока =$str_new_rule_name description=" Правило создано автоматически." enable=yes remoteip="0.0.0.0" | Out-Null $arr_firewall_rules = $firewall.Rules | Где {$_.Name -like 'BlockAttackers*'} } # Разделить существующие IP-адреса из текущих правил (-ов) брандмауэра "BlockAttackers *" в массив, чтобы мы могли легко найти их $arr_existing_bad_ips = @() foreach ($rule in $arr_firewall_rules) { $arr_existing_bad_ips += $rule.RemoteAddresses -split(',') } # Очистить маски подсетей от IP-адресов, которые в настоящее время заблокированы правилами брандмауэра (-ов) ForEach-Object {$_ -replace "/.*", ""} # Введите IP-адрес вашего сервера (IPv4 и IPv6) в строке 115 и 116. # Выберите IP-адреса для добавления в брандмауэр, но только те, которые... $arr_new_bad_ips_for_firewall = @() $arr_new_bad_ips_for_firewall = $arr_new_bad_ips_all_sorted | Где { # содержат IP-адрес (т. Е. Не являются пустыми или дефисом, который есть в журнале безопасности для систем, которые не прошли FTP-вход) $_. Длина -gt 6 -and # еще не включена в правила брандмауэра!($arr_existing_bad_ips_without_masks -contains $_) -and # не являются локальной обратной связью!($_.StartsWith('127.0.0.1')) -and # не являются частью локальной подсети!($_.StartsWith('192.168.')) -And!($_.StartsWith('0.0.')) -And!($_.StartsWith('10.0.')) -And!($_.StartsWith('*.*.*.*')) -and!($_.StartsWith('*:*:*:*:*:*')) } # Если существуют блокируемые IP-адреса, выполните следующее... if ($arr_new_bad_ips_for_firewall -ne $null) { # Запись даты и времени в файл журнала для конкретного сценария [DateTime]::Now | Out-File -Append -Encoding utf8 C:\inetpub\logs\LogFiles\blockattackers.txt # Записать недавно заблокированные IP-адреса в файл журнала $arr_new_bad_ips_for_firewall | Out-File -Append -Encoding utf8 C:\inetpub\logs\LogFiles\blockattackers.txt # Boolean, чтобы убедиться, что новые IP-адреса добавляются только в одно правило $bln_added_to_rule = 0 # Массив для хранения плохих IP-адресов из каждого правила по одному в время, поэтому мы можем рассчитывать, чтобы убедиться, что добавление новых не превысит 1000 IP-адресов $arr_existing_bad_ips_current_rule = @() # Для каждого правила "BlockAttackers *" в брандмауэре выполните следующее... foreach ($rule в $ arr_firewall_rules)) { if ($bln_added_to_rule -ne 1) { # Разделить существующие IP-адреса из текущего правила в массив, чтобы их можно было легко подсчитать $arr_existing_bad_ips_current_rule = $rule.RemoteAddresses -split(',') # Если количество IP-адресов для add - меньше 1000 минус текущее количество IP-адресов в правиле, добавьте их в это правило, если ($arr_new_bad_ips_for_firewall.Count -le (1000 - $arr_existing_bad_ips_current_rule.Count)) { # Добавить новые IP-адреса в правило брандмауэра $ arr_new_bad_ips_for_ %{$rule.RemoteAddresses += ',' + $_} # Напишите, к какому правилу были добавлены IP-адреса для эхо-файла журнала. "Новые IP-адреса, добавленные выше в правило брандмауэра Windows:" $rule.Name | Out-File -Append -Encoding utf8 C:\inetpub\logs\LogFiles\blockattackers.txt # Установить логическое значение, чтобы любые другие правила пропускались при добавлении IP-адресов $bln_added_to_rule = 1 } } } # Если в другом месте не было места " BlockAttackers * "правило брандмауэра, создайте новое и добавьте к нему IP-адреса, если ($bln_added_to_rule -ne 1) { $str_new_rule_name = "BlockAttackers (создано) + $ current_date_utc.ToString ("гггг-ММ-дд ЧЧ: мм: сс ") + " UTC)" netsh advfirewall firewall добавить правило dir= в действии = имя блока =$str_new_rule_name description=" Правило создано автоматически." enable=yes remoteip="0.0.0.0" | Out-Null $new_rule = $firewall.rules | Где {$_.Name -eq $str_new_rule_name} # Добавить новые IP-адреса в правило брандмауэра $arr_new_bad_ips_for_firewall | %{$new_rule.RemoteAddresses += ',' + $_} # Напишите, к какому правилу были добавлены IP-адреса в эхо-файл журнала. "Новые IP-адреса выше добавлены во вновь созданное правило брандмауэра Windows:" $new_rule.Name | Out-File -Append -Encoding utf8 C:\inetpub\logs\LogFiles\blockattackers.txt } }
Имя лог-папки FTP FTPSVC*
на линии 54 должно быть завершено причины. В строке 115 и 116 необходимо ввести IP-адрес вашего сервера (IPv4 и IPv6), в противном случае IP-адрес собственных серверов может быть добавлен в правило брандмауэра сто раз. Переменная $int_block_limit
Я установил 1 на моем сервере, поэтому скрипт блокирует атаку хакеров, вызывая событие 4625 в течение двух секунд. Я все еще думаю о запуске сценария в дополнение к происходящим 4625 событиям за период в несколько минут. Конечно, было бы также возможно разделить сценарии и позволить одному сценарию проверять события 4625, инициированные событием 4625, а другому - папки журналов FTP, периодически проверяющие каждые 5 или 10 минут, даже с отдельным правилом межсетевого экрана. и лог-файл.
Если существует атакуемый веб-сервер, вы можете установить расширение динамических ограничений IP. Если это для стандартной аутентификации на сервере, то вы должны иметь возможность реализовать изоляцию домена и сервера, которая ограничивала бы объем атак на компьютеры, присоединенные к домену, и могла бы быть настроена таким образом, чтобы разрешать попытки только со стороны систем, к которым вам необходим доступ. сервер. В окнах предотвращение грубых атак состоит в том, чтобы установить политику блокировки учетной записи равной 10 минутам, а политику плохого пароля - 3 попыткам - это означает, что атакующая учетная запись блокируется в течение 10 минут после 3 попыток. IP-соединения не блокируются по умолчанию в Windows. (Кроме того, мне также любопытно, сколько попыток входа в систему требуется в секунду, чтобы повлиять на систему)
Вы имеете в виду вход на сервер / домен или вход на веб-сайт, работающий на сервере? Если вы имеете в виду вход на сервер / домен, то ответ - нет. В Windows отсутствует концепция блокировки IP-адресов на основании неудачных попыток входа в систему, поскольку IP-адреса не являются объектами безопасности. Могут быть сторонние инструменты, которые могут сделать это, но я не знаю ни одного, так как никогда не обращал на это внимания.
Я добавил мой для SQL
# Select from the Application log (SQL) all IP addresss that have more than $int_block_limit logon failure within $dat_time_window
$arr_new_bad_ips_SQL_log = @()
$arr_new_bad_ips_SQL_log = Get-EventLog -LogName 'Application' -After $dat_time_window |
Where-Object{$_.EventID -eq 18456} |
Select-Object @{n='CLIENT';e={$_.ReplacementStrings[-1]}} |
Group-Object -property CLIENT |
Where {$_.Count -ge $int_block_limit} |
Select -property Name |
{
$_.Name = $_.Name.Replace(" [CLIENT: ", "");
$_.Name = $_.Name.Replace("]", "");
return $_;
}
Тогда вам нужно будет добавить массив в ips_all
$arr_new_bad_ips_all = @($arr_new_bad_ips_SQL_log) + @($arr_new_bad_ips_security_log) + @($arr_new_bad_ips_ftp_control_channel) + @($arr_new_bad_ips_ftp)