runtime: Initial HTTPS request with client certificate fails on Linux, subsequent requests succeeds
Description
We are migrating a .NET Framework application to a .NET Core 3.1 application running on Linux in kubernetes. The application uses an HttpClient with client certificates to send request to an HTTP server. This works as expected when running on .NET Framework as well as .NET Core 3.1 on Windows. However, we get an unexpected behavior when running on Linux:
The first HTTP request fails with the following stack trace:
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
---> Interop+Crypto+OpenSslCryptographicException: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
--- End of inner exception stack trace ---
at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, Byte[] recvBuf, Int32 recvOffset, Int32 recvCount, Byte[]& sendBuf, Int32& sendCount)
at System.Net.Security.SslStreamPal.HandshakeInternal(SafeFreeCredentials credential, SafeDeleteContext& context, ArraySegment`1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
All subsequent requests to the HTTP server are successful. When monitoring the network traffic from the container, it becomes clear that the first request to the server only contains the leaf client certificate, whereas the following requests also contains the intermediate certificates.
This behavior can not be reproduced by using curl from within a newly created container. With curl, the request always succeeds and the observed network traffic shows that all requests contain the leaf client certificate as well as the intermediate ones.
Our application code is very much inspired by @bartonjs’s answer to this StackOverflow question (Can a .p12 file with CA certificates be used in C# without importing them to certificate store). That is: we put intermediate certificates in the current user’s CertificateAuthority store and only add the certificate to which we have the private key in the HttpClient.ClientCertificates property.
Is this behavior expected, or can we make modifications to our code to prevent this from happening?
Configuration
The Docker image is built on mcr.microsoft.com/dotnet/core/aspnet:3.1, dotnet --info outputs
Host (useful for support):
Version: 3.1.2
Commit: 916b5cba26
.NET Core SDKs installed:
No SDKs were found.
.NET Core runtimes installed:
Microsoft.AspNetCore.App 3.1.2 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
DEFAULT@SECLEVEL has been lowered from 2 to 1 the container (OpenSSL configuration)
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (10 by maintainers)
Use this
docker-compose.ymlfile:and run this to reproduce and capture the network traffic:
Complete command line log: