2025-07-30

Block Auth Failed IPs for Exchange

$UnBlockIPURL 是一個給 User 自行解鎖 IP 的清單,要另外處理
此處不提供與介紹

# in Hours
$BlockTime = 720;
$RuleGroupName = "ExchangeAuthFailBlockIPs"
$RuleSubnetsGroupName = "ExchangeAuthFailBlockSubnets"
$SMTPLookBackHours = 1;
$SMTPLogFullPath = "C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\FrontEnd\ProtocolLog\SmtpReceive\"
$SMTPLogSearchTailLines = 10000;
$UnBlockIPURL = 'https://www.contoso.com/BlockIPs/History/AllUnblock.Json';

$ClassBSubnetBlockCount = 3;

#-------------------------------------------------------------------------------------------------------------------------------------------

$MicrosoftIPSubnetsContent = '104.146.128.0/17,104.47.0.0/17,13.107.128.0/22,13.107.136.0/22,13.107.140.6/32,13.107.18.10/31,13.107.18.15/32,13.107.6.152/31,13.107.6.171/32,13.107.6.192/32,13.107.9.192/32,131.253.33.215/32,132.245.0.0/16,150.171.32.0/22,150.171.40.0/22,20.190.128.0/18,20.20.32.0/19,20.231.128.0/19,204.79.197.215/32,23.103.160.0/20,2603:1006::/40,2603:1006:1400::/40,2603:1006:2000::/48,2603:1007:200::/48,2603:1016::/36,2603:1016:1400::/48,2603:1016:2400::/40,2603:1017::/48,2603:1026::/36,2603:1026:2400::/40,2603:1026:3000::/48,2603:1027::/48,2603:1027:1::/48,2603:1036::/36,2603:1036:2400::/40,2603:1036:3000::/48,2603:1037::/48,2603:1037:1::/48,2603:1046::/36,2603:1046:1400::/40,2603:1046:2000::/48,2603:1047::/48,2603:1047:1::/48,2603:1056::/36,2603:1056:1400::/40,2603:1056:2000::/48,2603:1057::/48,2603:1057:2::/48,2603:1061:1300::/40,2603:1063::/38,2603:1063:2000::/38,2620:1ec:4::152/128,2620:1ec:4::153/128,2620:1ec:4::192/128,2620:1ec:40::/42,2620:1ec:6::/48,2620:1ec:8f0::/46,2620:1ec:8f8::/46,2620:1ec:8fc::6/128,2620:1ec:900::/46,2620:1ec:908::/46,2620:1ec:a92::152/128,2620:1ec:a92::153/128,2620:1ec:a92::171/128,2620:1ec:a92::192/128,2620:1ec:c::10/128,2620:1ec:c::11/128,2620:1ec:c::15/128,2620:1ec:d::10/128,2620:1ec:d::11/128,2a01:111:f100:2000::a83e:3019/128,2a01:111:f100:2002::8975:2d79/128,2a01:111:f100:2002::8975:2da8/128,2a01:111:f100:7000::6fdd:6cd5/128,2a01:111:f100:a004::bfeb:88cf/128,2a01:111:f400::/48,2a01:111:f402::/48,2a01:111:f403::/48,40.104.0.0/15,40.107.0.0/16,40.108.128.0/17,40.126.0.0/18,40.92.0.0/15,40.96.0.0/13,52.100.0.0/14,52.104.0.0/14,52.108.0.0/14,52.112.0.0/14,52.122.0.0/15,52.238.119.141/32,52.238.78.88/32,52.244.160.207/32,52.244.37.168/32,52.96.0.0/14';

$MicrosoftIPSubnets = @();
$MicrosoftIPSubnets += $MicrosoftIPSubnetsContent -Split ',';

$EscapeIPsContent = '175.140.29.122/32';
$EscapeIPs = @();
$EscapeIPs += $EscapeIPsContent -Split ',';

$MicrosoftIPRanges = @();
$MicrosoftIPRanges += '40.74.0.0-40.125.127.255';
$MicrosoftIPRanges += '52.96.0.0-52.115.255.255';

$FirewallObject = New-Object -ComObject HNetCfg.FwPolicy2;
$Global:Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False;

# Function

