.NET 5 bug history

How we encountered an unexpected bug in .NET 5, investigated the problem, and what came of it.





One fine day, it was decided to transfer a working project from .NET Core 3.1 to .NET 5. The migration turned out to be easier than it was, for example, when switching from .NET Core 2.1 to .NET Core 3 due to fewer improvements. In fact, it was just required to change TargetFramework to net5.0, update several libraries and fix a couple of places in the code that have become deprecated, so that in the future it will not be so painful to do.





, . . , , . , , HTTPS- - (401). , — . , , .NET Core 3.1, , .NET 5.





, . , HTTP Certificates, , API . , .





, - , ? curl, Python Go. .





? Windows, Linux ( , Docker). , , Docker, , , . .NET Core 3.1 , - ? , TargetFramework netcoreapp3.1, Windows, Linux.





, , ? : HttpClientFactory, HttpClientHandler , , - .





. , , , , ? , , . , .





? , : , — , — .





Query flowchart in a slightly more complex scenario

: , , , . , , . , macOS . , .





? : . — .





: .NET, ( 5.0.2), . , . , , , .





Jetbrains Rider. (External source debug). .NET, , HTTP-, .





Windows, Linux-, :





  1. Linux ;





  2. WSL 2 Docker.





SSH, IDE. , Rider - , Visual Studio, .





: SecureChannel SslStreamCertificateContext. , partial : Windows , Linux — OpenSSL. SSL- SslSessionsCache. , - , .





SSL- , HTTP- :





var assembly = AppDomain.CurrentDomain.GetAssemblies()
	.First(x => x.FullName?.Contains("System.Net.Security") == true);
var cacheType = assembly.GetTypes().First(x => x.Name == "SslSessionsCache");
var field = cacheType.GetField("s_cachedCreds", BindingFlags.NonPublic | BindingFlags.Static);
if (field != null)
{
	var dic = (IDictionary?) field.GetValue(null);
	dic?.Clear();
}
      
      



( . - .)





, , SSL-, . : EventSource.





EventSource

.NET Core 3.0, Linux EventSource — , , . :





  1. EventListener, ( , , csv-);





  2. dotnet-trace .





, csv, , :





  1. .NET Core 3.1 Windows 10





  2. .NET Core 3.1 Linux





  3. .NET 5 Windows 10





  4. .NET 5 Linux





, , , :





An example of a table with logs of a .NET 5 client on Linux
.NET 5 Linux

:





  • HTTP- 3.1 5.0. , managed SocketsHttpHandler (, Linux libcurl). 3.1, AppContext, ;





  • ;





  • Windows Linux, .





. , ...





, , — .NET. .NET Github, issue Pull Request.





issue , .





issue

Issues , , , . , - SSL- Http-, , area-System.Net



area-System.Net.Security



.





issue , , , , Github Stack Overflow, , , Hello World . , , issue , issue , .. , , .





, , issue . , , :





  • : - , — , ;





  • .





.





API , , .





,

, , , nginx - . .NET, , C#, ASP.NET Core Kestrel. .





ASP.NET Core. :





  • , (, );





  • Kestrel, .





ASP.NET Core , . , - -, , , . Go, , . , :





func main() {
	caCert, err := ioutil.ReadFile("ca.cer")
	if err != nil {
		log.Fatal(err)
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)
	cfg := &tls.Config{
		ClientAuth: tls.RequireAndVerifyClientCert,
		//ClientCAs: caCertPool,
	}
	srv := &http.Server{
		Addr:      ":8443",
		Handler:   &handler{},
		TLSConfig: cfg,
	}
	log.Fatal(srv.ListenAndServeTLS("certificate.cer", "private.key"))
}

type handler struct{}

func (h *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	w.Write([]byte("PONG"))
}
      
      



HTTP-, . Go net/http PFX- , , . , (CA). , , . , , , .





Go . , 401, , , . :





http: TLS handshake error from 127.0.0.1:56082: tls: failed to verify client's certificate: x509: certificate signed by unknown authority
      
      



, .





— (CA) , - . , CA, , (Chain of Trust) CA, . , , . .





, . TLS- Server hello, , :





How does the TLS handshake work between client and server
TLS-

- , (, , ), , .





PFX-. PFX- :





  1. ( );





  2. , . , PFX- ;





  3. , .





PFX- , , OpenSSL:





openssl pkcs12 -in certificate.pfx -clcerts -nokeys | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > certificate.cer
openssl pkcs12 -in certificate.pfx -cacerts -nokeys -chain | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ca.cer
openssl pkcs12 -in certificate.pfx -nocerts -nodes | sed -ne '/-BEGIN PRIVATE KEY-/,/-END PRIVATE KEY-/p' > private.key
      
      



PFX- , . PFX- :





openssl pkcs12 -export -out certificate.pfx -in certificate.crt -certfile ca.crt -inkey privateKey.key
      
      



, Go , .NET PFX-, , . , .NET 5 X509Certificate2, .





,

, OpenSSL. , .. CA, . , : .





CA, , CA, CSR- (Certificate Signing Request). (extensions), . , , . , SCT , . , .





, , , :





  • .

    , ( ), — . - , .. ;





  • . ?





  • Let's Encrypt.

    , , .





Let's Encrypt.





Let's Encrypt

, Let's Encrypt :





  • , ;





  • DNS, .





NAT, , . Ubuntu 20.04, .





, Freenom. DNS IP- . , .. (, 404).





, , . , , nginx apache, — acme.sh standalone. : , CA .





Let's Encrypt PFX- .NET 5, — Go, . ! ! , !





, Microsoft. , . issue , , , , .





?

Tomas Weinfurt, Microsoft, , , .NET, SSL. Pull Request, , , ( , ). PR master- ( .NET 6), 5.0. 5.0.4.





. , .NET 5 SslStreamCertificateContext, issue, 3.1. SSL-, , , , , .





, , - , , , . Go , , . Go net/http , .





, / , , :





  • , ;





  • , . , , ;





  • Stack Overflow - , ;





  • , , ( , );





  • , , .





.NET , , , ( , , ). .NET 5 C# 9.0, records code generators.





, , Microsoft .NET , Github. .NET , .





, . , , , , . , - .





Thanks to @tycheg for helping with initial reproduction and debugging of the problem.








All Articles