Tag Archives : Bindings


Server Name Indication (SNI) – a journey

Today I went on an unusual journey, and it involved paying the price for configuring Microsoft’s web server (specifically, IIS 8.0 and 8.5) with scant regard for why it works the way it does.  Let me start at the beginning..

As of Internet Information Services (IIS) 8.0 (Windows Server 2012) and continuing in the latest version, 8.5 (Windows Server 2012 R2) there is now support for “Server Name Indication”, or SNI.  IIS allows you to set this value when configuring HTTPS site bindings on websites, as per below:

image

“Require Server Name Indication” or “make IIS support multiple SSL/TLS certificates” as I used to call it is a feature of IIS which allows you to bind different digital certificates to different websites within IIS using the same IP address.

Prior to IIS 8.0, you could only bind a single certificate to an individual IP address which you could only bind to one website, due to the way that handshaking worked at the time.  From Wikipedia:

Server Name Indication (SNI) is an extension to the TLS computer networking protocol[1] by which a client indicates which hostname it is attempting to connect to at the start of the handshaking process.

This allows a server to present multiple certificates on the same IP address and TCP port number and hence allows multiple secure (HTTPS) websites (or any other Service over TLS) to be served off the same IP address without requiring all those sites to use the same certificate. It is the conceptual equivalent to HTTP/1.1 name-based virtual hosting, but for HTTPS.

Now there’s a caveat with SNI, and one which I did not truly appreciate until today – some older “legacy” browsers, applications and libraries do not support SNI.

No support for SNI

The following combinations do not implement SNI (from Wikipedia again):

Client side
Server side
Libraries
  • Qt client side up to 4.7
  • Mozilla NSS server side
  • Java before 1.7
  • Python 2.x (except 2.7.9), 3.0, 3.1 (ssl, urllib[2] and httplib modules)

This begs the painful question..

What happens when something which does not support SNI tries to call a website or web service which relies on SNI – such as websites hosted within IIS?

Consider what happens when a client which supports SNI makes a request of IIS 8.0 or 8.5:

image

Because the site name indicator is supplied, IIS is able to locate the correct certificate for the named site and return it as part of the TLS handshake (prior to receiving HTTPS headers).  If no named site is found, it will resort to the default certificate/HTTPS binding if there is one – note: you should have a default certificate set!

Now, let’s compare that with what would happen when SNI is not supported by the client:

image
Note: this assumes the default website has the default https/443 bound to it.

Because the initial TLS handshake does not include the server name indicator (the name of the requested site) IIS will default to returning whatever’s bound by default.  This will likely not match the certificate expected!

Some symptoms of clients not supporting SNI:

  • Certificate mismatch (requested URI doesn’t match certificate common name) – default certificate is returned
  • Intended website has no requests logged (but HTTP requests are logged – assuming a http binding is also used!)
  • Intended request is logged against the default site instead of the intended site

One potential solution

If most of your sites use the same domain, you can assign a wildcard certificate to be the default for https/443 binding.  When the non-SNI request arrives, the wildcard will match and then the subsequent HTTPS headers will result in the correct website being accessed:

image

I’m not sure if the sites would have to use the same wildcard certificate or not – this is currently being tested.

Another option

..could be to place a network load balancing (NLB) appliance in front of your webserver, if it supports HTTPS/SSL/TLS offloading.  This way, traffic coming from the NLB would actually be HTTP, not HTTPS.  This is obviously far less secure as the HTTPS traffic would terminate on the load balancer, but it does solve the problem in theory.

Conclusion

Well that was a fun find.  The moral of the story is.. take time to understand why certain settings “make things work”, or else chances are you’ll find out the hard way.  I hope this article helped someone out there.


WCF Services with WSE 3.0 compatible bindings

Hi There,

So chances are if you’ve read my subsequent posts, you’ll get the feeling that I’m working with some legacy web service applications.  You’d be right, and the challenge of Web Service Extensions (WSE) 3.0 is figuring out how to upgrade them to WCF (.NET 3.5/4.0) without harming the legacy clients who consume them.  We’ll call it a 1-2 punch combination – update the services, then we can worry about the consuming applications.

