wsDualHttpBinding Not Working When Deployed Under Azure - c#

WCF Duplex not working under Azure.
Everything works fine under IIS Express.
I know duplex binding is problematic because of the server callback, but....
I already shut down my firewall.
TCPView (Sysinternals) shows 10 to 12 packets being sent/received by the client and then it just dies... nothing happens.
I set to 10 minutes all timeouts i could.
Please see my config files below.
SERVER CONFIG:
<system.serviceModel>
<services>
<service behaviorConfiguration="MexBehaviour" name="MySrvc">
<endpoint address="" binding="wsDualHttpBinding" bindingConfiguration="wsDualHttpBinding"
name="wsDualEndpoint" bindingName="wsDualHttpBinding" contract="IMySrvc" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="mexHttpBinding"
name="MexEndpoint" bindingName="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://srvc.azurewebsites.net/MySrvc.svc" />
</baseAddresses>
<timeouts openTimeout="00:10:00" />
</host>
</service>
</services>
<bindings>
<wsDualHttpBinding>
<binding name="wsDualHttpBinding" openTimeout="00:10:00" sendTimeout="00:10:00"
clientBaseAddress="http://xxx.xxx.xxx.xxx:xxx">
<security mode="None">
<message clientCredentialType="None" negotiateServiceCredential="false" />
</security>
</binding>
</wsDualHttpBinding>
<mexHttpBinding>
<binding name="mexHttpBinding" />
</mexHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MexBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
CLIENT CONFIG:
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="wsDualEndpoint">
<security mode="None" />
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://srvc.azurewebsites.net/MySrvc.svc"
binding="wsDualHttpBinding" bindingConfiguration="wsDualEndpoint"
contract="SrvcRef.IMySrvc" name="wsDualEndpoint" />
</client>
</system.serviceModel>

I knew this wsDualHttpBinding didn't pass the "smell test"....
From Juval Lowy's book, "Programming WCF Services: Mastering WCF and the Azure AppFabric Service Bus":
...the WSDualHttpBinding is mostly unusable, since it is practically impossible to tunnel through various communication barriers separating the service from the client and the need to find a specific web-server machine makes this impractical.
I solved my problem by simply using netTcpBinding instead....
You just need to get IIS to work with TCP protocol.
There's plenty of articles out there explaining how to do it.
Here's one:
http://msdn.microsoft.com/en-us/library/ms731053.aspx
Cheers.

Related

WCF - HTTPS - Transport security works but message security throws exception on application startup

I have a WCF self hosted server (a console application which registers the wcf contract with castle ioc container AsWcfService). I need it to work securely over https.
When I configure the server to use wsHttpBinding with security mode=Transport and clientCredentialsType=None, everthing works fine.
The configurations looks as follows:
Transport Security Configuration
<behaviors>
<serviceBehaviors>
<behavior name="secureBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" httpsHelpPageEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="secureBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="01:00:00">
<security mode="Transport" >
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="service" behaviorConfiguration="secureBehavior">
<endpoint binding="wsHttpBinding" bindingConfiguration="secureBinding" contract="Contract.Service" />
<host>
<baseAddresses>
<add baseAddress="https://domain-name:port-number/"/>
</baseAddresses>
</host>
</service>
</services>
The above works fine.
Message Security Configuration
<behaviors>
<serviceBehaviors>
<behavior name="secureBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" httpsHelpPageEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="secureBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="01:00:00">
<security mode="Message" >
<message clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="service" behaviorConfiguration="secureBehavior">
<endpoint binding="wsHttpBinding" bindingConfiguration="secureBinding" contract="Contract.Service" />
<host>
<baseAddresses>
<add baseAddress="https://domain-name:port-number/"/>
</baseAddresses>
</host>
</service>
</services>
With message security configuration, however, when I try to start the server I get the following exception:
Could not find a base address that matches scheme http for the
endpoint with binding WSHttpBinding. Registered base address schemes
are [https]. System.InvalidOperationException: Could not find a base
address that matches scheme http for the endpoint with binding
WSHttpBinding. Registered base address schemes are [https].
I can't find the reason for this error anywhere I look.
An explanation would be highly appreciated.

Can't connect to IIS server on remote machine

