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:
11.0.7507
now).TrustServerCertificate=True
, Encrypt=False
and MultiSubnetFailover=True
in the connection string.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:
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:
And there are some extensions (marked in yellow) that were not used in the call that it's working:
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:
Those are the Cipher Suites listed in the Client Hello
message when the old function is executed:
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:
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!