sql-serveraws-lambdatls1.2.net-8.0microsoft-data-sqlclient

SQL Server error 31 - "Encryption(ssl/tls) handshake failed", in an AWS Lambda function


I have an AWS Lambda function (REST Api), which has been running for years, that just queries a stored procedure on a remote SQL Server. I wanted to make some changes to it and took the opportunity to update the code, since its target framework is .NET Core 2.1.

So I created a new C# project targeting .NET 8.0 and using the 'Lambda ASP.NET Core Web Minimal API' template. By the way, I had a hard time getting it to work, but I finally did it thanks to this article: Building Serverless .NET Minimal API (using Controller) with AWS Lambda.

But now I get this exception when I try to connect to my SQL Server:

A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 31 - Encryption(ssl/tls) handshake failed)

With this inner exception:

System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.

In the research I've done, almost everywhere says this exception has to do with using TLS 1.2 to connect to SQL Server. I have tried many solutions but without success.

This is the SQL Server environment (it is hosted on a local cloud server provider):

And this is the connection string I'm using:
$"Data Source={serverUrl};Initial Catalog={database};User ID={username};Password={pwd};"

Things I've tried so far:

  1. Updated SQL Server 2012 from SP3 to SP4 (version 11.0.7507 now).
  2. Enabled TLS 1.2 in Database server via RegEdit (TLS 1.2 support for Microsoft SQL Server).
  3. Added TrustServerCertificate=True, Encrypt=False and MultiSubnetFailover=True in the connection string.
  4. Changed from System.Data.SqlClient (version 4.8.6) to Microsoft.Data.SqlClient (version 5.2.0).

-- EDIT 1 --

After some exchange of information with users AlwaysLearning and Charlieface in the comments section, I've tried capturing more information using WireShark at the server, so I'll post some screenshots of that. I've used tcp port 1433 as a capture filter, and then I've used ssl as display filter.

When I execute the old AWS Lambda function (running on .NET Core 2.1), it communicates with the server using TLS v1.2 already, and it works:

Wiresharking old function 1

Wiresharking old function 2

But when I execute the new AWS Lambda function (running on .NET 8.0), it also communicates using TLS v1.2, but it's a bit different, at first it says it's TLSv1, but inside the message it says it's TLS v1.2 also:

Wiresharking new function 1

Wiresharking new function 2

And there are some extensions (marked in yellow) that were not used in the call that it's working:

Wiresharking new function 3

I guess some of those are the problem, maybe psk_key_exchange_modes and key_share?
Is it expecting some kind of key that I don't have?

-- EDIT 2 --

Looking at the Server Hello message that's exchanged between client and server when the old function is executed, it seems that TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028) was the Cipher Suite used in the handshake protocol:

Wiresharking old function 3

Those are the Cipher Suites listed in the Client Hello message when the old function is executed:

Wiresharking old function 4

When the new function is executed, this Cipher Suite (TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)) is not listed in the Client Hello message:

Wiresharking new function 4


Solution

  • After some research, I discovered that it is unusual that in a TLS handshake process the server receives a Client Hello message from the client and just ends the "conversation" abruptly with a [FIN, ACK] message, rather than a Server Hello response or an alert message demonstrating any problem that may have occurred when parsing the Client Hello message.

    Then I read somewhere that this unusual behavior could be caused by some issue with the Cipher Suites or some issue related to the certificate. I didn't have a certificate on the server, so I started wondering if that could be the problem. So I searched for a way to use the free TLS certificate generator Let's Encrypt with SQL Server and found this article:

    And this other article also has some good advice on how to configure a TLS certificate in SQL Server:

    After installing the TLS certificate on the server and associating it with SQL Server, the connection to SQL Server in the new AWS Lambda function started working!