I have create iis server on remonte machine (Windows Server 2008 R2). This is my web.config:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="Binding" closeTimeout="00:05:00" sendTimeout="00:10:00" />
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="DictionaryServiceBehaviors">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="DictionaryServiceBehaviors" name="BandD.Serwis.SerwisISS.Service.DictionariesService">
<endpoint address=""
binding="wsHttpBinding"
contract="BandD.Serwis.SerwisISS.Interface.IDictionariesService"
bindingConfiguration="Binding"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://xxx.xxx.199.89:7833/BandD.Serwis.SerwisISS.Service/DictionariesService/"/>
</baseAddresses>
</host>
</service>
</services>
That is app.config for client application:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IDictionariesService" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://xxx.xxx.199.89:7833/Service/DictionariesService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDictionariesService"
contract="DictionariesService.IDictionariesService" name="WSHttpBinding_IDictionariesService">
</endpoint>
</client>
I have add IIS server role to my remote machine, i set physical path to locate publised file from server application (publised from VS). All of authentication i set to Disabled, only Anonymous Authentication is Enabled.
When i try connect to WSDL with SoapUi i go error:
Error getting response; java.net.UnknowsHostException: winserver2008
When i want connect to server with client app i must write username and password (administrator password don't work).
What i must do to can connect to server without authentication. What i should change on server(Windows server) or app.config to can connect correctly.
Probably i have bed web/app.config
Ok i found solution:
On MS Server i change for now website connect as (in bassic setting) to administrator. This is only for now and i change it later.
Second i change web.config on server:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="Binding" closeTimeout="00:05:00" sendTimeout="00:10:00">
<security mode="None" />
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="DictionaryServiceBehaviors">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="DictionaryServiceBehaviors" name="BandD.Serwis.SerwisISS.Service.DictionariesService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding"
contract="BandD.Serwis.SerwisISS.Interface.IDictionariesService" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
name="mex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://http://xxx.xxx.199.89:7833/Service/DictionariesService" />
</baseAddresses>
<timeouts closeTimeout="00:01:00" openTimeout="00:10:00" />
</host>
</service>
</services>
At last i change client app config:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IDictionariesService">
<reliableSession enabled="true" />
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://xxx.xxx.199.89:7833/Service/DictionariesService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDictionariesService"
contract="DictionariesService.IDictionariesService" name="WSHttpBinding_IDictionariesService" />
</client>
</system.serviceModel>

Support both HTTP and HTTPS Web.Config WCF Service

I'm running into a configuration problem with my WCF service when trying to support both https and https. Ideally what I'd like is to run http on my dev machine and then publish to azure running https.
I followed these posts to try and run the configuration:
http://jayakrishnagudla.blogspot.com/2009/12/configuring-wcf-services-to-work-with.html
How to configure a single WCF Service to have multiple HTTP and HTTPS endpoints?
My Web.Config is as follows:
<system.serviceModel>
<services>
<service name="Backend.Services.UserService.UserService" behaviorConfiguration="">
<endpoint address=""
binding="webHttpBinding"
contract="Backend.Services.UserService.IUserService"
bindingConfiguration="HttpsBinding"
behaviorConfiguration="Web">
</endpoint>
<endpoint address=""
binding="webHttpBinding"
contract="Backend.Services.UserService.IUserService"
bindingConfiguration="HttpBinding"
behaviorConfiguration="Web"
>
</endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name ="HttpBinding">
<security mode="None">
<transport clientCredentialType="None"/>
</security>
</binding>
<binding name="HttpsBinding">
<security mode="Transport"/>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="Web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
As far as I can tell, this configuration should be correct according to the above links. However, when I build and run this service locally via http I get the following error:
Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http].
I'm not quite sure where the problem is and assume its a misconfiguration. Any help would be appreciated.
I've been trying to do this for days (years actually, but just restarted a few days ago), and the post above pointed me in the right direction with protocolMapping, but you need to specify the bindingConfiguration in the protocolMapping section to make it choose the <security mode=None> or <security mode=Transport>:
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<protocolMapping>
<add scheme="http" binding="basicHttpBinding" bindingConfiguration="ServiceBinding"/>
<add scheme="https" binding="basicHttpBinding" bindingConfiguration="ServiceBindingSSL"/>
</protocolMapping>
Leave the bindingConfiguration attribute off of the endpoint - it will be set automatically based on the protocol. Then set up the second binding configuration in your bindings section:
<basicHttpBinding>
<binding name="ServiceBinding" ...>
<security mode="None">
</security>
</binding>
<binding name="ServiceBindingSSL" ... >
<security mode="Transport">
</security>
</binding>
</basicHttpBinding>
This technique worked for me. Hope it helps you!
i finally got it working for HTTP & HTTPS, based on Rick Moss' answer. except that i did not leave away the bindingConfiguration off the endpoint, because it caused a no endpoint listening error:
<configuration>
...
<system.serviceModel>
<services>
<service name="WcfService1.Service1">
<endpoint address="" name="ep1" binding="webHttpBinding" bindingConfiguration="ServiceBinding" contract="WcfService1.IService1" behaviorConfiguration="WebBehavior" />
<endpoint address="" name="ep1" binding="webHttpBinding" bindingConfiguration="ServiceBindingSSL" contract="WcfService1.IService1" behaviorConfiguration="WebBehavior" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="ServiceBinding" ...>
<security mode="None">
</security>
</binding>
<binding name="ServiceBindingSSL" ...>
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
...
</behaviors>
<protocolMapping>
<add scheme="http" binding="basicHttpBinding" bindingConfiguration="ServiceBinding"/>
<add scheme="https" binding="basicHttpBinding" bindingConfiguration="ServiceBindingSSL"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
...
</configuration>
EDIT: this only seems to work with Anonymous authentication in IIS. Enabling Windows Authentication in a different web service under the same website in IIS caused:
Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http].
i hate Web.config files. they're too tightly coupled to IIS
Have you looked at the protocol mapping wcf configuration section?
<protocolMapping>
<add scheme="http" binding="wsHttpBinding"/>
<add scheme="https" binding="wsHttpBinding"/>
</protocolMapping>
Edit : I am not sure why you have configured an "https" binding under the webHttpBinding type. Shouldn't you have both http webHttpBinding and wsHttpBinding defined and assigned to your endpoint?
<webHttpBinding>
<binding name ="HttpBinding">
<security mode="None">
<transport clientCredentialType="None"/>
</security>
</binding>
</webHttpBinding>
<wsHttpBinding>
<binding name="wsHttpEndpointBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>

