Howto WCF Service HTTPS Binding and Endpoint Configuration in IIS with Load Balancer

httpsiis-7load balancingwcf

We have a WCF service that is being hosted on a set of 12 machines. There is a load balancer that is a gateway to these machines.

Now the site is setup as SSL; as in a user accesses it through using an URL with https. I know this much, the URL that addresses the site is https, but none of the servers has a https binding or is setup to require SSL. This leads me to believe that the load balancer handles the https and the connection from the balancer to the servers are unencrypted (this takes place behind the firewall so no biggie there).

The problem we're having is that when a Silverlight client tries to access a WCF service it is getting a "Not Found" error. I've set up a test site along with our developer machines and have made sure that the bindings and endpoints in the web.config work with the client. It seems to be the case in the production environment that we get this error.

Is there anything wrong with the following web.config? Should we be setting up how https is handled in a different manner?

We're at a loss on this currently since I've tried every programmatic solution with endpoints and bindings. None of the solutions I have found deal with a load balancer in the manner we're dealing.

Web.config service model info:

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="TradePMR.OMS.Framework.Services.CRM.CRMServiceBehavior">
          <serviceMetadata httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
        <behavior name="TradePMR.OMS.Framework.Services.AccountAggregation.AccountAggregationBehavior">
          <serviceMetadata httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>          
      <customBinding>    
        <binding name="SecureCRMCustomBinding">
          <binaryMessageEncoding />
          <httpsTransport />
        </binding>

        <binding name="SecureAACustomBinding">
          <binaryMessageEncoding />
          <httpsTransport />
        </binding>
      </customBinding>
      <mexHttpsBinding>
        <binding name="SecureMex" />
      </mexHttpsBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

    <!--Defines the services to be used in the application-->
    <services>
      <service behaviorConfiguration="TradePMR.OMS.Framework.Services.CRM.CRMServiceBehavior"
        name="TradePMR.OMS.Framework.Services.CRM.CRMService">

        <endpoint address="" binding="customBinding" bindingConfiguration="SecureCRMCustomBinding"
          contract="TradePMR.OMS.Framework.Services.CRM.CRMService" name="SecureCRMEndpoint" />

        <!--This is required in order to be able to use the "Update Service Reference" in the Silverlight application-->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>

      <service behaviorConfiguration="TradePMR.OMS.Framework.Services.AccountAggregation.AccountAggregationBehavior"
        name="TradePMR.OMS.Framework.Services.AccountAggregation.AccountAggregation">

        <endpoint address="" binding="customBinding" bindingConfiguration="SecureAACustomBinding"
          contract="TradePMR.OMS.Framework.Services.AccountAggregation.AccountAggregation" name="SecureAAEndpoint" />

        <!--This is required in order to be able to use the "Update Service Reference" in the Silverlight application-->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

The ServiceReferences.ClientConfig looks like this:

<configuration>
    <system.serviceModel>
        <bindings>
            <customBinding>
                <binding name="StandardAAEndpoint">
                    <binaryMessageEncoding />
                    <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
                <binding name="SecureAAEndpoint">
                    <binaryMessageEncoding />
                    <httpsTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
                <binding name="StandardCRMEndpoint">
                    <binaryMessageEncoding />
                    <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
                <binding name="SecureCRMEndpoint">
                    <binaryMessageEncoding />
                    <httpsTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                </binding>
            </customBinding>
        </bindings>
        <client>
            <endpoint address="https://Service2.svc"
                binding="customBinding" bindingConfiguration="SecureAAEndpoint"
                contract="AccountAggregationService.AccountAggregation" name="SecureAAEndpoint" />
            <endpoint address="https://Service1.svc"
                binding="customBinding" bindingConfiguration="SecureCRMEndpoint"
                contract="CRMService.CRMService" name="SecureCRMEndpoint" />
        </client>
    </system.serviceModel>
</configuration>

(The addresses are of no consequence since those are dynamically built so that they will point to a dev's machine or to the production server)

Best Answer

I'm answering this as I've been asked by a few people who know that the app is in production, but didn't see an answer here.

We couldn't solve this in the above scenario. HTTPS from the client to the load balancer is OK. The problem is when the load balancer takes that connection and points it to a web server in an unencrypted format. This seemingly breaks the WCF protocol. The client is sending HTTPS communications but the server is getting unencrypted communication.

We solved the issue by passing through all SSL communications.

The best "solution" would be to see if your WCF service was not using the HTTP method of transmission and setting up your load balancer to pass these communications through unaltered. The load balancer could then do its standard operating procedure on regular HTTPS traffic generated from the website.

I haven't tested this as our application scenario requires the WCF service to be compatible with ASP.NET.

Hopefully someone else can elaborate on this with some more information.

Related Topic