0

I'm getting this error when I call AuthenticateAsClientAsync on the client's SslStream: The handshake failed due to an unexpected packet format.

All of this worked successfully using sockets, so the certificates and thumbprints are set up correctly, but it's not working in Kestrel. The only thing I can think of is that Kestrel doesn't allow listening on hostnames and the hostname validation fails on the client? Did I miss something? How would I dig deeper into this error to find the underlying issue?

Client-Side Console App

var client = new TcpClient();

await client.ConnectAsync("one.two.local", 8005);

var sslStream = new SslStream(client.GetStream());;

// TODO: Use TLS 1.3 once Microsoft fixes their bugs
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions // #### ERROR HERE ####
{
    CertificateRevocationCheckMode = X509RevocationMode.NoCheck,
    TargetHost = "one.two.local",
    EnabledSslProtocols = SslProtocols.Tls12,
    EncryptionPolicy = EncryptionPolicy.RequireEncryption,
    RemoteCertificateValidationCallback = (a, b, c, d) => true
});

Server-Side Host Builder:

Note that the X509CertificateUtility is loading certificates from the local machine store and the certificate is found.

WebHost.CreateDefaultBuilder(args)
    .ConfigureServices(services => { })
    .UseKestrel(options =>
    {
        options.Listen(IPAddress.Parse("127.0.0.9"), 8005, builder =>
        {
            // child thumbprint (obfuscated for posting)
            // certificate is found
            var certificate = X509CertificateUtility.Find("4F6FFF21dFFF0FF743FFF44338F41F8FFFF46491");

            // TODO: Use TLS 1.3 once Microsoft fixes their bugs
            builder.UseHttps(new HttpsConnectionAdapterOptions
            {
                SslProtocols = SslProtocols.Tls12,
                CheckCertificateRevocation = false,
                ClientCertificateMode = ClientCertificateMode.NoCertificate,
                ServerCertificate = certificate,
                ClientCertificateValidation = (a, b, c) => true
            });

            builder.UseConnectionHandler<KairosConnectionHandler>();
        });
    })
    .UseStartup<Startup>();

HOSTS file:

127.0.0.9   one.two.local

Cert Info

Subject: one.two.local
Enhanced Key Usage: Client + Server Authentication
Subject Alternative Name: DNS Name=one.two.local
Steve Andrews
  • 561
  • 3
  • 14
  • TLS has a certificate block where the server sends a list of certificate names to client. Then client looks up the certificate by the name. So the certificate has to be loaded on the client machine in the machine stores and the user stores. The certificate has to be loaded before the client sends a request. – jdweng Dec 26 '20 at 11:07
  • @jdweng That can't be true. For instance, if I visit a website I've never visited before, and they use TLS, I'm not required to already have their certificate. The certificate exchange is part of the handshake. More to my issue, this is running on the dev environment on my machine so the certificates are available. And it's not a certificate problem because certificates work fine using the same process without Kestrel. – Steve Andrews Dec 26 '20 at 21:38
  • TLS will handle the generation of the certificate and you do not need to handle the code. – jdweng Dec 26 '20 at 22:04

0 Answers0