Function ExtractStringBetweenStrings {

param (
$MainString,
$FirstString,
$SecondString
);

$FirstPos = $MainString.IndexOf($FirstString) + $FirstString.Length
$SecondPos = $MainString.IndexOf($SecondString,$FirstPos)
$Return = $MainString.substring($FirstPos,($SecondPos-$FirstPos))

return $Return;
};

Function MergeRules {

param (
$Type
);

# Day
$MergeDates = @();
$DateCounts = 7;
switch ($Type) {
'Day' {
for ($i=1;$i -le $DateCounts;$i++) {
$MergeDates += ('{0:yyyy-MM-dd}' -f $((Get-Date).AddDays(-$i)));
};
};
'Month' {
for ($i=1;$i -le $DateCounts;$i++) {
$MergeDates += ('{0:yyyy-MM}' -f $((Get-Date).AddMonths(-$i)));
};
};
'Year' {
for ($i=1;$i -le $DateCounts;$i++) {
$MergeDates += ('{0:yyyy}' -f $((Get-Date).AddYears(-$i)));
};
};
};

foreach ($MergeDate in $MergeDates) {
$FirewallRuleName  = ($RuleGroupName + ' ' + $MergeDate);
Write-Host ('MergeRules: ' + $Type + ' of ' + $MergeDate);

$MergeRules = @();
$MergeRules += $FirewallObject.rules | where {($_.Grouping -eq $RuleGroupName) -and ($_.Name -like ($RuleGroupName + ' ' + $MergeDate + '*')) -and ($_.Name -ne ($RuleGroupName + ' ' + $MergeDate))};

if ($MergeRules.Count -le 0) {
Write-Host ('No Rules of ' + $MergeDate + ' to Merge');
} else {

$MergeBlockIPs = @();
foreach ($MergeRule in $MergeRules) {
Write-Host ('MergeRules: ' + $MergeRule.Name + ' to ' + $FirewallRuleName);
$MergeBlockIPs += ($($MergeRule.RemoteAddresses).Replace('/255.255.255.255','').Replace('/255.255.255.0','/24').Replace('/255.255.0.0','/16').Replace('/255.0.0.0','/8')).Split(',').Split('-');
};

if ($MergeBlockIPs.Count -gt 0) {
$TempArray = $MergeBlockIPs | where {(($_ -ne $Null) -and ($_ -ne '') -and ($_ -ne '*'))} | Sort-Object | Get-Unique;
$MergeBlockIPs += $TempArray;
};

foreach ($IP in $MergeBlockIPs) {
if ((CheckIPInSubnet -IpAddresses $IP -Subnets $MicrosoftIPSubnets) -eq $True) {
write-host ("IP " + $IP + " is Microsoft Office365 Server IP, Pass it.");
$MergeBlockIPs = $MergeBlockIPs | where {$_ -ne $IP}
};
if ((CheckIPInRange -IpAddresses $IP -Subnets $MicrosoftIPRanges) -eq $True) {
write-host ("IP " + $IP + " is Microsoft IP, Pass it.");
$MergeBlockIPs = $MergeBlockIPs | where {$_ -ne $IP}
};
};
$MergeBlockIPsTemp = @();
$MergeBlockIPsTemp += $MergeBlockIPs | Sort-Object | Get-Unique;
$MergeBlockIPs = @();
$MergeBlockIPs += $MergeBlockIPsTemp;

if ($MergeBlockIPs -ne $Null) {
if ($MergeBlockIPs.Count -ge 1) {
$CheckRuleExists = @();
$CheckRuleExists += $FirewallObject.rules | where {($_.Grouping -eq $RuleGroupName) -and ($_.Name -eq $FirewallRuleName)};
if ($CheckRuleExists.Count -eq 0) {
$RuleToAdd = ($MergeBlockIPs -Join(','));
if (-not (($RuleToAdd -eq $Null) -or ($RuleToAdd -eq '') -or ($RuleToAdd -Match '0.0.0.0') -or ($RuleToAdd -eq '*'))) {
write-host ("Add Policy: " + $FirewallRuleName + " => " + $RuleToAdd);
$Rule = New-Object -ComObject HNetCfg.FWRule;
$Rule.Name = $FirewallRuleName;
$Rule.Enabled = $True;
$Rule.Direction = 1;
$Rule.Grouping = $RuleGroupName;
$Rule.Profiles = 7;
$Rule.Action = 0;
$Rule.EdgeTraversal = $false;
$Rule.RemoteAddresses = $RuleToAdd;
$FirewallObject.Rules.Add($Rule);
$ProcessType = "Add";
};
} else {
foreach ($CheckRuleExist in $CheckRuleExists) {
if ($CheckRuleExist -ne $Null) {
$BlockedIPs = @();
$BlockedIPs += (($($CheckRuleExist.RemoteAddresses).Replace('/255.255.255.255','').Replace('/255.255.255.0','/24').Replace('/255.255.0.0','/16').Replace('/255.0.0.0','/8')).Split(',').Split('-'));
if ($BlockedIPs.Count -gt 0) {
$TempArray = $BlockedIPs | where {(($_ -ne $Null) -and ($_ -ne '') -and ($_ -ne '*'))} | Sort-Object | Get-Unique;
$BlockedIPs = @();
$BlockedIPs += $TempArray;
};
if (($MergeBlockIPs -Join(',')) -ne ($BlockedIPs -Join(',')))  {
$MergeBlockIPs += $BlockedIPs;
if ($MergeBlockIPs.Count -gt 0) {
$TempArray = $MergeBlockIPs | Sort-Object | Get-Unique;
$MergeBlockIPs = @();
$MergeBlockIPs += $TempArray;
};

$RuleToAdd = ($MergeBlockIPs -Join(','));
if (-not (($RuleToAdd -eq $Null) -or ($RuleToAdd -eq '') -or ($RuleToAdd -Match '0.0.0.0') -or ($RuleToAdd -eq '*'))) {
write-host ("Update Policy: " + $CheckRuleExist.Name + " => : " + $RuleToAdd);
Set-NetFirewallRule -DisplayName $CheckRuleExist.Name -RemoteAddress $MergeBlockIPs;
};
};
} else {

};
};
};

foreach ($MergeRule in $MergeRules) {
write-host ("Remove Merged Policy: " + $MergeRule.Name + " which Merged in " +  $FirewallRuleName);
Remove-NetFirewallRule -DisplayName $MergeRule.Name
};
};
};
};
};
};

