You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Kestrel support for "path based" TLS renegotiation. #23948
Is your feature request related to a problem? Please describe.
We have a reverse proxy running on ASP.NET Core, hosted in IIS in-process. During the initial TLS handshake with the client, the server is configured to not ask for a client certificate. However, if the path of the request contains, say "pksecure", IIS triggers a TLS renegotiation and sends a client certificate request.
The following configuration in IIS is how it works:
The linked document does not capture the same scenario. The recommendation there is using a separate hostname to mimic optional client certificates. However, the required scenario is the ability to keep the hostname the same and however renegotiate TLS based on path. The renegotiation of TLS is necessary because path is a http construct and the initial TLS handshake is already done by then and we are choosing to change the parameters of TLS based on http constructs.
That model isn't going to work anymore, renegotiation is obsolete in modern protocols. It's prohibited by the HTTP/2 spec and has been complete removed from TLS 1.3 (HTTP/3 & QUIC).
Even in HTTP/1.1 it was problematic. It could cause a POST request to deadlock if the request body filled up the TCP window and blocked the renegotiate packets.
The proposal outlined in the linked doc should work with all existing implementations and protocols. I understand that it will require some application redesign, but you'll need to address that in the long term anyways.
Makes sense. I didn't know it was prohibited by Http/2. This is a good thing, this gives us leverage when talking to partners to put this pattern on the deprecation path.
Interestingly TLS 1.3 does define a new way to request the client certificate after the connection has been established, it's called post-handshake authentication. https://tools.ietf.org/html/rfc8446#section-4.6.2
@davidfowl raises a good point that people using the cert auth handler will still have to be careful not to deadlock POST requests for the reasons outlined above, auth runs before model binding consumes the request body. We'll want to consider mitigations to at least make it fail instead of deadlock.
Activity
Tratcher commentedon Jul 15, 2020
That feature is outdated and will not be added to kestrel.
See the following doc for an alternative.
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-3.1#optional-client-certificates
avparuch commentedon Jul 15, 2020
The linked document does not capture the same scenario. The recommendation there is using a separate hostname to mimic optional client certificates. However, the required scenario is the ability to keep the hostname the same and however renegotiate TLS based on path. The renegotiation of TLS is necessary because path is a http construct and the initial TLS handshake is already done by then and we are choosing to change the parameters of TLS based on http constructs.
Tratcher commentedon Jul 15, 2020
That model isn't going to work anymore, renegotiation is obsolete in modern protocols. It's prohibited by the HTTP/2 spec and has been complete removed from TLS 1.3 (HTTP/3 & QUIC).
Even in HTTP/1.1 it was problematic. It could cause a POST request to deadlock if the request body filled up the TCP window and blocked the renegotiate packets.
The proposal outlined in the linked doc should work with all existing implementations and protocols. I understand that it will require some application redesign, but you'll need to address that in the long term anyways.
avparuch commentedon Jul 15, 2020
Makes sense. I didn't know it was prohibited by Http/2. This is a good thing, this gives us leverage when talking to partners to put this pattern on the deprecation path.
Tratcher commentedon Jul 16, 2020
Interestingly TLS 1.3 does define a new way to request the client certificate after the connection has been established, it's called post-handshake authentication. https://tools.ietf.org/html/rfc8446#section-4.6.2
However, this feature is also explicitly prohibited for use with HTTP/2 https://tools.ietf.org/html/rfc8740#section-3. I wonder if HTTP/3 will support it.
Either way, it's still better to use a strategy that works across all versions.
6 remaining items
Tratcher commentedon Apr 27, 2021
The existing GetClientCertificateAsync API should cover it.
aspnetcore/src/Http/Http/src/Features/TlsConnectionFeature.cs
Line 19 in bf51aa5
davidfowl commentedon Apr 27, 2021
Will the sync API be blocking? I think it should return null.
Tratcher commentedon Apr 27, 2021
The property will return the current value, if any. That's how HttpSys works now.
Tratcher commentedon Apr 27, 2021
HttpSys does have one other API controlling this:
aspnetcore/src/Servers/HttpSys/src/ClientCertificateMethod.cs
Lines 21 to 24 in 1453c5b
Tratcher commentedon Apr 27, 2021
@davidfowl raises a good point that people using the cert auth handler will still have to be careful not to deadlock POST requests for the reasons outlined above, auth runs before model binding consumes the request body. We'll want to consider mitigations to at least make it fail instead of deadlock.
Tratcher commentedon May 28, 2021
Here's Kestrel's current implementation:
aspnetcore/src/Servers/Kestrel/Core/src/Internal/TlsConnectionFeature.cs
Lines 37 to 40 in 3341e46
And here's where the client cert is currently assigned:
aspnetcore/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs
Line 201 in 3341e46
It may be interesting to note that a renegotiation may cause some/all of these other fields to change:
aspnetcore/src/Servers/Kestrel/Core/src/Middleware/HttpsConnectionMiddleware.cs
Lines 202 to 208 in 3341e46
davidfowl commentedon May 28, 2021
Cache that allocation 😄