FIRST – I am stealing code here and re-sharing (with very little modification). All credit goes the fine gentleman that wrote these two articles, I would urge you to read them:

Bulk Add IP Access Restrictions to Azure App Service Using AZ Powershell

Bulk Add Cloudflares IPs to Azure App Service Access Restrictions Using AZ Powershell

I made a few minor modifications the provided code. First, I like to just run a lot of my Azure Powershell stuff from an ISE session and don’t like encapsulating everything in new commands. Partly because I am not all that familiar with working that way even though it is probably a MUCH better way of doing things.

Before we get to the code though, what is this for exactly?

If you use cloudflare as a protection and CDN layer for a website it works by acting as a reverse proxy for your site. I.E. client connects to your site by a cloudflare hosted DNS record… instead of connecting directly to your server, their connection terminates at Cloudflare, they do things, then the pass the connection along to your actual service. ‘Nuff said, google if you need more info.

In the case of an Azure Web App (or any other web server I supposed), the app is hosted/available on some public IP and/or azure domain name that azure provides when you create the app…

What this means is that someone can easily bypass your cloudflare layer (and the associated performance enhancements and protections like web application firewalls) if they know your source systems IP address and in the case of azure, your azure provided domain name for your app.

So what that means is that you need to setup an ACL (Access Control List) on your source system to say “Allow traffic from all Cloudflare IP ranges and block everyone else”.

Cloudflare has like 20 IP ranges… And setting up that ACL by hand on a web app in Azure is arduous at best. But that is why we have scripting… to make things that are generally a pain in the rear… NOT a pain in the rear.

As a side note, you need the AZ powershell module installed for this to work and you know… credentials for Azure…

First open a powershell session and login to your account and select the subscription where your web app lives:

Connect-AzAccount
Select-AzSubscription -SubscriptionName Your_SubscriptionName_Here

Now without further ado, here is my modified code from the above links:

$AppServiceName = "##PUT_SERVICE_NAME_HERE##"
$ResourceGroupName = "##PUT_RESOURCE_GROUP_NAME_HERE##"
$RulePriority = "100"
$IPv6s = (Invoke-WebRequest -UseBasicParsing -Uri "https://www.cloudflare.com/ips-v6").Content.TrimEnd([Environment]::NewLine).Split([Environment]::NewLine);
$IPv4s = (Invoke-WebRequest -UseBasicParsing -Uri "https://www.cloudflare.com/ips-v4").Content.TrimEnd([Environment]::NewLine).Split([Environment]::NewLine);
$NewIpRestrictions = @();
foreach($IPv4 in $IPv4s){
    $NewIpRestrictions += @{
        ipAddress = $IPv4;
        action = "Allow";
        priority = $RulePriority;
        name = "CloudflareIPv4";
        description = "CloudflareIPv4";
        tag = "Default";
    }
}

foreach($IPv6 in $IPv6s){
    $NewIpRestrictions += @{
        ipAddress = $IPv6;
        action = "Allow";
        priority = $RulePriority;
        name = "CloudflareIPv6";
        description = "CloudflareIPv6";
        tag = "Default";
    }
}

$APIVersion = ((Get-AzResourceProvider -ProviderNamespace Microsoft.Web).ResourceTypes | Where-Object ResourceTypeName -eq sites).ApiVersions[0]
$WebAppConfig = Get-AzResource -ResourceName $AppServiceName -ResourceType Microsoft.Web/sites/config -ResourceGroupName $ResourceGroupName -ApiVersion $APIVersion
foreach ($NewIpRule in $NewIpRestrictions) {
    $WebAppConfig.Properties.ipSecurityRestrictions += $NewIpRule
}
Set-AzResource -ResourceId $WebAppConfig.ResourceId -Properties $WebAppConfig.Properties -ApiVersion $APIVersion

The only things I found “broken” (for me at least) from the original were the following:

I had to append the flag “-UseBasicParsing” on the IPv4 and IPv6 array generation command (it reaches out and gets the latest list of IP ranges from cloudflare) as Powershell was complaining about missing some Internet Explorer component. This flag fixes that.

Next, the forEach loop at the bottom references the wrong variable name for the array. The gent that wrote the articles above must have changed variable names from one article to the next without realizing. I have been guilty of the same. That is fixed above.

Okay… short and sweet, that’s it. Again, much laud the person that wrote most of the above. I’m just a beggar and thief for the most part.

1 of 1

2 comments on: Create Cloudflare ACL on Azure App Service

  1. Niels Swimberghe
    Reply

    Hi KiloRoot, good job on writing this 👍
    Thank you for linking my posts.

    • nbeam
      Reply

      Yeah man! – Your powershell write-up was EXACTLY what I was looking for and saved me a load of time in figuring it out for myself 🙂 – Anytime I come across something that specifically/personally useful on the web I write-it-up (I use my own blog for my work so I can journal fixes and things and not have to re-google the internet for everything 3 months later when I need the same solution again). – Thank you for writing and sharing your powershell!

Leave a Reply