However.. there are a few challenges.  As it turns out, you don’t need to wrap WCF services with a WSE web application as I first suspected.  This will work, but it gives you an extra set (of legacy) web services and you don’t really need an extra set of bindings and configuration which could cause you trouble down the stretch.

The solution is somewhat straightforward, in that WCF (in .NET 3.5/4.0) supports WSE 3.0 compatible bindings.  Trouble is, you have to use a custom binding, and it has a tendency to require a secure transport (out of the box) which can throw you.

Here’s what MSDN has to say about using a backwards compatible binding with WCF:

To enable a WCF service to interoperate with WSE 3.0 clients

Define a custom binding for the WCF service.

To specify that the August 2004 version of the WS-Addressing specification is used for message encoding, a custom binding must be created.

  1. Add a child customBinding Element to the <Bindings> of the service’s configuration file.
  2. Specify a name for the binding, by adding a binding element to the customBinding Element and setting the name attribute.
  3. Specify an authentication mode and the version of the WS-Security specifications that are used to secure messages that are compatible with WSE 3.0, by adding a child Security element to the binding element.
    To set the authentication mode, set the authenicationMode attribute of the Security element. An authentication mode is roughly equivalent to a turnkey security assertion in WSE 3.0. The following table maps authentication modes in WCF to turnkey security assertions in WSE 3.0.

    WCF Authentication Mode = WSE 3.0 turnkey security assertion

    AnonymousForCertificate  = anonymousForCertificateSecurity

    Kerberos = kerberosSecurity

    MutualCertificate = mutualCertificate10Security*

    MutualCertificate = mutualCertificate11Security*

    UserNameOverTransport = usernameOverTransportSecurity

    UserNameForCertificate = usernameForCertificateSecurity

    * One of the primary differences between the mutualCertificate10Security and mutualCertificate11Security turnkey security assertions is the version of the WS-Security specification that WSE uses to secure the SOAP messages. For mutualCertificate10Security, WS-Security 1.0 is used, whereas WS-Security 1.1 is used for mutualCertificate11Security. For WCF, the version of the WS-Security specification is specified in the messageSecurityVersion attribute of the Security element.

    To set the version of the WS-Security specification that is used to secure SOAP messages, set the messageSecurityVersion attribute of the Security element. To interoperate with WSE 3.0, set the value of the messageSecurityVersion attribute to WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10.

  4. Specify that the August 2004 version of the WS-Addressing specification is used by WCF by adding a textMessageEncoding element and set the messageVersion to its value to Soap11WSAddressingAugust2004.

    ms730049.note(en-us,VS.90).gifNote: When you are using SOAP 1.2, set the messageVersion attribute to Soap12WSAddressingAugust2004.

  1. Specify that the service uses the custom binding.

    1. Set the binding attribute of the Service Endpoint element to customBinding.
    2. Set the bindingConfiguration attribute of the Service Endpoint element to the value specified in the name attribute of the binding element for the custom binding.

Example:

The following code example specifies that the Service.HelloWorldService uses a custom binding to interoperate with WSE 3.0 clients. The custom binding specifies that the August 2004 version of the WS-Addressing and the WS-Security 1.1 set of specifications are used to encode the exchanged messages. The messages are secured using the AnonymousForCertificate authentication mode.

<configuration>
  <system.serviceModel>
    <services>
      <service 
        behaviorConfiguration="ServiceBehavior" 
        name="Service.HelloWorldService">
        <endpoint binding="customBinding" address=""
          bindingConfiguration="ServiceBinding"
          contract="Service.IHelloWorld"></endpoint>
      </service>
    </services>

    <bindings>
      <customBinding>
        <binding name="ServiceBinding">
          <security authenticationMode="AnonymousForCertificate"
                  messageProtectionOrder="SignBeforeEncrypt"
                  messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                  requireDerivedKeys="false">
          </security>
          <textMessageEncoding messageVersion ="Soap11WSAddressingAugust2004"></textMessageEncoding>
          <httpTransport/>
        </binding>
      </customBinding>
    </bindings>
    <behaviors>
      <behavior name="ServiceBehavior" returnUnknownExceptionsAsFaults="true">
        <serviceCredentials>
          <serviceCertificate findValue="CN=WCFQuickstartServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName"/>
        </serviceCredentials>
      </behavior>
    </behaviors>
  </system.serviceModel>
