8

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)

Mike G
  • 283
  • 1
  • 4
  • 11

4 Answers4

3

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.

Mike G
  • 283
  • 1
  • 4
  • 11
1

I realise this a very old question, but I've come across this issue recently, and solved it using steps provided here:

https://blog.tonysneed.com/2012/06/18/building-scalable-and-secure-wcf-services/

As one of the other responses here state, it requires subclassing HttpTransportElement and its BindingElementType, so that it returns a ISecurityCapabilities that "fools WCF" into thinking the connection is secure. You can then use this tranport element in a customBinding.

velsietis
  • 11
  • 1
  • Thanks for this blog post. I'll have to try this out. Since it is an "old" question I don't have a scenario where I can test it out. When this was applicable we just offloaded our external SSL cert at the load balancer and then use an internally issued SSL cert to go from the load balancer to the endpoint. – Mike G Apr 17 '18 at 13:05
0

Setting Security Mode to None on the basicHttpBinding allows the WCF web services to receive non-SSL traffic.

<bindings>
    <basicHttpBinding>
        <binding>
            <security mode="None"></security>
        </binding>
    </basicHttpBinding>
</bindings>
ShootTheCore
  • 101
  • 1
0

We ran into the same issue and went with a solution provided by a developer at Microsoft. That solution is to create a custom HttpTransport that overrides the requirement to have SSL from the load balancer to the server.

Jason Berg
  • 18,954
  • 6
  • 38
  • 55