Search code examples
c#sql-serverazureasp.net-coreazure-web-app-service

SQL Server Pre-Login Handshake (error: 31 - Encryption(ssl/tls) handshake failed)


I have a SQL server version 12.0.6205 and the following code in a .Net Core 3.1 (or 6) Web Api controller:

 var builder = new SqlConnectionStringBuilder
{
    DataSource = DataSource,
    UserID = UserID,
    Password = Password,
    InitialCatalog = InitialCatalog,
    ApplicationIntent = ApplicationIntent.ReadWrite,
    
    // Same result if true/true
    Encrypt = false,
    TrustServerCertificate = false
};

var connection = new SqlConnection(builder.ToString());
using (var cmd = new SqlCommand() { Connection = connection, CommandText = "SELECT TOP 1 * FROM [dbo].[Table]" })
{
    connection.Open(); // Breaks here
    var reader = cmd.ExecuteReader();
    Console.WriteLine(reader.HasRows);
}

Locally this code works without issues but when executing in Azure's App service it breaks when opening the connection with:

System.Data.SqlClient.SqlException (0x80131904): 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)

I also have been able to reproduce the error, locally, if creating a docker imaged based on appsvc/dotnetcore (any tag)

FROM mcr.microsoft.com/appsvc/dotnetcore:3.1-latest_20220105.1

ENV ASPNETCORE_URLS=http://+:80  

EXPOSE 8080
WORKDIR /home/site/wwwroot/
COPY . .

ENTRYPOINT ["dotnet", "Test.dll"]

Solution

  • Like @DraggonDragger said this is a TLS issue but in my specific case I can't rely on the SQL server being updated to allow TLS 1.2 therefore I had to allow TLS 1.0 in the application.

    I ended up following this answer: https://stackoverflow.com/a/61523341/17892120;

    Essentially, for docker images, adding this line is enough: RUN sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf

    And for Azure's App Service, we can add sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf && dotnet Test.dll for the startup command.

    For future reference, there's also a discussion about this in GitHub, link.