WCF: Life behind SSL Offloader

WCF: Exposing and consuming WCF service behind SSL Off loader

Capture

 

 

 

 

 

Problem Statement: Service external address looks correct over HTTPS, however metadata location points to Http end point.

  1. Host headers getting corrected with the use of <useRequestHeadersForMetadataAddress/>, no machine name. but the metadata location on service page is pointing to Http.
  2. Because of this, clients are not able to get the metadata.

 

Example:

Service in question: https://xyz.com/TestServices/Service.svc

WSDL Address on service main page:

svcutil.exe https://xyz.com/TestServices/Service.svc?wsdl

 

Internal end point address in WSDL (point to Http):

https://xyz.com/TestServices/Servicesa.svc

 

Solution part 1:

To correct the internal service address and get it over https:

  • We add a “logicalAddress” attribute to service end point using “HTTPS”.
  • Add “ListenURI” attribute to service end point using “HTTP” Address.
  • Update the useRequestHeaderForMetaDataAddress and added the specific port (54888) – if not using default port.

With this we can get the service up and running with Https END point. Able to use the SingleWSDL link to get the relevant meta data location.

However still on main service page, we see svcutil.exe https://    and not svcutil.exe https://  But internally address is correct.

 

Nested problem 1:

One more error, which may see with the setting is – 404 error – no service end point listening. To resolve the 404 error, we need to use “AddressFilterMode” attribute at service class.

 

Reason being:

Request coming via LB will have two addresses:

  1. Via (Physical Address)
  2. To (Logical Address)

 

To get the service end point over HTTPS in WSDL document we added “via” attribute to HTTP and “To” attribute to HTTPS.

When doing load balancing ideally only “via” attribute is changed from HTTPS to HTTP. Some load balancer may even set the “To” attribute to HTTP, and as a result service won’t be able to handle the request.

Below setting will help us handle these request from LB.

[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]

public class Service1 : IService1

 

Nested Problem 2:

We got the service WSDL over HTTPS, but we may observe that the internal meta data (XSD) location points to Http. Because of this if we try to use the default WSDL end point, we still fail to add reference.

 

However, we can use the SingleWSDL link added in framework 4.5 to address the same issue.

https://blogs.msdn.com/b/piyushjo/archive/2011/10/05/what-s-new-in-wcf-4-5-flat-wsdl-support.aspx

 

More questions:

  1. Is there a way we can force service main page to show Https endpoint?
    1. Only one way – ExternalMetaDataLocation
  2. Is there a way to disable default wsdl link and only use singlewsdl?
    1. Not possible.

 

Solution part 2:

  1. To disable the normal WSDL link, we need to set ExternalMetadataLocation
  2. To use externalMetaDataLocation, we can copy the WSDL file which gets created when we add a service reference to single WSDL file in any client project.
  3. Next we copy this WSDL file to server at same location where we have Service.svc file.
  4. Once done, we can set the metadata location to point to this WSDL file and client will only see this location.

 

I placed service1. wsdl file at same level as SVC file. Capture

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

This file is copied from client project – when I add reference to Single WSDL.

Capture

 

 

 

 

 

 

 

 

 

Once done, all we have to do is set ExternalMetaDataLocation WSDL file: Capture

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

With this when we browse the service, we only see the location set to get MetaData and is the only way to override the MetaData location manually. Capture

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Only problem with this approach is, when you have new schema or WSDL created, you need to disable external Metadata location in build environment and use SingleWSDL to get correct WSDL with schema generated.

Once you get new WSDL in sample client project, simple put the WSDL on server and rest all will continue to work fine.

It’s like you have to push WSDL file (if any changes done in structure) along with binaries… that’s it.

 

To create Flat WSDL in framework 4.0 even for “?WSDL” link…

We can use below blog, but to change the WSDL Address from Http to Https, we need to use External Meta Data Location tag.

https://blogs.msdn.com/b/saurabs/archive/2015/04/13/wcf-concept-of-flat-wsdl.aspx

On top of that, it still exposes the “?SingleWSDL” link..

 

Solution part 3:

Using IIS Re-write module to redirect the request for “?wsd” to “singlewsdl”.

Steps to get and use URL re-write module:

  1. URL Re-write X64 : https://go.microsoft.com/fwlink/?LinkID=615137
  2. URL Re-write X86 : https://go.microsoft.com/fwlink/?LinkID=615138
  3. One you install it on IIS server, follow below steps to add a new Rewrite rule.

 Capture

 

 

 

 

 

 

 

 

 

 

 

 

Click on – View Rewrite maps:

Capture

 

 

Add new Re-write Map

Capture

 

 

 

 

Give a name:

Capture

 

 

 

 

Select Add Mapping Entry:

Capture

 

 

 

 

 

Add Mapping, like this

Capture

 

 

 

 

 

 

Now go back to Rule window and add new re-write rule:

Capture

 

 

 

 

 

 

 

 

 

Select rule, we created:

Capture

 

 

 

 

 

 

 

 

Once added, it should rewrite all request to WSDL to SINGLEWSDL and user should be able to get the Metadata in one shot.

One catch with this is, I cannot override the External WSDL URl. Client will still see Http address infront of svcutil.exe

However, if they just put WSDL in Https Address, they will get single WSDL.

Capture

 

 

 

 

 

 

 

 

Explanation:

Visual Studio Add service reference will break, if just refer the service address without WSDL or SingleWSDL added at the end.

If we enter the service url https://xyz.com/Test/Service.svc we get a 400 error

Reason being:

This what happens when we try to add a service reference:

 

  1. Initial SSL Handshake.
  2. Second request try to get the Service PAGE and it eventually read the same address what gets printed infront of exe https://
  3. In below screen we can see that packet 6 and 7 are actually sent over HTTP, since Packet 5 returned Http end point in main service page (see Screen 2).
  4. And eventually third request is sent over HTTP and in your case it fails.

 

Screen 1

Capture

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Screen 2

Capture

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

What can be done?

Since Add Service reference is designed to read the service page to get WSDL DOC:

  • Either we need to get WSDL Doc available over Http (Not possible for SSL offloading).
  • Hard code the ExternalMetaDataLocation in service behavior and keep the WSDL file on server.
    • This will make sure that when we need metadata (browser or VS), it eventually get’s it from this fixed location and no chances of error.

I hope this help in understanding WCF life behind SSL off-loader LB.

Thanks

Saurabh Somani