WCF and SSL Processing Load Balancers

How to Configure WCF Service to Receive Unencrypted Credentials through F5 Networks’ BIG-IP and Similar Devices

11 Min Read
ITPro Today logo in a gray background | ITPro Today

RELATED: "Security for WCF" and "Going Mobile with WCF"

This month s column explores how to pass non-Windowscredentials through load-balancing devices that process SSL, such as F5Networks popular BIG-IP devices. For more information on load balancing, see "Load Balancing and Scaling Your WCF Services."

A common problem encountered when deploying WCF servicesis getting them to play nicely in a load-balanced environment that relies ondevices that process SSL requests and forward unencrypted requests to back-endservers. A popular implementation of this scenario involves F5 Networks BIG-IPload-balancing devices. As a follow up to last month s column when I talkedabout load-balancing issues with WCF, this article will focus solely onconfiguring your WCF clients and services to work well with SSL processingdevices.

 

The Problem Statement

Public-facing WCF services are often accessed over HTTPS,which means that SSL is relied on to protect message transfer. Without anintermediary, WCF clients and services simply agree on a suitable binding withthe appropriate credentials and transport security enabled. Figure 1 shows anexample where a WCF client sends messages using BasicHttpBinding with asecurity mode of TransportWithMessageCredential so the transport can protectmessage transfer while the message contains the actual credentials to beauthenticated.


Figure 1: SSL processing without anintermediary.

When an intermediary is introduced to process SSLencryption, such as a load-balancing device, messages are forwarded to theservice without SSL encryption. Figure 2 illustrates this scenario, where theclient establishes a secure point-to-point channel with the SSL load balancer.Presumably, this SSL load balancer is behind the firewall and messages are thenforwarded to the service intact, but without the SSL encryption. This meansthat the service must somehow configure a binding that can receive the desiredcredential without protection something that WCF explicitly disallows (inmost cases). The configuration shown in Figure 2, for example, would not besupported, because it asks for a UserName to be received in the message, butneither transport protection nor message protection with a service certificateare present.


Figure 2: SSL processing loadbalancers forwarding unencrypted messages over HTTP.

There are a few possible answers to this problem:

  • Send messages without credentials (of course, in that case you don t need to read this article).

  • The SSL processing load balancer can be configured to establish a new SSL session with the target service. This is not always easy to configure (depending on the load balancer); more importantly, it defeats the purpose of using an SSL load balancer to improve efficiency behind the firewall.

  • WCF services can be configured for basic authentication and receive credentials in the clear over HTTP. This can work; however, it precludes passing credentials in the message, and the use of more interesting credentials (such as issued tokens).

  • WCF services can be configured to fake the presence of transport security so that the runtime will allow receiving message credentials without transport or message protection.

I ll explain how to achieve the last two bulleted items inthe remainder of this article.

 

Basic Authentication

One way to pass credentials through an SSL load balancerto a WCF service is to use basic authentication. As shown in Figure 3, clientsestablish an SSL session with the load balancer and pass username and passwordcredentials encoded in the Authenticate HTTP header. The load balancer thenforwards the Authenticate HTTP header to the WCF service over an unsecured HTTPchannel.


Figure 3: Basic authenticationthrough an SSL load balancer.

The client uses BasicHttpBinding configured for Transportsecurity mode, and Basic credentials as shown here:

              

Set the proxy s UserName credentials to pass credentials:

MessageManagerServiceClient proxy =   new MessageManagerServiceClient("secureBasic");proxy.ClientCredentials.UserName.UserName = "username";proxy.ClientCredentials.UserName.Password= "password"; 

The result is that the proxy will initialize theAuthenticate HTTP header and send messages to the load balancer over a secureSSL channel. The load balancer is then responsible for forwarding the messageand the Authenticate HTTP header to the downstream service, after processingthe SSL encryption for a request.

The WCF service is configured for BasicHttpBinding withTransportCredentialOnly security mode and a credential type of Basic. Thissends the Authenticate HTTP header in the clear, but the assumption here isthat the SSL load balancers and WCF services are behind a firewall and that adecision has been made that this open communication can be trusted behind thisfirewall. The service configuration looks like this:

              

The same result cannot be directly achieved withWSHttpBinding, because it doesn t support TransportCredentialOnly.

 

Message Credentials

Other than the scenario just described, WCF specificallydisallows sending credentials over an unsecured channel. This poses a challengepassing message credentials through an SSL load balancer because it requiresforwarding messages unencrypted over HTTP. For example, the scenario shown inFigure 2 would not work because of the requirement to pass a UserNamecredential in the message over HTTP and without message security where themessage itself is encrypted with the service certificate. Although the figureshows BasicHttpBinding as the chosen binding, the same problem exists forWSHttpBinding and related bindings. Consider the service endpoint and bindingconfiguration shown in Figure 4.

               