function CheckIPInRange {
param(
[string[]] $IpAddresses,
[string[]] $IPRanges
)

<#
.SYNOPSIS
Determine if an IP address exists in the specified IP Range.
.EXAMPLE
PS C:\>CheckIPInRange 192.168.1.10 192.168.1.0-192.168.10.0
Determine if the IP address exists in the specified IP Range.
.INPUTS
System.Net.IPAddress
#>

foreach ($IpAddress in $IpAddresses) {
[bool] $Result = $false
foreach ($IPRange in $IPRanges) {
$ip = [system.net.ipaddress]::Parse($ipAddress).GetAddressBytes()
[array]::Reverse($ip)
$ip = [system.BitConverter]::ToUInt32($ip, 0)

$from = [system.net.ipaddress]::Parse(($IPRange -Split "-")[0]).GetAddressBytes()
[array]::Reverse($from)
$from = [system.BitConverter]::ToUInt32($from, 0)

$to = [system.net.ipaddress]::Parse(($IPRange -Split "-")[1]).GetAddressBytes()
[array]::Reverse($to)
$to = [system.BitConverter]::ToUInt32($to, 0)

[bool] $Result = ($from -le $ip -and $ip -le $to)
if ($Result -eq $True) {
break;
};
};
return $Result
};
}

function CheckIPInSubnet {
[CmdletBinding()]
[OutputType([bool], [string[]])]
param (
# IP Address to test against provided subnets.
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 1)]
[ipaddress[]] $IpAddresses,
# List of subnets.
[Parameter(Mandatory = $true)]
[string[]] $Subnets,
# Return list of matching subnets rather than a boolean result.
[Parameter(Mandatory = $false)]
[switch] $ReturnMatchingSubnets
)

<#
.SYNOPSIS
Determine if an IP address exists in the specified subnet.
.EXAMPLE
PS C:\>CheckIPInSubnet 192.168.1.10 -Subnet '192.168.1.1/32','192.168.1.0/24'
Determine if the IP address exists in the specified subnet.
.INPUTS
System.Net.IPAddress
#>

