Aspnetcore: Support cipher suite configuration

Created on 26 May 2017  ·  33Comments  ·  Source: dotnet/aspnetcore

As I understand, Kestrel 2 will be considered "safe" for edge deployments with HTTPS. Currently, there is no way to easily configure many desirable parameters of HTTPS. Mainly, the cipher suites that are supported, the algorithm and key size of the key exchange, etc.

For Windows, the functionality is configured the same as it was with IIS - with the registry / group policy. For Linux, I'm not exactly sure how to change the configuration, or if it can be done at all. I suspect it will just use OpenSSL's default in the distribution. If that is not the case, then I would be keen in knowing how to do it.

The Windows configuration by registry for SChannel leaves a lot to be desired. Changing SChannel's default configuration is not just for IIS or Kestrel - it affects anything that uses SChannel (remote desktop for example).

For edge deployments, it is naturally desirable to want to configure the cipher suites. There is a lot of pressure and mandate to start turning off old versions of TLS and strengthening cipher suite configuration, ensuring poor symmetric cipher are disabled, like 3DES, etc. Setting a preferred order is also important. Most web servers will prioritize AES128 over AES256 for performance, while some customers may wish to trade off the performance for security.

Even for internal traffic use, this is still very useful. Internal TLS is important, and because the traffic is internal to my infrastructure, I can mandate it to be whatever I want, such as TLS 1.2 only and ECDHE-AES-GCM-128 and not have to worry about client compatibility.

area-servers servers-kestrel

Most helpful comment

@Drawaes

For windows, it's a non starter, as it relies on SChannel, which has a registry level config that is machine wide only

I want to dispel this statement because I keep hearing it. SChannel in usermode is quite capable of configuring protocols and cipher suites at pretty much any level you want, such as the socket. Here is some awful C++ code I wrote that does that: https://gist.github.com/vcsjones/7687d2a764836b40300d15fea07510f8 (it gets interesting around line 92)

This just sets up a little dummy TLS handshake server that uses TLS v1.1, regardless of what the registry is set to. It isn't enough code to try it in a browser (because I was too lazy to finish the handshake), but if you compile this code, run it, and point openssl to it, you get something like this:

screen shot 2017-05-26 at 3 30 15 am

Using openssl s_client -connect 127.0.0.1:21213

You can configure the cipher suites in SCHANNEL_CRED - the example is just set to "use whatever".

So I would argue that Kestrel is capable of using SChannel on Windows and allow cipher suite / protocol selection. Well, actually I would argue that CoreFX is capable of implementing SslStream in such a way, but the machinery is there for Windows.

All 33 comments

On Linux you can do it by configuring OpenSSL (not cURL). For windows you are stuck with the Registry/Policy story, which is an issue I have raised. It means that every site on a machine has to run with the same config. SSLStream delegates all of the processing to SChannel so you have no option

@Drawaes

On Linux you can do it by configuring OpenSSL (not cURL)

How? OpenSSL is just a library, it doesn't really have a configuration file other than openssl.cnf which is, as far as I know, it not used to set the protocols and cipher suites - just when you use bin/openssl in the CLI to do things like CSRs or run a CA.

Our TLS support currently comes via SSLStream, we'll need to file an issue on corefx.

For windows, it's a non starter, as it relies on SChannel, which has a registry level config that is machine wide only (eg both client and server uses will be effected). OpenSsl has a possibility but it needs code, and it would change everything in process that uses SslStream,

@Drawaes

For windows, it's a non starter, as it relies on SChannel, which has a registry level config that is machine wide only

I want to dispel this statement because I keep hearing it. SChannel in usermode is quite capable of configuring protocols and cipher suites at pretty much any level you want, such as the socket. Here is some awful C++ code I wrote that does that: https://gist.github.com/vcsjones/7687d2a764836b40300d15fea07510f8 (it gets interesting around line 92)

This just sets up a little dummy TLS handshake server that uses TLS v1.1, regardless of what the registry is set to. It isn't enough code to try it in a browser (because I was too lazy to finish the handshake), but if you compile this code, run it, and point openssl to it, you get something like this:

screen shot 2017-05-26 at 3 30 15 am

Using openssl s_client -connect 127.0.0.1:21213

You can configure the cipher suites in SCHANNEL_CRED - the example is just set to "use whatever".

So I would argue that Kestrel is capable of using SChannel on Windows and allow cipher suite / protocol selection. Well, actually I would argue that CoreFX is capable of implementing SslStream in such a way, but the machinery is there for Windows.

I know you can set the protocol version, my schannel prototype did that. Was unaware you could set curves and ciphers?

Sure, I updated it to limit it to cipher suites with AES-128. Change it to AES-256 and it will pick AES-256.

The API for this is very, very strange, but it's doable, I think.

Nice! The API isn't that bad. 😄 Good ol' SSPI's.

I guess the question now is whether IIS relies on calls to AcceptSecurityContext in the kernel to handle this bit (I think it does?), or whether it does it in usermode. At one point it was advantageous to do it in the kernel for perf reasons.

IIS delegates HTTPS to Http.Sys in kernel mode. So does WebListener.

IIS Does it in the kernel, I believe http.sys also does it in the kernel.

On 26/05/2017 5:49 PM, "Steve Syfuhs" notifications@github.com wrote:

Nice! The API isn't that bad. 😄 Good ol' SSPI's.

I guess the question now is whether IIS relies on calls to
AcceptSecurityContext in the kernel to handle this bit (I think it does?),
or whether it does it in usermode. At one point it was advantageous to do
it in the kernel for perf reasons.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/aspnet/KestrelHttpServer/issues/1865#issuecomment-304332419,
or mute the thread
https://github.com/notifications/unsubscribe-auth/APpZuen5nqQsbT9Li6p35XBesLH4OyWeks5r9wKQgaJpZM4NnDth
.

