ARR: change the hostname on re-routing to backend node the requests

I
When re-routing the requests from clients to backend node(s) in a web farm, ARR is using by default the farm name as host header in the re-routed requests. But it can be configured to change that host-name, at a per-node level.

For example, let’s say that I have an IIS instance with Application Request Routing (named ARR) with two IIS instances working as backend processing nodes (named IIS-A and IIS-B). Requests are arriving at ARR node (at its IP address) as http://Public-HostName. But the sites on backend nodes are configured for hostname Internal-SiteName. So ARR should address the IIS-A/B nodes with http://Internal-SiteName, not with http://Public-HostName. How do I do that?







The illustrative setup




I’m creating a very simple web farm in ARR, adding IIS-A and IIS-B as nodes. Even if I configure IIS-A/B machine in the farm, ARR would connect to these machines by their IP addresses in the end, so we need to ensure that these names are DNS-resolvable.



640x415?v=1.png ARR web farm setup

The farm definition in applicationHost.config would end up like:



<configuration>
<webFarms onDemandHealthCheck="true">
<webFarm name="Public-HostName" enabled="true">
<server address="IIS-A" enabled="true" />
<server address="IIS-B" enabled="true" />
</webFarm>
</webFarms>
</configuration>



A corresponding URL Rewrite rule is being created. Since I have several farms defined on my ARR node, I am tweaking a bit the rule created by default, adding an {HTTP_HOST} condition:



large?v=1.png URL Rewrite rule for the farm

With this rule in place, it looks like this in the applicationHost.config:



<configuration>
<system.webServer>
<rewrite>
<globalRules>
<rule name="ARR_Public-HostName_loadbalance" enabled="true" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<conditions>
<add input="{HTTP_HOST}" pattern="Public-HostName" />
</conditions>
<action type="Rewrite" url="http://Public-HostName/{R:0}" />
</rule>
</globalRules>
</rewrite>
<proxy enabled="true" arrResponseHeader="true" />
</system.webServer>
</configuration>




The rule says something like this:

  • Whatever request comes at the IP of the ARR machine, meaning whatever URL (where URL means what’s coming after the site or server name in the browser’s address bar)…
  • If the request has the host header Public-HostName
  • Then re-route the request to the server farm Public-HostName

But wait! My nodes Internal-SiteName expect as hostname. If I change the URL Rewrite rule to re-route to “Internal-SiteName”, then the ARR farm would not be recognized. I could change the farm name to “Internal-SiteName” instead, but sometimes this is not possible or desired. Is there an alternative?







Change host name in ARR




When ARR is addressing the backend nodes, to get a response for the request, it could have the hostname changed. Instead of using the farm name as the host header when addressing IIS-A/B, it could use a custom hostname, which may be defined per-node.

There are 2 steps needed, both involving configuration settings that are hidden; meaning that they are not accessible via the ARR configuration UI. We would need to manually edit the applicationHost.config or better use Configuration Editor feature from IIS Manager.





ARR farm setting




Firstly, change the applicationRequestRouting > protocol settings for the server farm, setting the preserveHostHeader to False. This tells ARR to not enforce placing the farm name in the host header for requests it sends to IIS-A/B. To do that:



  1. Select the server node in the IIS Manager, then open the Configuration Editor feature.

641x356?v=1.png Configuration editor



  1. In the Section drop-down, select the webFarms setting. Then edit the farms collection by hitting the ellipsis “...” button.

641x355?v=1.png Edit collection of web farms



  1. In the list of defined web farms, select the server farm that is going to be configured.
  2. Then, expanding the applicationRequestRouting > protocol settings, set the preserveHostHeader to false.

640x780?v=1.png Select farm, change settings: preserveHostHeader under protocol, under applicationRequestRouting



  1. Don’t forget to hit Apply on the right side, after closing the Collection Editor window for server farms.

641x355?v=1.png Don't forget to save changes







Farm node(s) setting




Secondly, change the hostName of the farm node(s) that are placed in the ARR server farm. You need to do that for each of the farm nodes that has to be addressed with a hostname different than the farm’s name.



  1. Select the server node in the IIS Manager, then open the Configuration Editor feature.

641x355?v=1.png Configuration editor



  1. In the Section drop-down, select the webFarms setting. Then edit the farms collection by hitting the ellipsis “...” button.

641x355?v=1.png Edit server farms collection



  1. In the list of defined web farms, select the server farm that is going to be configured.
  2. Now click the ellipsis button “...” to edit the collection of nodes pertaining to the server farm selected:

641x500?v=1.png Edit nodes collection in the selected server farm



  1. For each of the nodes in the farm, select the node in the upper list, then in the lower pane expand applicationRequestRouting and set the custom hostName setting:

640x692?v=1.png Change hostName for the selected farm node, under applicationRequestRouting



  1. Don’t forget to hit Apply on the right side, after closing the Collection Editor windows for server farms and farm nodes collections.

641x355?v=1.png Don't forget to save changes



With that, if the Public-HostName is resolvable to the IP address of the ARR machine, then we can access the site from a client.



641x216?v=1.png Test the site, the internal routing changing the host header



For reference, the farm definition in the applicationHost.config now looks like this:



<configuration>
<webFarms onDemandHealthCheck="true">
<webFarm name="Public-HostName" enabled="true">
<server address="IIS-A" enabled="true">
<applicationRequestRouting hostName="Internal-SiteName" />
</server>
<server address="IIS-B" enabled="true">
<applicationRequestRouting hostName="Internal-SiteName" />
</server>
<applicationRequestRouting>
<protocol preserveHostHeader="false" />
</applicationRequestRouting>
</webFarm>
</webFarms>
</configuration>



All the best!

Continue reading...
 
Top Bottom