Figure 4: Problemswith the service endpoint and binding configuration.

The address specified is HTTP; thus, when the ServiceHostis initialized for this service type, the following error will be thrown:

The provided URI scheme 'http' is invalid; expected 'https'.

Parameter name: context.ListenUriBaseAddress

Essentially, the runtime is expecting an HTTPS endpoint toprotect the UserName credential. The same problem will occur for anynon-Windows credential.

When an HTTP binding is configured for any form ofTransport security (Transport, TransportWithMessageCredential), the channelstack uses HttpsTransportBindingElement as the transport channel, as opposed toHttpTransportBindingElement. The security capabilities of the former includetransfer protection (encryption and signing) and server authentication. Thelatter doesn t have these security capabilities. Thus, even if you customizethe binding to use HttpTransportBindingElement, ServiceHost initialization willfail because the transport channel cannot provide signing and encryption.

For example, the code in Figure 5 initializesBasicHttpBinding for TransportWithMessageCredential and UserName credentials,initializes a CustomBinding to access the collection of channels, then swapsHttpsTransportBindingElement for HttpTransportBindingElement.

BasicHttpBinding basicBinding = new   BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);basicBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;CustomBinding customBinding = new CustomBinding(basicBinding);HttpsTransportBindingElement transport =   customBinding.Elements.Find();int index = customBinding.Elements.IndexOf(transport);customBinding.Elements.Remove();customBinding.Elements.Insert(index, new HttpTransportBindingElement());

Figure 5: InitializeBasicHttpBinding, initialize a CustomBinding; then swapHttpsTransportBindingElement for HttpTransportBindingElement.

When the ServiceHost is initialized, the following erroris presented:

The 'BasicHttpBinding'.'http://tempuri.org/' binding for the

   'IMessageManagerService'.'http://www.thatindigogirl.com/

 samples/2008/01' contractis configured with an

   authentication mode that requires transportlevel

   integrity and confidentiality. However thetransport

   cannot provide integrity and confidentiality.

There is an effective workaround for this to use HTTPtransport, but have that transport channel assert to the runtime (lie) that itcan provide transfer protection. This is done by supplying a customISecurityCapabilities implementation for the HTTP transport channel.

 

Asserting Security Capabilities

As mentioned, the WCF runtime expects a secure channel tobe present if non-Windows credentials are used for authentication. Thisprecludes using HTTP protocol unless you use a custom HTTP transport channelthat can lie to the runtime about its capabilities. All channels have theopportunity to report their security capabilities by returning an instance ofISecurityCapabilities when the channel s GetProperty method is called.

In this case, we want to supply a custom HttpTransportBindingElementthat can return security capabilities indicating transfer protection is present(even though it is not). The goal is to produce a binding configurationequivalent to BasicHttpBinding or WSHttpBinding receiving a non-Windowscredential, such as a UserName credential, without SSL encryption. The closestconfiguration to this is to configure a binding withTransportWithMessageCredential security mode, then replace theHttpsTranportBindingElement with a custom version of HttpTransportBindingElement.

The custom implementation of HttpTransportBindingElementmust return an instance of ISecurityCapabilities. In Figure 6, a CustomBindingbased on WSHttpBinding is modified to swap HttpsTransportBindingElement with acustom type, AssertEncryptionHttpBindingTransport. This type extendsHttpTransportBindingElement and overrides GetProperty to return acustom instance of ISecurityCapabilities, AssertEncryptionSecurityCapabilities.

