Installing IIS Dynamic IP Restrictions in an Azure Web Role (PAAS)

 

A Denial-Of-Service (DOS) attack can target any application/tenant should it be hosted in Windows Azure or hosted by an ISP. If you are using Azure Web Sites or IIS in a VM (IAAS), a simple way to mitigate such attack would be to enable Dynamic IP Restrictions as described in many blog articles:

Configuring Dynamic IP Address Restrictions in Windows Azure Web Sites
IIS 8.0 Dynamic IP Address Restrictions
Using Dynamic IP Restrictions (documentation for IIS7/7.5)

The following steps described how to install Dynamic IP Restrictions in a Cloud Service/Web Role using a startup task on any OS Family (1-4):

  1. Edit ServiceDefinition.csdef for your Cloud Service and declare a startup task :

    <Startup>
    <Task commandLine="startup\startup.cmd" executionContext="elevated">
    <Environment>
    <Variable name="EMULATED">
    <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
    </Variable>
    </Environment>
    </Task>
    </Startup>

  2. Since the "Dynamic IP Restrictions" is part of IIS8/8.5 but was shipped as an out of band module in IIS 7/7.5, the startup task needs to use different installation methods depending on the OS Family used. Create the following startup.cmd file:

    @echo Emulated is: %EMULATED%
    if "%EMULATED%"=="true" goto EOF
    echo **** check for Windows 2008 or 2008 R2 >> log.txt
    ver | findstr /i "6\.0\." > nul
    if %errorlevel% equ 0 goto ver_Win2008
    ver | findstr /i "6\.1\." > nul
    if %errorlevel% equ 0 goto ver_Win2008
    echo **** using DISM to enable IIS-IPSecurity (Windows 2012 and above) >> log.txt
    %windir%\system32\dism.exe /online /quiet /enable-feature /featurename:IIS-IPSecurity >> log.txt
    goto config
    : ver_Win2008
    echo **** using WEBPI to install DynamicIPRestrictionsRTW (Windows 2008 or 2008 R2) >> log.txt
    %~dp0webpicmdline /AcceptEula /Products:DynamicIPRestrictionsRTW >> log.txt
    :config
    %windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/security/dynamicIpSecurity /denyByConcurrentRequests.enabled:"True" /denyByConcurrentRequests.maxConcurrentRequests:"30" /denyByRequestRate.enabled:"True" /denyByRequestRate.maxRequests:"30" /denyByRequestRate.requestIntervalInMilliseconds:"5000" /commit:apphost >> log.txt
    :EOF
    exit /b 0

  3. Create a startup folder in your WebRole project and copy the startup.cmd into it

  4. Download the WEBPI binaries from https://go.microsoft.com/?linkid=9752821 and unzip the contents to the startup folder created above. Your Visual Studio project should look like this:

  5. Right click on all the files on the startup folder, change each of file properties for the files in the project from their default value ("Copy to Output Directory") to "Copy Always" :

  6. Build and publish your cloud service – I would suggest to publish on staging environment so that you can confirm everything is fine

  7. To check that Dynamic IP Restrictions are enabled, RPD to one instance and use IIS Management tool. Note that, starting with Windows 2012/IIS8, Dynamic IP Restrictions are part of "IP Address and Domain Restrictions".

    [Windows 2008/IIS7 & 2008 R2/IIS7.5]

    [Windows 2012/IIS8 & 2012 R2/IIS8.5]

                    If Dynamic IP Restrictions are not enabled, check the content of log.txt file (dir E:\approot\*.log.txt)

  8. Test that Dynamic IP Restrictions are in effect using the following procedure :

    Download URLSTRESS from https://blogs.msdn.com/b/friis/archive/2010/12/28/urlstress-a-simple-gui-tool-with-source-code-to-stress-your-favorite-web-server.aspx and configure it to request you web site URL. The tool will allow to "flood" your role with HTTP requests and Dynamic IP Restrictions should start rejecting requests based on Dynamic IP Restrictions configuration. In the following screenshot, the tool is configured for a single thread constantly requesting the root URL of my web role (https://cswebrolewithdip.cloudapp.net/):

     

    If you connect on you web role using Internet Explorer, you may get this error during the time where your IP is "blacklisted" :

 