process {
foreach ($IpAddress in $IpAddresses) {
[System.Collections.Generic.List[string]] $listSubnets = New-Object System.Collections.Generic.List[string]
[bool] $Result = $false
foreach ($Subnet in $Subnets) {
[string[]] $SubnetComponents = $Subnet.Split('/')

[int] $bitIpAddress = [BitConverter]::ToInt32($IpAddress.GetAddressBytes(), 0)
[int] $bitSubnetAddress = [BitConverter]::ToInt32(([ipaddress]$SubnetComponents[0]).GetAddressBytes(), 0)
[int] $bitSubnetMaskHostOrder = 0
if ($SubnetComponents[1] -gt 0) {
$bitSubnetMaskHostOrder = -1 -shl (32 - [int]$SubnetComponents[1])
}
[int] $bitSubnetMask = [ipaddress]::HostToNetworkOrder($bitSubnetMaskHostOrder)

if (($bitIpAddress -band $bitSubnetMask) -eq ($bitSubnetAddress -band $bitSubnetMask)) {
if ($ReturnMatchingSubnets) {
$listSubnets.Add($Subnet)
}
else {
$Result = $true
continue
}
}
}

## Return list of matches or boolean result
if ($ReturnMatchingSubnets) {
if ($listSubnets.Count -gt 1) { Write-Output $listSubnets.ToArray() -NoEnumerate }
elseif ($listSubnets.Count -eq 1) { Write-Output $listSubnets.ToArray() }
else {
$Exception = New-Object ArgumentException -ArgumentList ('The IP address {0} does not belong to any of the provided subnets.' -f $IpAddress)
Write-Error -Exception $Exception -Category ([System.Management.Automation.ErrorCategory]::ObjectNotFound) -CategoryActivity $MyInvocation.MyCommand -ErrorId 'TestIpAddressInSubnetNoMatch' -TargetObject $IpAddress
}
}
else {
return $Result
}
}
}
}

# Function

$AddBlockIP = @();
$PrivateIPAlert = @();

# AddBlockIP From Event Log

$QueryEvents = (Get-EventLog -LogName Security -InstanceId 4625 -After (Get-Date).AddMinutes(-60))

foreach ($QueryEvent in $QueryEvents) {
$IP = ((($QueryEvent.Message.split("`n")) | where {$_ -like "*Source Network Address*"}) -split ":")[1].trim();
if (([ipaddress]::TryParse($IP, [ref]$null)) -eq $True) {
if ($IP -NotMatch '(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)') {
# Public IP
$AddBlockIP += $IP
} else {
# Private IP
if ($PrivateIPAlert.IP -notcontains $IP) {
$PrivateIPAlert += New-Object -TypeName psobject -Property @{
IP = $IP;
Event = $QueryEvent;
};
};
};
};
};
# AddBlockIP From Event Log

# AddBlockIP From SMTP Log

$BlockFromSMTPLog = @();
$LastLogFiles = Get-ChildItem $SMTPLogFullPath | sort LastWriteTime | select -last 2

foreach ($LastLogFile in $LastLogFiles) {
write-host ("Working on File: " + $LastLogFile.Name);
$AuthFailedLog = (Get-Content -Path $LastLogFile.FullName -Tail $SMTPLogSearchTailLines | where-object {$_ -Like '*Inbound AUTH LOGIN failed*' -or $_ -Like '*Unrecognized authentication type*' -or $_ -Like '*Authentication unsuccessful*'})| sort -Descending

foreach ($Item in $AuthFailedLog) {
$Elements = $Item.Split(",");
if (([DateTime]$Elements[0]) -lt $(Get-Date).AddHours(-$SMTPLookBackHours)) {
break;
};
$GetIP = ($Elements[5].Split(":"))[0];
if (-not (($GetIP -eq $Null) -or ($GetIP -eq '') -or ($GetIP -eq '-') -or ($GetIP -eq '*') -or ($GetIP -Match '175.140.29.122') -or ($GetIP -Match '0.0.0.0') -or ($GetIP -Match '(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)'))) {
$GetIP = try {[ipaddress]$GetIP} catch {$False};
if ($GetIP -ne $False) {
if ($GetIP.IPAddressToString -ne $Null) {
$BlockFromSMTPLog += $GetIP.IPAddressToString;
};
};
};
};
};
$AddBlockIP += $BlockFromSMTPLog;
# AddBlockIP From SMTP Log

