WCF NetTcpBinding Security - how does it work?
I am encountering the following problems trying to work through the quagmire of settings in WCF...
I created a WCF client-server service using a NetTcp binding. I didn't make any changes to the security settings and when running on one machine it works very nicely. However, when I ran my client from another machine it complained that the server didn't like the security credentials that were sent.
I understand now that NetTCP is "secured" by default and that my client would have been passing the wrong security details - namely the Windows user name and password (or some form of domain authentication) to my server which as they are not running on the same domain it would not have liked.
However, what I don't understand is as follows:
I haven't specified any security in my binding - does the standard settings expect a Windows user name or password to be sent?
I don't have any certificate installed on my server - I understand that NetTCP bindings need some form of public private key to protect the credentials - yet this seemed to work when both client and server were on the same machine - how was the data getting encrypted? Or wants it as WCF knew it was on the same machine and encryption isn't needed?
I have had to set my security mode on my client and server to "none" now and they connect nicely. However is there a way to encrypt my data without a certificate?
Finally... what is the difference between Transport and Message security?
To check my understanding (excuse the scenario!) message security is like if I sent a letter from person A to person B and I encode my hand writing to ensure that if anyone intercepts it they cannot read it? Transport Security is if I decide to have my letter sent by armed transport so that no one can get at it along the way?
Is it possible to have any form of encryption in WCF without a certificate? My project is a private project and I don't want to purchase a certificate and the data isn't that sensitive anyway so it's just for my own knowledge.
The default client credential type for NetTcpBinding is Windows Authentication. For Windows Authentication to work both client and server must be in the same domain, or mutually trusting domains (which in your case you do not have).
If both client and server were on the same domain, WCF would handle the mechanics of Windows Authentication "behind the scenes". And when both client and server are on the same machine they are effectively within the same domain, so Windows can use its own mechanisms to handle the encryption and decryption. It will only do this within mutually trusting domains, though.
If you don't have mutually trusting client and server domains, then the client and server must have some other way to determine if they trust each other with their keys. That's where certificates come in. The client and the server have their own certificates (or the server can issue the client a certificate).
Transport security is like encrypting the outside of the envelope as well as the inside. The downside is if you have to pass the envelope to someone outside your own organization, they need a decryption key just to know where the envelope is supposed to go--now they can read the message in the envelope also. On the other hand, transport security is faster--it requires less security overhead data getting passed along with your envelope.
Message security encrypts your message, but the envelope can be read by the postal workers (the internet and its routers). Only the source and the destination have the keys to decrypt the message, but the intermediaries can properly route your message.
To summarize: to use encryption over the NetTcpBinding both client and server must be within a domain (or mutually trusting domains) or you must have a key exchanging certificate.
Edit: I was asked for some example code--here is a binding element in XAML. It would normally be placed within a netTcpBinding element.
<binding name="Secure" listenBacklog="4000" receiveTimeout="00:20:00" sendTimeout="00:20:01" maxReceivedMessageSize="2147483647" maxConnections="200" portSharingEnabled="true"> <!-- ~2 GB --> <readerQuotas maxStringContentLength="2147483647"/> <!-- ~2 GB max string content length --> <security mode="Message"> <transport clientCredentialType="None" protectionLevel="EncryptAndSign"/> <message clientCredentialType="None"/> </security> </binding>
The important part is the security element. For transport security one would change the mode attribute to "Transport". More than likely the clientCredentialType would not be "None" but rather "Certificate", "Ntlm", or "Windows" depending on the context.