Configuring IIS ARR for Lync/Exchange with Powershell

Many times I’ve needed to configure IIS ARR as the reverse proxy for Lync, Exchange and related services. To speedup the  process I’ve created this powershell script.

It’s a basic script, and as such can be enhanced, but it does what It’s most commonly needed.

These are the assumptions:

  • IIS ARR is already up and running Smile
  • Each service will be balanced based on the URL
  • Each service will use a different URL
  • Timeout settings will be configured using the most demanding one as the base for all services

For simplicity I have created a PowerShell function that will create the IIS ARR web farm for me and then call it for each WebFarm I need.

First some paperwork :

DISCLAIMER: All information on these pages is provided “as -is”, without any warranty, whether express or implied, of its accuracy, completeness, fitness for a particular purpose, title or non-infringement, and none of the third-party products or information mentioned in the work are authored, recommended, supported or guaranteed by the Author. Further, I shall not be liable for any damages you may sustain by using this information, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such damages.

Now the fun begin Smile.

The function accepts these parameters:

  • serverFarmPrefix –> It is the prefix that will be used to distinguish the webfarm
  • serverList –> It is the list of servers that offer this service
  • url2Balance –> It is the url to be used to route the traffic to the right servers
  • skipPlain –> It is a switch used to avoid creating the rules for the plain traffic (no SSL)
  • pPort –> It is the port of the server that is offering the service in clear
  • sPort –> It is the port of the server that is offering the service securely
Function New-WebFarm(){
[Parameter(mandatory=$True)][String]$serverFarmPrefix = "WebFarm",
[Parameter(mandatory=$True)]$serverList = @("server1.icubed.lab","server2.icubed.lab"),
[Parameter(mandatory=$True)][String]$url2Balance = "*",
[Parameter(mandatory=$False)][Switch]$skipPlain = $false,
[Parameter(mandatory=$False)][int]$pPort = 80,
[Parameter(mandatory=$False)][int]$sPort = 443

The function will then create the server farm

##Server Farms
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "webFarms" -name "." -value @{name="$serverFarmPrefix"}
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "webFarms/webFarm[@name='$serverFarmPrefix']/applicationRequestRouting/protocol" -name "timeout" -value "00:03:20"
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "webFarms/webFarm[@name='$serverFarmPrefix']/applicationRequestRouting/protocol/cache" -name "enabled" -value "False"

As stated the timeout values are those of the most demanding service (mobility) which is 200 seconds. After that, will add the servers to the farms, using the specified port (in any) or the defaults (80 and 443)

#Add Servers
 ForEach ($serverName in $serverList){
 Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "webFarms/webFarm[@name='$serverFarmPrefix']" -name "." -value @{address="$serverName"}
 Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "webFarms/webFarm[@name='$serverFarmPrefix']/server[@address='$serverName']/applicationRequestRouting" -name "httpPort" -value $pPort
 Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "webFarms/webFarm[@name='$serverFarmPrefix']/server[@address='$serverName']/applicationRequestRouting" -name "httpsPort" -value $sPort

At last, it will create the Rewrite rules:

if (!($skipPlain)){
 Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules" -name "." -value @{name="$ruleName";patternSyntax='Wildcard';stopProcessing='True'}
 Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleName']/match" -name "url" -value "*"
 Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleName']/conditions" -name "." -value @{input='{HTTP_HOST}';pattern="$url2Balance"}
 Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleName']/action" -name "type" -value "Rewrite"
 Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleName']/action" -name "url" -value "http://$serverFarmPrefix/{R:0}"
 Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules" -name "." -value @{name="$ruleNameSSL";patternSyntax='Wildcard';stopProcessing='True'}
 Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleNameSSL']/match" -name "url" -value "*"
 Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleNameSSL']/conditions" -name "." -value @{input='{HTTPS}';pattern='on'}
 Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleNameSSL']/conditions" -name "." -value @{input='{HTTP_HOST}';pattern="$url2Balance"}
 Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleNameSSL']/action" -name "type" -value "Rewrite"
 Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/rewrite/globalRules/rule[@name='$ruleNameSSL']/action" -name "url" -value "https://$serverFarmPrefix/{R:0}"

If –skipPlain is specified, the rules for the clear traffic are not created.

Once I have my function defined, I can call it as my times I need.

First I’ll define the parameters for my farms:

##Join simple URL webfarm
$joinFarm = "Join"
$joinServerList = "server1.adds.icubed.lab","server2.adds.icubed.lab","server3.adds.icubelab"
$joinURL = "join.*"
$joinSPort = 443
##Exchange web services webfarm
$exchFarm = "Exchange"
$exchServerList = "server6.adds.icubed.lab","server7.adds.icubed.lab"
$exchURL = "outlook.*"
$exchSPort = 443
##Lyncdiscover simple URL webfarm
$lyncDiscFarm = "LyncDiscover"
$lyncDiscServerList = "server1.adds.icubed.lab","server2.adds.icubed.lab","server3.adds.icubed.lab"
$lyncDiscURL = "lyncdiscover.*"
$lyncDiscPPort = 8080
$lyncDiscSPort = 4443
##Office Webapps webfarm
$webAppsFarm = "Webapps"
$webAppsServerList = "server3.adds.icubed.lab","server5.adds.icubed.lab"
$webAppsURL = "webapps.*"
$webAppsSPort = 443
##Skype/Lync Pool External webservices webfarm
$extWSFarm = "ExternalWS"
$extWSServerList = "server1.adds.icubed.lab","server2.adds.icubed.lab","server3.adds.icubed.lab"
$extWSURL = "skypews.*"
$extWSSPort = 4443

After that I’ll call the function for each of them:

New-WebFarm -serverFarmPrefix $joinFarm -serverList $joinServerList -url2Balance $joinURL -sPort $joinSPort -skipPlain
New-WebFarm -serverFarmPrefix $exchFarm -serverList $exchServerList -url2Balance $exchURL -sPort $exchSPort -skipPlain
New-WebFarm -serverFarmPrefix $lyncDiscFarm -serverList $lyncDiscServerList -url2Balance $lyncDiscURL -sPort $lyncDiscSPort -pPort $lyncDiscPPort
New-WebFarm -serverFarmPrefix $webAppsFarm -serverList $webAppsServerList -url2Balance $webAppsURL -sPort $webAppsURL -skipPlain
New-WebFarm -serverFarmPrefix $extWSFarm -serverList $exchServerList -url2Balance $extWSURL -sPort $extWSURL -skipPlain

And this is the net result:




As stated this is the first release of this script and as such there’s a lot of space for improvement.

However I think it can help you in configuring things quickly.

Here is the complete script:

IIS-ARR Setup (7.4 KiB, 174 downloads)

I’ll keep you posted!


Leave a Reply