.NET 8连接SQL Server 2012时SSL/TLS握手失败求助
.NET 8连接SQL Server 2012预登录握手SSL/TLS失败问题解决
问题描述
从.NET 6升级至.NET 8以获取LTS支持,但暂无法升级SQL Server 2012,连接数据库时出现预登录握手阶段报错,提示SSL/TLS握手失败。
报错堆栈
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) ---> System.IO.EndOfStreamException: End of stream reached ...(省略中间堆栈信息) at sqltest.Program.Main(String[] args) in /src/src/ConsoleAppConnectivity/Program.cs:line 29 ClientConnectionId:d974cac0-f1a3-4864-9867-17360db6e502
复现步骤
使用以下控制台应用及Dockerfile可复现问题:
控制台应用代码
using System.Data.SqlClient; namespace sqltest { class Program { static void Main(string[] args) { try { var builder = new SqlConnectionStringBuilder { DataSource = "<host>", UserID = "<user>", Password = "<pw>", InitialCatalog = "<DB>", TrustServerCertificate = true, Encrypt = false }; using SqlConnection connection = new(builder.ConnectionString); Console.WriteLine("\nQuery data example:"); Console.WriteLine("=========================================\n"); connection.Open(); var sql = "SELECT top 10 * FROM dbo.<Table>"; using SqlCommand command = new(sql, connection); using SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) { Console.WriteLine("{0} {1}", reader.GetString(0), reader.GetString(1)); } } catch (SqlException e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nDone. Press enter."); Console.ReadLine(); } } }
Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base COPY certificates/ca/cert.pem /etc/ssl/certs/cert.pem RUN update-ca-certificates WORKDIR /app FROM mcr.microsoft.com/dotnet/sdk:8.0 as build COPY certificates/ca/cert.pem /etc/ssl/certs/cert.pem RUN update-ca-certificates WORKDIR /src COPY . . RUN dotnet restore src/ConsoleAppConnectivity --ignore-failed-sources RUN dotnet build src/ConsoleAppConnectivity/ConsoleAppConnectivity.csproj -c Release -o /app --no-restore FROM build AS publish RUN dotnet publish src/ConsoleAppConnectivity/ConsoleAppConnectivity.csproj -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . # Recommended change to make it work RUN sed -i 's/CipherString = DEFAULT@SECLEVEL=2/CipherString = DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf ENTRYPOINT ["dotnet", "ConsoleAppConnectivity.dll"]
预期行为
成功查询并返回dbo.<Table>中的前10条记录。
技术环境
- Microsoft.Data.SqlClient版本:5.1.2
- .NET目标框架:8
- SQL Server版本:2012(64位标准版)
已尝试操作
- 测试多个.NET 8镜像均出现该问题,切换至.NET 5/6/7镜像及对应目标框架时连接正常;
- 修改
/etc/ssl/和/usr/lib/ssl/下的openssl.cnf,尝试添加/修改SECLEVEL、MinProtocol属性,但无效果; - 执行修改CipherString为
DEFAULT@SECLEVEL=1的命令,未解决问题。
解决方案
1. 启用.NET对旧TLS协议的支持
.NET 8默认禁用了TLS 1.0和TLS 1.1,而未打SP4补丁的SQL Server 2012仅支持这些旧协议。可通过以下方式开启支持:
方式一:代码中添加配置
在Main方法开头加入:
// 启用旧版加密套件支持 AppContext.SetSwitch("System.Net.DontEnableSchUseStrongCrypto", true); // 允许使用系统默认之外的旧TLS版本 AppContext.SetSwitch("System.Net.DontEnableSystemDefaultTlsVersions", true);
方式二:Docker环境变量配置
在Dockerfile的final阶段添加:
ENV DOTNET_SYSTEM_NET_DISABLESCHUSESTRONGCRYPTO=1 ENV DOTNET_SYSTEM_NET_DONTENABLESYSTEMDEFAULTTLSVERSIONS=1
2. 完整配置OpenSSL协议和加密级别
仅修改CipherString不足以解决问题,需确保OpenSSL允许SQL Server 2012支持的协议。将Dockerfile中的配置命令替换为:
RUN sed -i '/\[system_default_sect\]/a MinProtocol = TLSv1.0' /etc/ssl/openssl.cnf && \ sed -i 's/CipherString = DEFAULT@SECLEVEL=2/CipherString = DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf
该命令会在system_default_sect节点下添加TLSv1.0支持,同时降低加密级别。
3. 升级SQL Server 2012的TLS支持(推荐)
若SQL Server 2012已安装SP4及后续累积更新,建议在服务器端启用TLS 1.2:
- 修改服务器注册表,启用TLS 1.2并禁用旧协议;
- 应用端连接字符串添加
SslProtocol=Tls12,无需启用旧协议即可兼容。
4. 升级Microsoft.Data.SqlClient版本
将Microsoft.Data.SqlClient升级至最新稳定版(如5.2.x或更高),新版本可能修复了.NET 8下的兼容性问题。
内容的提问来源于stack exchange,提问作者Diego Sanabria
相关产品推荐
相关产品推荐