</configuration>

So after defining your WCF services, instead of using a basicBinding or a wsHttpBinding, all you need to do is define a customBinding, like the one below:

<!– WSE 3 compatible binding –>

      <!– http://msdn.microsoft.com/en-us/library/ms730049%28v=VS.90%29.aspx –>

     
      <customBinding>

        <binding name="customWseBinding"> 
         <security messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"

                    authenticationMode="UserNameOverTransport"

                    allowInsecureTransport="true">

          </security>

          <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />

         <httpTransport authenticationScheme="Anonymous" />          
        </binding>     
      </customBinding>

Now, assuming all your other settings are set correctly, you might get excited when the page.. almost.. loads:

image

However, what is this?

Error: Security policy export failed. The binding contains a TransportSecurityBindingElement but no transport binding element that implements ITransportTokenAssertionProvider. Policy export for such a binding is not supported. Make sure the transport binding element in the binding implements the ITransportTokenAssertionProvider interface. ----> System.InvalidOperationException: Security policy export failed. The binding contains a TransportSecurityBindingElement but no transport binding element that implements ITransportTokenAssertionProvider. Policy export for such a binding is not supported. Make sure the transport binding element in the binding implements the ITransportTokenAssertionProvider interface.

Not what we were expecting?  Basically, httpTransport doesn’t implement the ITransportTokenAssertionProvider which is what is being expected by the customBinding.  To work around this you have to, unfortunately, implement your own custom transport.  It’s nasty, but it works.

To take a look at the classes you’ll need, please read this article or this article.

After implementing the custom handler, the binding looks like this:

<customBinding>

        <binding name="customWseBinding">

          <security messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"

                    authenticationMode="UserNameOverTransport"

                    allowInsecureTransport="true">

          </security>

          <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />

          <!–<httpTransport authenticationScheme="Anonymous" />–>

          <CustomHttpTransport authenticationScheme="Anonymous" />

        </binding>     
      </customBinding>

Which results in the following screen:

image

 

References

How to: Configure WCF Services to Interoperate with WSE 3.0 Clients

http://msdn.microsoft.com/en-us/library/ms730049%28v=VS.90%29.aspx

http://social.msdn.microsoft.com/forums/en-US/wcf/thread/ea0ff7b6-12c4-487d-a983-c07e06260acf/


An update on a pending entry (WCF and EF POCO Objects) 2

Hi Everyone,

Well, I said I’d do it, and I will be – I’ve spent several hours putting together a sample DB and solution which demonstrates how to support Entity Framework (v4) POCO objects serialized in and out of WCF Services.

In a word, it’s going to be a lengthy article – maybe even several articles – as there are many things to address.  I was stuck on the last part of the scenario – sending objects back to be updated, but in the last 30 minutes I remembered what had to be done.

The sample solution will contain a test DB schema, a WCF Service project, a test client project (a console application) and some additional projects (class libraries) as well as an Entity Framework (v4) EDMX model which has been converted into POCO objects using the POCO Template Generator which you can install via Visual Studio 2010.

So now that the project is working in an end-to-end scenario, all I have to do is write up notes, capture some screenshots and also make notes of potential pitfalls and errors.  This is tricky stuff, but it is quite possible to accomplish.  Stay tuned, as the first post will be coming out this week!  If you want to be prepared in advance, I strongly suggest you have a play at generating POCO objects for your existing Entity Framework (v4) model.

Here’s a quick sample of things to come..

DB-Schema EDMX

  • This is a screenshot from SQL Management Studio’s SQL Diagrams, showing the raw schema
  • Next we have the EDMX (Entity Framework Entity Model) in all its glory

Poco-1 Poco-2

  • A screenshot of how to access the Code Generation template options from the EDMX designer
  • Next, we have a screenshot of the Online Templates – note the ADO.Net C# POCO Entity Generator is the first item

/R