$AddBlockIP = ($AddBlockIP | Group -NoElement | where {$_.Count -ge 10}).Name | Sort-Object | Get-Unique
$AddBlockIP
$PrivateIPAlert

# Pass IP Unblock By User
try {
$AllUnblockIPs = (Invoke-RestMethod -Uri $UnBlockIPURL);
write-host ("Got Pass IP Unblock By User :=> " + ($AllUnblockIPs | ConvertTo-Json -Compress));
}catch {
}

if ($AllUnblockIPs -ne $Null) {
foreach ($Item in $AllUnblockIPs) {
$TimePassSeconds = (New-TimeSpan -Start (([System.DateTimeOffset]::FromUnixTimeSeconds($Item.Time)).DateTime.ToLocalTime()) -End (Get-Date)).TotalSeconds;
if ($TimePassSeconds -lt 3600) {
if (($Item.Type).ToLower() -eq 'unblock ip') {
$Policys = @();
$Policys += ($FirewallObject.rules | where {($_.Grouping -eq $RuleGroupName) -and ($_.RemoteAddresses -like ("*" + $Item.IP + "*"))})
if ($Policys -ne $Null) {
foreach ($Policy in $Policys) {
$NewRemoteAddress = (($($Policy.RemoteAddresses).Replace('/255.255.255.255','/32').Replace('/255.255.255.0','/24').Replace('/255.255.0.0','/16').Replace('/255.0.0.0','/8')).Split(',').Split('-'));
if ($NewRemoteAddress.Count -gt 0) {
$TempArray = $NewRemoteAddress | where {(($_ -ne $Null) -and ($_ -ne '') -and ($_ -ne '*') -and ($_ -ne ($Item.IP)) -and ($_ -ne ($Item.IP + '/32')))} | Sort-Object | Get-Unique;
$NewRemoteAddress = @();
$NewRemoteAddress += $TempArray;
};
if ($NewRemoteAddress -ne $Null) {
write-host ("Remove : " + $Item.IP + " from Policy: " + $Policy.Name);
Set-NetFirewallRule -DisplayName $Policy.Name -RemoteAddress $NewRemoteAddress
} else {
write-host ("Remove Policy (Unblock By User): " + $Policy.Name);
Remove-NetFirewallRule -DisplayName $Policy.Name
};
};
};
write-host ("Removed : " + $Item.IP + " from AddBlockIP");
$AddBlockIP = $AddBlockIP | where {($_ -ne $Item.IP) -and (($_ -ne $Null) -and ($_ -ne '') -and ($_ -ne '*'))};
};
};
};
};
# Pass IP Unblock By User

# Skip Microsoft and Escape IPs
foreach ($IP in $AddBlockIP) {
if ((CheckIPInSubnet -IpAddresses $IP -Subnets $MicrosoftIPSubnets) -eq $True) {
write-host ("IP " + $IP + " is Microsoft Office365 Server IP, Pass it.");
$AddBlockIP = $AddBlockIP | where {$_ -ne $IP}
};
if ((CheckIPInRange -IpAddresses $IP -Subnets $MicrosoftIPRanges) -eq $True) {
write-host ("IP " + $IP + " is Microsoft IP, Pass it.");
$AddBlockIP = $AddBlockIP | where {$_ -ne $IP}
};
if ((CheckIPInSubnet -IpAddresses $IP -Subnets $EscapeIPs) -eq $True) {
write-host ("IP " + $IP + " is Escape IP, Pass it.");
$AddBlockIP = $AddBlockIP | where {$_ -ne $IP}
};
};
# Skip Microsoft and Escape IPs

# Skip Already Blocked by Subnets

$BlockedSubnetsRulesExisted = @();
$BlockedSubnetsRulesExisted += $FirewallObject.rules | where {($_.Grouping -eq $RuleSubnetsGroupName)};
foreach ($RuleExisted in $BlockedSubnetsRulesExisted) {
$BlockedSubnets = @();
$BlockedSubnets += ((($RuleExisted.RemoteAddresses).Replace('/255.255.0.0','/16').Split(',')) | Sort-Object | Get-Unique);
};
foreach ($IP in $AddBlockIP) {
foreach ($BlockedSubnet in $BlockedSubnets) {
if ((CheckIPInSubnet -IpAddresses $IP -Subnets $BlockedSubnet) -eq $True) {
$AddBlockIP = $AddBlockIP | where {$_ -ne $IP}
};
};
};
# Skip Already Blocked by Subnets

