Posts tagged “DDOS

Powershell script to monitor and protect Azure VM against Denial of Service attacks


To get started with Azure Powershell see this post.

Public facing web sites are increasingly getting exposed to distributed denial of service attacks. This controller script puts together a couple of tools/scripts that extract  IPs from HTTPErr logs based on frequency and set/update Azure VM Endpoint Access Control List. This script is available on the Microsoft Script Center Repository.

The script will:

  • Check if the computer running it has Internet access
  • Open a PS session to the Azure VM
  • Collect a group of web counters
  • Download HTTPErr log files if any
  • Archive those log files to a local folder on the Azure VM
  • Parse the downloaded files, extract IPs, identify those that appear more than $Threshold times
  • Retrieve the VM web Endpoint ACL
  • Update the VM web Endpoint ACL by adding offending IPs
  • Check if a given URL is online

Example:

E:\Install\Scripts\Azure\AZ-MonitorAndRepair.ps1 -SubscriptionName SB01-Subscription -VMName SB01 -AdminName Samb -PwdFile d:\sandbox\Cred.txt -EndPointName HTTP -URL http://mysitehere.com -Verbose

This example runs the script once. This can be used to generate the d:\sandbox\Cred.txt encrypted password file if it does not exist.

Az001

In this example, 5 HTTPErr log file were found, archived, downloaded, processed for IPs showing up more than 500 times. The 6th file is the current log file. No IPs were found that showed up more than 500 times, and the ACL was not changed.

If IPs were found that showed up more than 500 times (default $Threshold) in any of the logs, the script will update the VM ACL:

Az002

Example:

$RepeatEvery = 300 # seconds
$ScriptPath = 'E:\Install\Scripts\Azure\AZ-MonitorAndRepair.ps1'
$Params = @{
  SubscriptionName = 'SB01-Subscription'
  VMName = 'SB01'
  AdminName = 'Samb'
  PwdFile = 'd:\sandbox\Cred.txt'
  EndPointName = 'HTTP'
  URL = 'http://mysite.com'
  Verbose = $true
}
While ($true) { # Repeat until CTRL-C
  "Start at $(Get-Date)"
  $D = Measure-Command { & $ScriptPath @Params }
  "End at $(Get-Date)"
  " done in $($D.Minutes):$($D.Seconds) mm:ss, waiting for $RepeatEvery seconds"
  Start-Sleep -Seconds $RepeatEvery
}

In this example the script runs every 5 minutes and displays progress on the console screen.

Az003

Example:

$R = 300 # seconds
$ScriptPath = 'E:\Install\Scripts\Azure\AZ-MonitorAndRepair.ps1'
$ScriptLog = "D:\Docs\EG\Azure\Mitigate-DDOS_$(Get-Date -format yyyyMMdd).txt"
$Params = @{
 SubscriptionName = 'SB01-Subscription'
 VMName = 'SB01'
 AdminName = 'Samb'
 PwdFile = 'd:\sandbox\Cred.txt'
 EndPointName = 'HTTP'
 URL = 'http://mysite.com'
 Verbose = $true
}
While ($true) { # Repeat until CTRL-C
 "Start at $(Get-Date)" *>> $ScriptLog
 $D = Measure-Command { & $ScriptPath @Params *>> $ScriptLog }
 "End at $(Get-Date)" *>> $ScriptLog
 " done in $($D.Minutes):$($D.Seconds) mm:ss, waiting for $R seconds" *>> $ScriptLog
 Start-Sleep -Seconds $R
}

This is a similar example. The script runs every 5 minutes and logs all output to log file $ScriptLog

Example:

$ScriptPath = 'E:\Install\Scripts\Azure\AZ-MonitorAndRepair.ps1'
$ScriptLog = "D:\Docs\EG\Azure\Mitigate-DDOS_$(Get-Date -format yyyyMMdd).txt"
$Params = @{
 SubscriptionName = 'SB01-Subscription'
 VMName = 'SB01'
 AdminName = 'Samb'
 PwdFile = 'd:\sandbox\Cred.txt'
 EndPointName = 'HTTP'
 URL = 'http://mysite.com'
 Verbose = $true
}
"Start at $(Get-Date)" *>> $ScriptLog
$Duration = Measure-Command { & $ScriptPath @Params *>> $ScriptLog }
"End at $(Get-Date)" *>> $ScriptLog
" done in $($Duration.Minutes):$($Duration.Seconds) mm:ss" *>> $ScriptLog

