none
SSL/TSL with NetTcpBinding RRS feed

  • Question

  • Documentation says that NetTcpBinding supports ssl encryption. However I realized that when I create an instance of the service using:

    var binding = new NetTcpBinding(SecurityMode.Transport, true)

    The service starts, but I observe no encryption in WireShark. Further readings lead me to realize that I need to define a certificate:

    var binding = new NetTcpBinding(SecurityMode.Transport, true) binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;

    host.Credential.ServiceCertificate.SetCertificate( StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "1ae99dcf575283f3c4fbf3151681266b2ba6745e");

    But now I need to install a client certificate, i.e. - use certificate authentication.

    Do I understand correctly that I cannot have transport encryption without client certificate in NetTcpBinding with Windows type authentication?

    Saturday, April 13, 2019 12:22 PM

All replies

  • Hi Aleksey Malyshev,
    It is unnecessary to require the client to provide a certificate when we set up the security to Transport.
    The following code also works.
    NetTcpBinding binding = new NetTcpBinding();
                binding.Security.Mode = SecurityMode.Transport;
                binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;

    Result.
    https://i.stack.imgur.com/XmS8E.png
    In other words, all you have to do is provide a server-side certificate. The client credential is just the way to authenticate the client.
    Here is my example, wish it is useful to you.
    Server(console application, IP:10.157.13.69)
    class Program
        {
            static void Main(string[] args)
            {
                Uri uri = new Uri("net.tcp://localhost:4396");
                NetTcpBinding binding = new NetTcpBinding();
                binding.Security.Mode = SecurityMode.Transport;
                binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
    
                using (ServiceHost sh = new ServiceHost(typeof(TestService), uri))
                {
                    sh.AddServiceEndpoint(typeof(ITestService), binding, "");
                    ServiceMetadataBehavior smb;
                    smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb == null)
                    {
                        smb = new ServiceMetadataBehavior()
                        {
                        };
                        sh.Description.Behaviors.Add(smb);
    
                    }
    
                    Binding mexbinding = MetadataExchangeBindings.CreateMexTcpBinding();
                    sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
    //specify an x509 certificate.
                    X509Certificate2 cert = new X509Certificate2("1.pfx", "123456");
                    sh.Credentials.ServiceCertificate.Certificate = cert;
    
                    sh.Opened += delegate
                    {
                        Console.WriteLine("service is ready");
                    };
                    sh.Closed += delegate
                    {
                        Console.WriteLine("service is closed");
                    };
                    sh.Open();
                    Console.ReadLine();
    
                    sh.Close();
                }
            }
        }
        [ServiceContract]
        public interface ITestService
        {
            [OperationContract]
            string GetResult();
        }
    
        [ServiceBehavior]
        public class TestService : ITestService
        {
            public string GetResult()
            {
                return $"Hello, busy World. {DateTime.Now.ToShortTimeString()}";
            }
        }

    Client(console application,Invoke the service by adding service reference. IP:10.157.19.140)
    class Program
        {
            static void Main(string[] args)
            {
                ServiceReference1.TestServiceClient client = new ServiceReference1.TestServiceClient();
                try
                {
                    var result = client.GetResult();
                    Console.WriteLine(result);
                }
                catch (Exception)
                {
    
                    throw;
                }
            }
    }

    Client(app.config)
        <system.serviceModel>
            <bindings>
                <netTcpBinding>
                    <binding name="NetTcpBinding_ITestService">
                        <security>
                            <transport clientCredentialType="None" />
                        </security>
                    </binding>
                </netTcpBinding>
            </bindings>
            <client>
                <endpoint address="net.tcp://10.157.13.69:4396/" binding="netTcpBinding"
                    bindingConfiguration="NetTcpBinding_ITestService" contract="ServiceReference1.ITestService"
                    name="NetTcpBinding_ITestService">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
            </client>
    </system.serviceModel>

    Feel free to let me know if there is anything I can help with.
    Best Regards
    Abraham

    Monday, April 15, 2019 6:27 AM
    Moderator
  • Thanks for reply. But there is still a problem. If I set TcpClientCredentialType.None, then how can I authenticate the user? channelFactory.Credentials.Windows.ClientCredential do not work. If I set TcpClientCredentialType.Windows, there is no encryption.
    Wednesday, April 24, 2019 10:11 PM
  • Hi Aleksey Malyshev,

    It seems you are right. When I use windows credential as client credential, not only is it not encrypted using the TLS protocol, it can even run without configuring a certificate on the server. 
    Here is the official quote.

    >> If you are using Windows security, a certificate is not required.

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/transport-security-overview
    In my opinion, under this circumstance, the transport security of NetTcpBinding is provided by the windows security. In other words, when using windows credentials to authenticate clients, NetTcpBinding itself can implement transport layer security. Your understanding is good.
    >>The NetTcpBinding generates a run-time communication stack by default, which uses transport security, TCP for message delivery, and a binary message encoding. This binding is an appropriate Windows Communication Foundation (WCF) system-provided choice for communicating over an Intranet.
    https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.nettcpbinding?view=netframework-4.8
    Regards
    Abraham

    Thursday, April 25, 2019 11:34 AM
    Moderator