# Skip Already Blocked
$RulesExisteds = @();
$RulesExisteds += $FirewallObject.rules | where {($_.Grouping -eq $RuleGroupName)};
$BlockedIPs = @();
if ($RulesExisteds -ne $Null) {
foreach ($RuleExisted in $RulesExisteds) {
$BlockedIPs += (($($RuleExisted.RemoteAddresses).Replace('/255.255.255.255','').Replace('/255.255.255.0','/24').Replace('/255.255.0.0','/16').Replace('/255.0.0.0','/8')).Split(',').Split('-'));
};
};
$BlockedIPs = $BlockedIPs | Sort-Object | Get-Unique
foreach ($IP in $AddBlockIP) {
if ($BlockedIPs -contains $IP) {
$AddBlockIP = ($AddBlockIP | where {$_ -ne $IP});
};
};
# Skip Already Blocked

$WholeBlockedIPs = ($BlockedIPs + $AddBlockIP | Sort-Object | Get-Unique);

# Upload Blocked IPs to Wii
$URL = 'https://www.contoso.com/AAPI/BlockIPs/';

$POST = ([PSCustomObject]@{
Host = $env:computername;
Method = 'Report';
BlockedIPs = $WholeBlockedIPs;
}) | ConvertTo-Json -Compress;

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$URLRequest = Invoke-RestMethod -Method 'POST' -Uri $URL -ContentType 'application/json' -Body $POST;
write-host $URLRequest;
write-host '';
# Upload Blocked IPs to Wii

# Block Subnet Class B

$BlockSubnetsUpdated = $False;

$BlockedIPClassB = @();
foreach ($BlockedIP in $WholeBlockedIPs) {
$BlockedIPClassB += ((($BlockedIP -Split '\.')[0..1] -Join '.') + '.0.0/255.255.0.0')
};
$BlockSubnets = @();
$BlockSubnets += ($BlockedIPClassB | Group-Object | where {$_.Count -ge $ClassBSubnetBlockCount}).Name

$CheckRuleExists = @();
$CheckRuleExists += $FirewallObject.rules | where {$_.Name -eq $RuleSubnetsGroupName};
if ($CheckRuleExists.Count -eq 0) {
$Rule = New-Object -ComObject HNetCfg.FWRule;
$Rule.Name = $RuleSubnetsGroupName;
$Rule.Enabled = $True;
$Rule.Direction = 1;
$Rule.Grouping = $RuleSubnetsGroupName;
$Rule.Profiles = 7;
$Rule.Action = 0;
$Rule.EdgeTraversal = $false;
$Rule.RemoteAddresses = ($BlockSubnets -join ",");
if ($Rule.RemoteAddresses -ne '*') {
$FirewallObject.Rules.Add($Rule);
$BlockSubnetsUpdated = $True;
};
} else {
foreach ($CheckRuleExist in $CheckRuleExists) {
if ($CheckRuleExist) {
$RemoteAddress = @();
$RemoteAddress += ((($CheckRuleExist.RemoteAddresses).Split(',') | Sort-Object | Get-Unique) -join ",");
$NewBlockIP = @();
$NewBlockIP += $RemoteAddress.Split(',');
$NewBlockIP += $BlockSubnets;
$NewBlockIP = $NewBlockIP | Sort-Object | Get-Unique

if ($NewBlockIP.count -ne 0) {
if (($NewBlockIP -join ",") -ne $RemoteAddress) {
$CheckRuleExist.RemoteAddresses = ($NewBlockIP -join ",");
if ($CheckRuleExist.RemoteAddresses -ne '*') {
$CheckRuleExist.update;
$BlockSubnetsUpdated = $True;
};
};
};
};
};
};

#if ($BlockSubnetsUpdated -eq $True) {

$BlockedSubnetsRulesExisted = @();
$BlockedSubnetsRulesExisted += $FirewallObject.rules | where {($_.Grouping -eq $RuleSubnetsGroupName)};
foreach ($RuleExisted in $BlockedSubnetsRulesExisted) {
$BlockedSubnets = @();
$BlockedSubnets += ((($RuleExisted.RemoteAddresses).Replace('/255.255.0.0','/16').Split(',')) | Sort-Object | Get-Unique);
};

