WCF Multiple host headers IIS7 in a DMZ with NAT

Abstract

After some investigations I have come to the following conclusion. You can not host a WCF service in IIS7, .NET 3.5, where the host site uses multiple host headers and have the service respond to more than one of those host headers.

Scenario

IIS is in a DMZ with one internal IP address. It can also be accessed from the internet via a public different IP address that goes through Network Address Translation at the firewall. Thus effectively the site has one IP address but two possible host headers to respond to.

Configuration

In order to get the WSDL to correctly insert the IP address of the server, rather than the server machine name. Two entries were made into the site bindings, with separate host headers (IP address as host header as we have no domain name set up for this server) for each.

This creates an error from the service that you will find many reference to by searching the Internet.

This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.

This is because WCF only supports one base address for each protocol, but IIS can support multiple. This is summarised nicely here: Ram Poornalingam's WebLog

If you don’t configure up both IIS bindings in the WCF configuration you get the following message as WCF does not know what to do.

No protocol binding matches the given address [blah blah blah] Protocol bindings are configured at the Site level in IIS or WAS configuration

WcfException

I set the host header as the IP address of the site as the WSDL was reporting localhost as the address of the server without it.

[more]

Others suffering too

Looking for the solution it seemed there are a few issues around having sites hosting WCF services where the site has more than one face. This might be due to load balancing where sites www1.yourdomain.com and www2.yourdomain.com point to same site, or multi faced hosting solutions or simpler scenarios like mine.

Pre .NET 3.5

Before .NET 3.5 a custom ServiceHostFactory class can be created to force feed a particular site id to the service. This works for some people but not for our senario for the same reasons to why the .NET 3.5 solution does not work for us.

WCF .NET 3.5

With .NET 3.5 an aspect of this problem was addressed, that for many seems to have solved the problem. This is the introduction of the following configuration elements.

For sites;
http://testl.fabrikam.com/Service.svc
http://test2.fabrikam.com/Service.svc

<system.serviceModel>




  <serviceHostingEnvironment>




     <baseAddressPrefixFilters>




        <add prefix=”net.tcp://test1.fabrikam.com:8000”/>




        <add prefix=”http://test2.fabrikam.com:9000”/>




    baseAddressPrefixFilters>




  serviceHostingEnvironment>




system.serviceModel>

Because a WCF service hosted under a site allows binding to only one base address for each scheme, you can use the prefix filter feature to pick the required base address of the hosted service

This is great if you just want one of the host header calls to work. You could use redirects via IIS rewriter or just ensure the service is always called under the correct host header. Most people seem to be able to work with this from what I read on the various blogs and forums. For our scenario this is no good, as both host headers must be able to respond, our DMZ does not know of the internet and the Internet cant redirect to a hidden internal IP address if the caller is outside the organisation. Some Internet posts speak about using redirects successfully in load balancing situations.

Living with it

We have to live with this constraint, so as it happens it lead me to rethink what I was doing and create another IIS site, and a copy of the service in both. It actually is good for me to have one site (external facing) as a test service and the other configured to work on live data.

I could have done this if both needed to be identical services too, but most people object as do I to the overhead of maintaining multiple sites and configurations to achieve what we want.

Some of many References:

WCF in IIS with Websites that have Multiple Identities

Load balancing error with WCF service - NLB

How can WCF support multiple IIS Binding specified per site ?

Configuring WCF and IIS 7 With HTTP Bindings and Multiple Host Headers

@ MSDN