WSHttpBinding wsHttpBinding = new   WSHttpBinding(SecurityMode.TransportWithMessageCredential);wsHttpBinding.Security.Message.ClientCredentialType =   MessageCredentialType.UserName;CustomBinding customBindingWS = new CustomBinding(wsHttpBinding);HttpsTransportBindingElement transportWS = customBindingWS.Elements.Find();int indexWS = customBindingWS.Elements.IndexOf(transportWS);customBindingWS.Elements.Remove();customBindingWS.Elements.Insert(indexWS, new   AssertEncryptionHttpTransportBindingElement());ServiceHost host = new   ServiceHost(typeof(MessageManager.MessageManagerService);host.AddServiceEndpoint(typeof(MessageManager.IMessageManagerService),   customBindingWS, "http://localhost:8000/MessageManagerService ");host.Open();

Figure 6: Exposingan HTTP endpoint that asserts SSL encryption through a custom binding.

The implementation ofAssertEncryptionHttpTransportBindingElement andAssertEncryptionSecurityCapabilities are shown in Figure 7.

public class AssertEncryptionHttpTransportBindingElement:   HttpTransportBindingElement{   public override BindingElement Clone()   {       return new AssertEncryptionHttpTransportBindingElement();   }   public override T GetProperty(BindingContext context)   {       if (typeof(T) == typeof(ISecurityCapabilities))       {           return (T)(object)new AssertEncryptionSecurityCapabilities();       }       return base.GetProperty(context);   }}public class AssertEncryptionSecurityCapabilities: ISecurityCapabilities{   #region ISecurityCapabilities Members   public ProtectionLevel SupportedRequestProtectionLevel   {       get { return ProtectionLevel.EncryptAndSign;  }   }   public ProtectionLevel SupportedResponseProtectionLevel   {       get { return ProtectionLevel.EncryptAndSign;  }   }   public bool SupportsClientAuthentication   {       get { return false; }   }   public bool SupportsClientWindowsIdentity   {       get { return false; }   }   public bool SupportsServerAuthentication    {       get { return true; }   }   #endregion}

Figure 7: Customimplementations of HttpTransportBindingElement and ISecurityCapabilities.

Although the scheme supported byAssertEncryptionHttpTransportBindingElement is HTTP (not HTTPS), AssertEncryptionSecurityCapabilitiesreturns ProtectionLevel.EncryptAndSign when the runtime asks for the supportedprotection level for requests and responses. In addition, server authenticationis asserted, although a service certificate is not present in this scenario. Becausethis custom ISecurityCapabilities implementation lies about its capabilities tothe runtime, the ServiceHost will allow you to configure an HTTP endpoint forthe UserName credential.

With this implementation, the UserName credential can bepassed securely to the SSL load balancer and forwarded to the service over HTTPin the clear.

Note: The samplecode illustrates this with a router service that processes the SSL request andforwards messages to the service over HTTP (see end of article for downloaddetails). Remember that this type of configuration should be carefullyconsidered as it bypasses standard security practices for passing credentials.

 

Addressing Concerns

In scenarios where messages are passed through anintermediary (in this case, the SSL load balancer) to the target service,WS-Addressing features may require your attention. BasicHttpBinding does notrely on WS-Addressing; however, WSHttpBinding and other HTTP bindings do.

There are a few possible scenarios to consider:

  • The client sends messages directly to load balancers.

  • The client sends messages to the service and is unaware of load balancers that will intercept the message.

  • The client sends messages directly to load balancers, but specify a logical address that matches the service.

If clients send messages directly to load balancers, theWS-Addressing To header will be set to that of the load balancer, not that ofthe service. The default behavior is for a proxy to initialize both the logicaladdress (the To header) and the physical address (where the message will besent) to the same value as the address attribute of the . Forexample, this client endpoint:

will result in sending messages to the same address as theTo header shown in Figure 8.

    https://localhost/BigIP/Service.svc/UserName   http://www.thatindigogirl.com/samples/2008/01/ IMessageManagerService/ SendMessage          test     

Figure 8: Sendingmessages to the same address as the To header.

By default, for the service to accept this message, the Toheader should match the physical address of the service:http://localhost/MessageManagerService. If not, an exception similar to thefollowing is thrown:

The message with To https://localhost/BigIP/Service.svc/ wsHttp cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check   that the sender and receiver s EndpointAddresses agree. 

To allow messages directed to the load balancers, theservice must either configure a different listen URI shown hereprogrammatically and declaratively by setting the address to match theexpected To header (the load balancer) and setting the listen URI property ofthe endpoint to match the physical address of the service:

host.AddServiceEndpoint(typeof(MessageManager. IMessageManagerService), customBindingWS,   "https://localhost/BigIP/Service.svc/wsHttp", new Uri("http://localhost:8000/MessageManagerService/wsHttp")); 

or disable address filtering, shown here applied as aservice behavior:

[ServiceBehavior(InstanceContextMode=InstanceContextMode. PerCall, AddressFilterMode=AddressFilterMode.Any)]public class MessageManagerService : IMessageManagerService

The former is preferable, because that at least ensures aknown To header.

If the client sends messages to the service, and thosemessages are intercepted by SSL load balancers, the To header will match theservice and no adjustments are necessary in the service configuration.

It also is possible for the client to send messages with aseparate logical and physical address. The To header is specified in theaddress property for the client endpoint, and the physical address wheremessages should be sent is specified in a client via behavior:

               

This is not the ideal situation, because the client shouldreally be unaware of the redirection, and be able to generate proxy andconfiguration directly from WSDL. Either of the first two options is commonlyimplemented.

 

Conclusion

Configuring services to receive credentials over unsecurechannels is not advisable under most circumstances. It is, however, a verypopular scenario to use SSL processing load balancers like BIG-IP to handle SSLdecryption and forward messages within a trusted environment. The entire pointis to optimize communications across the server farm. The approach I explainedin this article gives you a few ideas for handling the situation using basicauthentication or passing a non-Windows credential using message security.

The sample code also includes a mechanism forconfiguration of the custom binding discussed in this article, declaratively.This is done by creating custom binding elements, which I will explain in mynext column.

Download the samplesfor this article at http://www.dasblonde.net/downloads/aspprojan09.zip.

 

Read more about:

Microsoft
Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like