$UpdateRules = @();
$UpdateRules += $FirewallObject.rules | where {($_.Grouping -eq $RuleGroupName) -and ($_.Name -like ($RuleGroupName + '*'))};

if ($UpdateRules.Count -gt 0) {
foreach ($UpdateRule in $UpdateRules) {
write-host ('Working on ' + $UpdateRule.Name)
$RemoteAddress = @();
$RemoteAddress += $($UpdateRule.RemoteAddresses).Replace('/255.255.255.255','');
$NewBlockIP = @();
$NewBlockIP += $RemoteAddress.Split(',');
foreach ($IP in $NewBlockIP) {
foreach ($BlockedSubnet in $BlockedSubnets) {
if ((CheckIPInSubnet -IpAddresses $IP -Subnets $BlockedSubnet) -eq $True) {
write-host ('Remove ' + $IP + ' from ' + $UpdateRule.Name)
$NewBlockIP = $NewBlockIP | where {$_ -ne $IP};
};
};
};
$NewBlockIP = $NewBlockIP | Sort-Object | Get-Unique

if ($NewBlockIP.count -ne 0) {
if (($NewBlockIP -join ",") -ne $RemoteAddress) {
$UpdateRule.RemoteAddresses = ($NewBlockIP -join ",");
if ($UpdateRule.RemoteAddresses -ne '*') {
$UpdateRule.update;
};
};
};
};
};
#};
# Block Subnet Class B

if ($AddBlockIP.count -ne 0) {

$FirewallRuleName  = ($RuleGroupName + ' ' + (Get-Date).ToUniversalTime().AddHours(8).ToString('yyyy-MM-dd HH:00:00'));

$CheckRuleExists = @();
$CheckRuleExists += $FirewallObject.rules | where {$_.Name -eq $FirewallRuleName};
if ($CheckRuleExists.Count -eq 0) {
$Rule = New-Object -ComObject HNetCfg.FWRule;
$Rule.Name = $FirewallRuleName;
$Rule.Enabled = $True;
$Rule.Direction = 1;
$Rule.Grouping = $RuleGroupName;
$Rule.Profiles = 7;
$Rule.Action = 0;
$Rule.EdgeTraversal = $false;
$Rule.RemoteAddresses = ($AddBlockIP -join ",");
if ($Rule.RemoteAddresses -ne '*') {
$FirewallObject.Rules.Add($Rule);
};
} else {
foreach ($CheckRuleExist in $CheckRuleExists) {
$RemoteAddress = @();
$RemoteAddress += $($CheckRuleExist.RemoteAddresses).Replace('/255.255.255.255','');
$NewBlockIP = @();
$NewBlockIP += $RemoteAddress.Split(',');
$NewBlockIP += $AddBlockIP;
$NewBlockIP = $NewBlockIP | Sort-Object | Get-Unique

if ($NewBlockIP.count -ne 0) {
if (($NewBlockIP -join ",") -ne $RemoteAddress) {
$CheckRuleExist.RemoteAddresses = ($NewBlockIP -join ",");
if ($CheckRuleExist.RemoteAddresses -ne '*') {
$CheckRuleExist.update;
};
};
};
};
};
};

if (([int]('{0:HH}' -f $(Get-Date))) -eq 0) {
MergeRules -Type 'Day'
if (([int]('{0:dd}' -f $(Get-Date))) -eq 1) {
MergeRules -Type 'Month';
if (([int]('{0:MM}' -f $(Get-Date))) -eq 1) {
MergeRules -Type 'Year'
};
};
};

#Delete Rules
$CheckRuleToDelete = @();
$CheckRuleToDelete += $FirewallObject.rules | where {$_.Grouping -eq $RuleGroupName} | where-object {[DateTime]($_.Name -Replace ($RuleGroupName + ' '),'') -lt $(Get-Date).AddHours(-$BlockTime)};
foreach ($Rule in $CheckRuleToDelete) {
write-host "Delete Rule: ""$($Rule.Name)"""
netsh advfirewall firewall delete rule name=($Rule.Name)
};






沒有留言:

張貼留言