title: Kestrel and OpenSSL cipher suites
body: <p>How can I change the available cipher suites available to OpenSSL/Kestrel from within a Linux docker container?</p>
  
  <p>First, lets start with some environment details:</p>
  
  <ul>
  <li>We use a Linux docker container (Docker version 17.06.0-ce, build 02c1d87) that we connect to via powershell</li>
  <li>It hosts an ASP.Net Core (netcore 1.1) web app written in C#.</li>
  <li>Written largely against .NetStandard 1.4/1.6, but a move onto 2.0 is planned.</li>
  <li>We use Kestrel as our web server on the docker container </li>
  <li>Kestrel is using openSSL (1.0.1) under the hood as far as i understand.</li>
  </ul>
  
  <p>My Program.cs looks something like this, which sets up kestrel:</p>
  
  <pre><code>builder.UseKestrel(o =&gt; o.UseHttps(new HttpsConnectionFilterOptions
              {
                  SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11,
                  CheckCertificateRevocation = true,
                  ClientCertificateMode = ClientCertificateMode.AllowCertificate 
                  ServerCertificate = new X509Certificate2(certificate.Pfx, certificate.Password)
              }))
      .UseUrls(bindTo);
  </code></pre>
  
  <p>The key line being this:</p>
  
  <pre><code>SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11,
  </code></pre>
  
  <p>No matter what values I set here (Tls12, Tls11, Tls, or any subset of these), it doesn't seem to have an impact on what cipher suites are available to connections. I'm going by the sslLabs report for my URL, which is capped at Grade B due to the availability of RC4 ciphers on old protocols. Which is the issue what I want to sort, and I believe supporting just TLS1.1 and 1.2 should solve this.</p>
  
  <p>But for example, as you can see above, I don't mention TLS 1.0, and yet its available in the report, which has kind of stumped me.</p>
  
  <p>Is it actually using the code, or is it getting the available ciphers from somewhere else? Because it certainly looks like the value of the SslProtocols property makes no difference.</p>
  
  <p>When using Apache you can configure the available cipher suites via configuration file (httpd.conf), so I figured that kestrel might have a file to do the same thing, but I've not managed to find one. The general consensus seems to be that it be handled in code. Which as far as I can see, I have done?</p>
  
  <p>I then considered using Apache as the Internet-facing web server to handle the cipher management, which then proxies requests onto kestrel, but this would be in breach of contract for this project, where we specify that all data will remain encrypted during every stage of transit. The process of decrypting the data in Apache before re-encrypting it for transit onto kestrel isn't viable.</p>
  
  <p>I then thought that perhaps OpenSSL has a similar configuration file to Apache, and that I can just change that configuration to achieve what I needed. I found these 2 files in our file system:</p>
  
  <pre><code>/usr/lib/ssl/openssl.cnf
  /etc/ssl/openssl.cnf
  </code></pre>
  
  <p>But neither of them have any lists of cipher suites that I would expect to see when comparing with the Apache configuration file. Or perhaps it did, and I have just misunderstood the file format?</p>
  
  <p>I have also come across this method that can be used to configure available cipher suites 'SSL_CTX_set_cipher_list', but I think this is only available in C++, and there is no similar functionality/wrapper for C# that I have found. I guess it would be possible to write a C++ program to setup the cipher suites when pushing into docker before setting up the website? But this sounds really hacky though, I'd prefer to get the website handling it by itself.</p>
  
  <p>Long story short, I'm rapidly running out of ideas. So any input you have is greatly appreciated. Thanks for any help you can provide!</p>