Additional notes:

  • The Dynamic IP Restrictions settings are set in the following startup.cmd/appcmd command line:

    %windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/security/dynamicIpSecurity /denyByConcurrentRequests.enabled:"True" /denyByConcurrentRequests.maxConcurrentRequests:"30" /denyByRequestRate.enabled:"True" /denyByRequestRate.maxRequests:"30" /denyByRequestRate.requestIntervalInMilliseconds:"5000" /commit:apphost >> log.txt

  • The command sets the following config section in applicationhost.config :

    <dynamicIpSecurity>
    <denyByConcurrentRequests enabled="true" maxConcurrentRequests="30" />
    <denyByRequestRate enabled="true" maxRequests="30" requestIntervalInMilliseconds="5000" />
    </dynamicIpSecurity>

  • The above settings are more conservative than the ones used in most articles (Configuring Dynamic IP Address Restrictions in Windows Azure Web Sites). However, even the use of these settings may cause some problems if your web site is accessed through a proxy by a large amount of customers. If you face proxy related issues, you can have a look at this article: https://blogs.iis.net/wadeh/archive/2012/08/01/dynamic-ip-restriction-proxy-mode.aspx

  • If you want to allow/deny static IP address/ranges, you may integrate the appropriate command(s) in the startup task using similar technique as described in the following articles :

    Block Specific IP Addresses from Accessing a Web Role
    How to restrict unwanted IPs to access your site in Azure environment

    For example, if you want to deny access to IP '94.245.87.167' from our startup task, we can simply add the lines in bold to the startup task:

    @echo Emulated is: %EMULATED%
    if "%EMULATED%"=="true" goto EOF
    echo **** check for Windows 2008 or 2008 R2 >ver | findstr /i "6\.0\." > nul
    if %errorlevel% equ 0 goto ver_Win2008
    ver | findstr /i "6\.1\." > nul
    if %errorlevel% equ 0 goto ver_Win2008
    echo **** using DISM to enable IIS-IPSecurity (Windows 2012 and above) >> log.txt
    %windir%\system32\dism.exe /online /quiet /enable-feature /featurename:IIS-IPSecurity >> log.txt
    goto config
    : ver_Win2008
    echo **** using WEBPI to install DynamicIPRestrictionsRTW (Windows 2008 or 2008 R2) >> log.txt
    %~dp0webpicmdline /AcceptEula /Products:DynamicIPRestrictionsRTW >> log.txt
    echo **** using WEBPI to install IpSecurity >> log.txt
    %~dp0webpicmdline /AcceptEula /Products: IPSecurity>> log.txt

    :config
    %windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/security/dynamicIpSecurity /denyByConcurrentRequests.enabled:"True" /denyByConcurrentRequests.maxConcurrentRequests:"30" /denyByRequestRate.enabled:"True" /denyByRequestRate.maxRequests:"30" /denyByRequestRate.requestIntervalInMilliseconds:"5000" /commit:apphost >> log.txt
    echo **** deny access to IP 94.245.87.167 >> log.txt
    %windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/security/ipSecurity /+"[ipaddress='94.245.87.167',allowed='false']" /commit:apphost >> log.txt

    :EOFexit /b 0

I hope you've enjoyed this article as much as I enjoyed writing it & Thanks,

Emmanuel Boersma
Cloud Integration Engineer

Comments

  • Anonymous
    March 08, 2014
    Works like a charm :) Thanks for that. There is only one caveat - the task tag should wrap the Environment tag.

  • Anonymous
    March 10, 2014
    Thanks for the feedback Ilija! I've fixed the task tag issue. Emmanuel