wcf userName authentication with message security over https

Here is the situation, I want many clients to call my web service using username authentication over https. Security is the first priority so I am thinking of using wshttpbinding with message security. I don't know though if my thoughts are correct.
The thing is that I have already something that works but I don't know if it needs changes to achieve better security.
Here is what it's done by now.
<services>
<service name="myService" behaviorConfiguration="myBehavior" >
<endpoint address="" binding="basicHttpBinding" contract="myIService" bindingConfiguration="RequestUserName_BasicHttp" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/myService/" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="RequestUserName_BasicHttp">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="myvalidator, myNamespace"/>
</serviceCredentials>
So, by this way (which works) I don't think that I have best security (at least I need to send requests over https). What can I do to achieve better/best security? I have tried with wshttpbinding and https but I have some problems with certificates.
The development enviroment is Windows XP, VS2010, IIS7.5 express.
And there are a class library describing the Service and a consoleClient app for consuming it...The client has it's own app.config file in which there are the credentials (username and password).
you are already implementing user id and password verification and if you want to perform encryption and decryption of messages you must use Certificates with HttpsBinding or WsHttpBinding. More information about authentication and authorization in wcf please go through this MSDN documentation
Ok, I took into consideration Ramesh Babu answer and I change a little bit my project.
So instead of creating a class library for wcf service I created a WCF Service Application (there is this option in VS2010).Everything else remained unchanged so I made a new Web.config file like this
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="MyBinding">
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="MyBehavior" name="myName">
<endpoint address="myService.svc" binding="wsHttpBinding"
bindingConfiguration="MyBinding"
contract="myService.ImyService" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:44400/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebugincludeExceptionDetailInFaults="true" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="myService.Authentication.CustomValidator, myService" />
<serviceCertificate
findValue="MyCertificate"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
<connectionStrings>
<add name="myEntities" connectionString="......" />
</connectionStrings>
</configuration>
so I needed to create a certificate and I used SelfCert to create one and copy it to TrustedPeople (typing mmc in run).
After this I created a console app to consume thw service and app.config file of app was built automatically.