This example runs once and logs all output to $ScriptLog file.
When saved as E:\Install\Scripts\Mitigate-DDOS4.ps1 for example, this short script can be scheduled to run every 5 minutes:

$a = New-JobTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Seconds 300) -RepetitionDuration ([TimeSpan]::MaxValue)
Register-ScheduledJob -Name DDOS4 -FilePath E:\Install\Scripts\Mitigate-DDOS4.ps1 -Trigger $a


Powershell function/tool to set/update Azure VM Endpoint Access Control List


One of the nice new features (2014) introduced is Access Control List (ACL) for Azure VM Endpoints. I think of it as a free virtual firewall for each Azure VM. This is a really nice feature because it can be managed and automated from Powershell. It’s also scoped to a single VM which is another nice design feature to minimize possible effects in case of error/mis-configuration.

See this page on How to Set Up Endpoints to a Virtual Machine.

The script can be downloaded from the Microsoft Script Center Repository.

To see a VM Endpoint ACL in Azure management interface:

Get-IPsFromLogs10

where you can view/edit rules in the VM Endpoint ACL manually.

Get-IPsFromLogs12

To get started with Azure Powershell see this post.

This Powershell cmdlet can also be used to show ACL rules (substitute the VM name and Endpoint name as needed of course):

Get-AzureAclConfig -EndpointName 'HTTP' -VM (Get-AzureVM | 
    where { $_.Name -eq 'EG01' }) | FT -Auto 

Get-IPsFromLogs11

The script uses as input an object with 2 properties: IP and Date. Date is used by the script to populate the Description of the rule.

A list of the IPs to block can be obtained from the Get-IPsFromLogs function/tool. This can be used with this function/tool to automate the process of obtaining a list of IPs where a DDOS attack is originating and configure the VM Endpoint ACL to block those IPs. Alternative, the same IP list can be used to configure the Azure VM Windows firewall to block those IPs. I prefer using the VM Endpoint ACL as opposed to the VM Windows firewall since the rule processing happens outside the VM. This offloads the VM processor and other precious resources.

Here’s an example script that puts the Get-IPsFromLogs and Set-AzACL tools together:

$IntakeFolder = "D:\Docs\EG\Intake"
$DoneFolder = "D:\Docs\EG\Done"
$SubscriptionName = "YourSubscription"
$VMName = "EG01"
$EndpointName = "HTTP"
$Threshold = 400
$BlockList = Get-IPsFromLogs -Logs (Get-ChildItem -Path $IntakeFolder).FullName `
-Threshold $Threshold -Verbose 
$BlockList | FT -AutoSize
try {
    $Error.Clear()
    Set-AzACL -IPList $BlockList -SubscriptionName $SubscriptionName `
    -VMName $VMName -EndPointName $EndpointName -Verbose -ErrorAction stop
    Get-ChildItem -Path $IntakeFolder | Move-Item -Destination $DoneFolder 
} catch {
    Write-Warning $Error[0]
}

The folder d:\docs\EG\Intake in this example starts with a group of log files from the C:\Windows\System32\LogFiles\HTTPERR folder.

Get-IPsFromLogs8

2 hours and 15 minutes later, the script found total 2 offending IPs:

Get-IPsFromLogs13One of them put out 11 million requests in under 10 hours.

Note: the last step of updating the ACL takes about 60 seconds, during which access to the VM is interrupted.

I ran the first 12 lines of the short controller script above on another group of log files – 613 of them, and got results like:

Get-IPsFromLogs14

To be cautious, I will only add the top 2 IPs to the ACL:

Set-AzACL -IPList ($BlockList |Select -First 2) -SubscriptionName $SubscriptionName -VMName $VMName -EndPointName $EndpointName -Verbose 

Get-IPsFromLogs15