IIS delegates HTTPS to Http.Sys in kernel mode. So does WebListener.

OK, I'll digress from the specifics of this, but rather want to point out that as someone that is in charge of deploying and managing TLS in an infrastructure, there are several gaps that need to be filled before I would be comfortable even considering terminating TLS with Kestrel. I'm raising the issues because I think they are important, and if the intention is for this to be a real scenario for Kestrel, there needs to be some discussion around this.

I'll put aside the Windows / SChannel issue because there is at least a functioning work around with Group Policy / registry since we are using SChannel in kernel mode, apparently.

The issue still stands that I do not know how to do this on Linux and it is a requirement for any practical deployment of HTTPS on the edge.

You can use the same trick for openssl. There is 1 instance per process. You can change the cipherlist before an tls connection starts u are good.
https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_cipher_list.html
Call that and you can do a similar thing. This time there is no kernel in play.

You can also compile out TLS levels .. you need to ensure you only call methods on the lib after .net did it's openssl init or you need to do it, otherwise you won't have ciphers loaded.

You can use the same trick for openssl. There is 1 instance per process. You can change the cipherlist before an tls connection starts u are good.

Ah. That would work... but platform invoking openssl on process startup should be viewed as a work around at best, but that's good thinking.

Also /cc @blowdart

It would be desirable to configure TLS options via some platform-neutral .NET API that the process using Kestrel can apply before starting up the listener (with potentially reduced functionality compared to OpenSSL/SChannel configuration API).

Right now we use nginx both on Windows and Linux for certain roles, exactly to avoid having to maintain two different configuration paths. There are some parts of this infrastructure that are a good fit for potential replacement with Kestrel in the near future but any moment where we need to think about "Kestrel on Windows" versus "Kestrel on Linux" is a deal-killer for us.

@joshfree, we think this should be an SSLStream feature. Perhaps we should talk about this in our next sync-up.

cc @davidfowl

It will need to be supported from SslStream to work. There is an open issue to change SslStream's API to have an option bag, which hopefully will mean we can add more config options easier ;)

This is an SSLStream feature ask. Assigning to @shirhatti in case he wants to follow-up or close it.

Apparently this is starting to get hit as iPhone/iOS clients try to hit Kestrel and it's not possible. @mattcotterellnz hit this recently. Can we get this triaged and moved to Corefx? Or is this already coming in 2.1 with this? https://github.com/dotnet/corefx/pull/25985 @stephentoub

If there's a feature request for SslStream, someone should open an issue in corefx with a proposal.

Is it https://github.com/dotnet/corefx/issues/24588?

There are two "things" in this request: the cipher suites, and the protocol version.

As I understand, SslStream already supports configuring the protocol in AuthenticateAsServer and AuthenticateAsClient. I think for the protocol version then, it's just a matter of Kestrel allowing those values to be configured.

For cipher suites, yes - that will require work as SslStream does not expose setting that.

/cc @stephentoub

https://msdn.microsoft.com/en-us/library/ms145065(v=vs.110).aspx

Yes https://github.com/dotnet/corefx/issues/24588

Will satisfy the requirement from sslstream.

Putting this into the backlog for now.

@vcsjones Kestrel already allows the protocol version to be configured. https://stackoverflow.com/a/46833019/719967

@halter73 oh wow, OK - that's good to know. I apparently missed this (is it new?). Would it make sense to update the title and description of this issue to make it about cipher suites specifically then?

The SslProtocols config has been in Kestrel since 1.0, but back in 1.x it was on the HttpsConnectionFilterOptions type instead of the HttpsConnectionAdapterOptions type. I updated the title.

so now kestrel still does not support cipher suite configuration ?

so now kestrel still does not support cipher suite configuration ?

I believe the upstream issue at dotnet/corefx#24588 needs to be resolved first. If this is important to you, give it a 👍 so that folks are better able to understand how many people want this feature.

I'd like to use Kestrel as an edge server. I wrote an article how to deploy it as a non-sudo user here: https://medium.com/@ryan.dines/asp-net-core-aws-rhel-kestrel-14ce07a852ff. Then I started thinking about the TLS layer, I always configure to get an A+ rating from Qualsys with Apache or Nginx, so that would be awesome if you could pre-configure out of the box for me. To me should be part of the server config, here is my nginx config, if you were looking for inspiration on what other features to add besides the cipher suite order (by far the most important). Some are probably already implemented I imagine. Cool software by the way, love the direction ASP.NET is headed, keep up the good work.

server {
    server_name seniordevops.com;
    listen 443 ssl http2;
    ssl_certificate /etc/ssl/certs/seniordevops_com.crt;
    ssl_certificate_key /etc/ssl/certs/seniordevops.key;
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 180m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DHE+AES128:!ADH:!AECDH:!MD5;
    ssl_dhparam /etc/nginx/cert/dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/ssl/certs/seniordevops_com.crt;
    resolver 8.8.8.8 8.8.4.4;
    add_header Strict-Transport-Security "max-age=31536000" always;
    root /opt/workTracker/workTracker;
    index clockin/templates/registration/login.html;
    keepalive_timeout 5;
    client_max_body_size 4G;

Is there any feedback on this?

Is this unblocked now that https://github.com/dotnet/corefx/issues/24588 is resolved?

@avenema Yes. We've filed https://github.com/aspnet/AspNetCore/issues/9349 to track this work.

Closing this discussion issue in favor of the new issue

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aurokk picture aurokk  ·  3Comments

FourLeafClover picture FourLeafClover  ·  3Comments

rbanks54 picture rbanks54  ·  3Comments

rynowak picture rynowak  ·  3Comments

ermithun picture ermithun  ·  3Comments