HTTP and HTTPS Bindings

I have a application that consumes a WCF web service.
I have it cofigured to use a https binding. It works fine. I also wanted to add a HTTP binding to the same.
My requirement is if my client is on my domain (or on VPN) i need them to use the HTTP binding. and if they are external clients I want them to use HTTPS binding. How can I go about doing that? I am very new to WCF and this is my first try on it.
I have attached my Config File for reference. I did not know where to add the end point for the HTTP binding. Any help would be appriciated.
<system.serviceModel>
<services>
<service name="{service name}"
behaviorConfiguration="httpsBehavior">
<!--HTTPS END POINT-->
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="SecureHTTPBinding"
contract="{service contract}" />
<!--METADATA ENDPOINT-->
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="httpsBehavior">
<serviceMetadata httpsGetEnabled="true" httpsGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
<behavior name="httpBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<!--HTTPS BINDING-->
<binding name="SecureHTTPBinding">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<!--HTTP BINDING-->
<binding name="BasicHttpBinding">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
EDIT : Adding netTCP Binding
<system.serviceModel>
<services>
<service name="{Service Name}"
behaviorConfiguration="httpsBehavior">
<!--HTTPS END POINT-->
<endpoint address="https://localhost/Service1.svc"
binding="basicHttpBinding"
bindingConfiguration="SecureHTTPBinding"
contract="{Service Contract}" name="httpsEndPoint"/>
<!--METADATA ENDPOINT-->
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
<!--HTTP END POINT-->
<endpoint address="http://localhost/Service1.svc"
binding="basicHttpBinding"
bindingConfiguration="HttpBinding"
contract="{Service Contract}" name="httpsEndPoint"/>
<!--TCP METATADATA END POINT-->
<endpoint address="mextcp" binding="mexTcpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:808/Service1.svc" />
</baseAddresses>
</host>
<!--TCP ENDPOIN-->
<endpoint address="net.tcp://localhost:808/Service1.svc" binding="netTcpBinding" contract="{Service Contract}" name="netTCPEndPoint" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="httpsBehavior">
<serviceMetadata httpsGetEnabled="true" httpsGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<!--HTTPS BINDING-->
<binding name="SecureHTTPBinding" allowCookies="true"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32"
maxArrayLength="200000000"
maxStringContentLength="200000000"/>
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
<!--HTTP BINDING-->
<binding name="HttpBinding" allowCookies="true"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000">
<readerQuotas maxDepth="32"
maxArrayLength="200000000"
maxStringContentLength="200000000"/>
<security mode="None" />
</binding>
</basicHttpBinding>
<!--TCP BINDING-->
<netTcpBinding>
<binding transferMode="Buffered" />
</netTcpBinding>
</bindings>
I am aware of the the possible Dos attacks wrt to the numbers in the code and I would work around it. For now just wanted to get it working. When I use this config file I run into error that says
Could not find a base address that matches the scheme net.tcp for the endpoint MetadataExchageTcpBinding. Registered base addresses are [http,https]
Can some one help me expose a net.tcp binding for my service.
Any help would be appriciated
Use netTcpBinding for your domain clients. Your network firewall will almost certainly block raw TCP traffic by default while letting in HTTP traffic, so it will naturally ensure that each client goes to the appropriate endpoint. You may very well get an extra performance boost for domain clients into the bargain.
If you don't want to do that (e.g. your WCF host doesn't support it, or you have problems with VPN clients), then just expose one HTTPS endpoint for all clients regardless of location. The cost of SSL will be trivial compared to the overhead of doing a cross-network call in the first place.
Background:
netTcpBinding transmits data in a compact binary format, which is more efficient than sending XML text over HTTP. The downsides are: it is not compatible with non-.NET clients, and you have to open specific ports on the firewall to let it through. Neither of those issues will be a problem for your scenario though.
You can expose any number of endpoints in a WCF service, as long as they all have unique distinct combinations of Address/Binding/Contract. You can therefore expose both HTTPS and TCP endpoints to the same service because they will have different Addresses and Bindings.

Categories