Skip to content

Instantly share code, notes, and snippets.

@ghotz
Last active May 7, 2024 04:40
Show Gist options
  • Save ghotz/1b99470bce5caed245c1b024040ec263 to your computer and use it in GitHub Desktop.
Save ghotz/1b99470bce5caed245c1b024040ec263 to your computer and use it in GitHub Desktop.
Auto ban IP addresses by POST requests total size over a certain threshold in the last http log file
# Warning: remember to whitelist who you want to allow to post by entering their IP addresses in the Azure Portal
import-module Az;
$TenantID = 'YOURTENANTID';
$SubscriptionID = 'YOURSUBID'
$ResourceGroupName = 'WebSite';
$AppServiceName = 'YOURSERVICENAME';
$MyIP = (Invoke-WebRequest -uri "http://ifconfig.me/ip").Content; #avoid self-banning
$MaxPostsBytes = 100KB;
# Authenticate to Azure if not already authenticated
if (!$Connection) { $Connection = Connect-AzAccount -Tenant $TenantID -Subscription $SubscriptionID };
# Get Log files technique from https://hkarthik7.github.io/azure%20devops/powershell/azure/2021/01/16/Parse-http-logs-of-Azure-webapp-using-Azure-DevOps-CI-pipeline.html
$SCM = "https://$($AppServiceName).scm.azurewebsites.net/api/vfs/LogFiles/http/rawlogs/" # to get zip file $SCM.Replace("vfs", "zip")
# Get authentication details from the publishing profile
Write-Output "Getting the authentication details from the publishing profile...";
if (!$WebApp) { $WebApp = Get-AzWebApp -ResourceGroupName $ResourceGroupName -Name $AppServiceName };
if (!$PublishingProfile) { [xml]$PublishingProfile = Get-AzWebAppPublishingProfile -WebApp $WebApp };
$UserName = $PublishingProfile.publishData.publishProfile[0].userName;
$Password = $PublishingProfile.publishData.publishProfile[0].userPWD;
$Base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $UserName,$Password)));
# Get the log files
Write-Output "Getting the log files...";
$LogFiles = Invoke-RestMethod -Uri $SCM -Headers @{Authorization=("Basic {0}" -f $Base64AuthInfo)} -Method GET;
#$LogFiles = $LogFiles | Where-Object { (Get-Date $_.crtime).Date -eq (Get-Date).Date } | Select * -Last 1; # filter by date as needed
$LogFile = $LogFiles | Sort-Object -Property mtime -Descending | Select -First 1;
$RawLog = Invoke-RestMethod -Uri "$SCM/$($LogFile.name)" -Headers @{Authorization=("Basic {0}" -f $Base64AuthInfo)} -Method GET; # to export -OutFile "PATH" -ContentType "text/plain" or "multipart/form-data" if zip file
# Parse the log files and get the IP addresses to ban
Write-Output "Parsing the log files and getting the IP addresses to ban...";
$ParsedLog = $RawLog | ConvertFrom-Csv -Delimiter " " -Header 'date','time','s-sitename','cs-method','cs-uri-stem','cs-uri-query','s-port,cs-username','c-ip','cs(User-Agent)','cs(Cookie)','cs(Referer)','cs-host','sc-status','sc-substatus','sc-win32-status','sc-bytes','cs-bytes','time-taken';
$IPAdressesToBan = $ParsedLog | ? { $_.'cs-method' -eq 'POST' -and $_.'cs(User-Agent)' -ne $MyIP } | Group-object -Property 'cs(User-Agent)' | % {[pscustomobject]@{IPAddress=$_.Name;PostsCount=$_.Count;PostsBytes = ($_.group | measure-object 'cs-bytes' -Sum).Sum}} | ? PostsBytes -gt $MaxPostsBytes | Select *;
# Get the IP addresses already banned
Write-Output "Getting the IP addresses already banned...";
$Restrictions = Get-AzWebAppAccessRestrictionConfig -ResourceGroupName $ResourceGroupName -Name $AppServiceName;
$IPAddressBanned = $Restrictions.MainSiteAccessRestrictions | ? { $_.Action -eq 'deny' -and $_.IpAddress -ne 'Any' -and ($_.IpAddress -split '/')[1] -eq '32' } | % { ($_.IpAddress -split '/')[0] };
# Ban the new IP addresses
$IPAdressesToBan | ? { $_.IPAddress -notin $IPAddressBanned } | % {
Write-Output "Banning $($_.IPAddress)..."
Add-AzWebAppAccessRestrictionRule -ResourceGroupName $ResourceGroupName -WebAppName $AppServiceName -Name "BL $($_.IPAddress)" -Priority 90 -Action Deny -IpAddress ("{0}/{1}" -f $_.IPAddress,'32')
};
Write-Host "Top 10 IP address L2 prefixes with the most POSTs and bytes:";
$IPAddressBanned | % {
[pscustomobject]@{
L1 = ($_ -split '\.')[0];
L2 = ("{0}.{1}" -f ($_ -split '\.')[0],($_ -split '\.')[1]);
L3 = ("{0}.{1}.{2}" -f ($_ -split '\.')[0],($_ -split '\.')[1],($_ -split '\.')[2]);
L4 = $_;
}
} |
Group-Object -Property L2 | sort count -Descending | select -First 10 | ft;
Write-Host "Top 10 IP address L3 prefixes with the most POSTs and bytes:";
$IPAddressBanned | % {
[pscustomobject]@{
L1 = ($_ -split '\.')[0];
L2 = ("{0}.{1}" -f ($_ -split '\.')[0],($_ -split '\.')[1]);
L3 = ("{0}.{1}.{2}" -f ($_ -split '\.')[0],($_ -split '\.')[1],($_ -split '\.')[2]);
L4 = $_;
}
} |
Group-Object -Property L3 | sort count -Descending | select -First 10 | ft;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment