title: WCF over TLS under Mono
body: <p>I am trying to get WCF communication to work over a TLS connection. I am using Mono 5.20.1.19 on Ubuntu 18.04, although I would hope that a solution would work on Windows too.</p>
  
  <p>Consider a basic interface like this:</p>
  
  <p>IExample.cs:</p>
  
  <pre class="lang-cs prettyprint-override"><code>using System;
  using System.ServiceModel;
  
  namespace Example
  {
      [ServiceContract]
      public interface IExample
      {
          [OperationContract]
          string Greet();
      }
  }
  </code></pre>
  
  <p>I have a server that sets up ServiceHost for an implementation of the interface:</p>
  
  <p>Server.cs:</p>
  
  <pre class="lang-cs prettyprint-override"><code>using System;
  using System.Net;
  using System.Net.Security;
  using System.ServiceModel;
  using System.ServiceModel.Security;
  using System.Security.Cryptography.X509Certificates;
  
  namespace Example
  {
      public class ExampleImpl : IExample
      {
          public string Greet()
          {
              Console.WriteLine("Greet() called");
  
              return "Hello!";
          }
      }
  
      public static class Program
      {
          public static void Main(string[] args)
          {
              using(var host = new ServiceHost(typeof(ExampleImpl), new Uri("net.tcp://localhost:5555"))){
                  var binding = new NetTcpBinding(SecurityMode.Transport);
                  binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
                  binding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
  
                  host.Credentials.ServiceCertificate.SetCertificate(
                      StoreLocation.CurrentUser,
                      StoreName.My,
                      X509FindType.FindBySubjectName,
                      "server");
  
                  host.AddServiceEndpoint(typeof(IExample), binding, "Example");
  
                  host.Open();
  
                  Console.WriteLine("listening at :5555");
                  Console.WriteLine("Press Enter to end the program");
  
                  Console.ReadLine();
              }
          }
      }
  }
  </code></pre>
  
  <p>Note that <code>SecurityMode.Transport</code> is specified for the NetTcpBinding, and <code>TcpClientCredentialType.Certificate</code> for the client credential type. I also specify a certificate which I installed to the <code>My</code> certificate store, in addition to the private key for the certificate.</p>
  
  <p>Now the client:</p>
  
  <p>Client.cs:</p>
  
  <pre class="lang-cs prettyprint-override"><code>using System;
  using System.Net;
  using System.ServiceModel;
  using System.ServiceModel.Channels;
  
  namespace Example
  {
      public static class Program
      {
          public static void Main(string[] args)
          {
              var binding = new NetTcpBinding(SecurityMode.None);
  
              var factory = new ChannelFactory&lt;IExample&gt;(binding, new EndpointAddress("net.tcp://localhost:5555/Example"));
  
              var obj = factory.CreateChannel();
  
              Console.WriteLine(obj.Greet());
          }
      }
  }
  </code></pre>
  
  <p>Note that in the client, the NetTcpBinding's security mode is set to <code>None</code>, and no client certificate is specified.</p>
  
  <p>We can build the two programs:</p>
  
  <pre class="lang-bash prettyprint-override"><code>$ csc Server.cs IExample.cs
  Microsoft (R) Visual C# Compiler version 2.8.2.62916 (2ad4aabc)
  Copyright (C) Microsoft Corporation. All rights reserved.
  $ csc Client.cs IExample.cs
  Microsoft (R) Visual C# Compiler version 2.8.2.62916 (2ad4aabc)
  Copyright (C) Microsoft Corporation. All rights reserved.
  </code></pre>
  
  <p>Now, if we run Server.exe, leave it open, and then in a different session run Client.exe, the server prints the message <code>Greet() called</code>, while the client prints <code>Hello!</code>.</p>
  
  <p>My confusion is why the connection is successful. I would expect that since the server's binding is set to <code>Transport</code>, then it should require a TLS connection; however it does not seem that TLS is being used, as no client certificate is being specified.</p>
  
  <p>How can I change the server portion of the code to require TLS connections?</p>