赞
踩
.net6在linux环境中连接部分低版本的sqlserver出现报错:
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)
解决方案:
(1)linux配置ssl降级,参考连接:centos下 连接sqlserver (provide:SSL Provider,error:31 - Encryption(ssl/tls) handshake failed)-腾讯云开发者社区-腾讯云
(2)将system.Data.SqlClient包替换为Microsoft.Data.SqlClient3.0.1
注意,需要将引用也换了
(3)链接字符串修改:TrustServerCertificate=true;Encrypt=false;
网上的资料不多,很多说改连接字符串内容的,对我的情况无效,单独将linux中的openssl降级也无效,几种一起上才行,我觉得这里的主要起作用的还是sqlclient包降级。
原因:为什么包一降级就行了?是否高级别的sqlclient强制使用了某些加密的密码套件而sqlserver不支持这些密码套件?这里涉及的知识我不了解,搞不清来龙去脉,有懂得朋友可以指点一下
---更新---
最近学习计算机网络后,联想到这个报错,再次分析一下:
sqlserver的数据库连接,使用的微软自家的TDS协议,这个协议是基于SSL/TLS的。根据报错最后的内容:Encryption(ssl/tls) handshake failed。可以得知是在建立TLS连接的时候握手失败了。
下面贴张图大概讲解一下TLS连接的原理:
TLS连接分为握手和会话阶段,以下文字来源于课本内容:(讲讲握手阶段,毕竟报错已经明确说明了是握手失败)
***************
我们先介绍协议 TLS的握手阶段。握手阶段包括:(1)协商加密算法,(2)服务器鉴别,(3)生成主密钥,(4)服务器用自己的私钥把主密钥解密出来
(重点内容)
(1)协商加密算法客户A向服务器B发送自己选定的加密算法(包括密钥交换算法)。服务器B从中确认自己所支持的算法,同时把自己的CA数字证书发送给A。这里要说明一下,从TLS1.0更新到1.1和 1.2版本时,每一次更新都增加了当时认为是更加安全可靠的加密算法。为了协议的向后兼容,对老版本中的不太安全的数十种算法也都保留下来了。这就造成协商过程非常耗时,需要花费2倍RTT的时间(通常记为2-RTT)。因此最新的TLS 1.3版本把陈旧的很多种算法统统取消(例如MD5,SHA-1,DES,3DES等),只留下几种最安全的算法。客户不是把自己所有的加密算法都告诉服务器,供服务器来挑选,而是猜测服务器可能愿意使用什么加密算法,把自己选定的加密算法直接发送给服务器,让服务器来确认。这就把“协商”时间缩短为1-RTT。
(2)服务器鉴别 客户 A用数字证书中CA的公钥对数字证书进行验证鉴别。
(3)生成主密钥 客户A按照双方确定的密钥交换算法生成主密钥MS(Master Secret)。客户 A用B的公钥PKB对主密钥MS加密,得出加密的主密钥PKB(MS),发送给服务器 B。请注意,在有关TLS的文档中,密钥一词使用的是Secret,而不是Key。
(4)服务器B用自己的私钥把主密钥解密出来:SKn(PKa(MS)) =MS。这样,客户A和服务器B都拥有了为后面的数据传输使用的共同的主密钥MS。
**************
根据上面这段话中的橙色字体的内容,得知不同的TLS版本支持的加密方法是不一样的,我的场景中,服务器的sqlserver版本非常古老。估计只支持TLS1,而客户端用的是.net6,环境是linux,所以此处需要linux配置ssl降级,原来默认是TLS1.3。
可是为什么sqlclient包需要降级呢???
还有为什么不降级的情况下,在windows系统可以正常连接sqlserver服务器?(难道是windows默认是TLS1.0的配置)
文中提到:客户不是把自己所有的加密算法都告诉服务器,供服务器来挑选,而是猜测服务器可能愿意使用什么加密算法,把自己选定的加密算法直接发送给服务器,让服务器来确认。
这里的决定发送哪几种加密算法的“客户”,是指的操作系统,还是应用程序?
这些问题我暂时没有确切答案。如果有知道的朋友可以指点一下
关于sqlserver和tls的官方信息
--------再次更新------
之前以为这个连接问题只会出现在linux上,结果今天在Windows上也出现了
客户端:windows系统,使用java连接sqlserver
服务器端:sqlserver2012
这次在客户端,使用c#连接sqlserver时正常连接,而切换到java则报tls协议不一致错误。
从这一点起码排除了操作系统的干扰。我把java版本切换到1.8,还是报错(之前是21)
之后从网上找到方法,修改java.securety文件里的参数(实际是因为默认的配置里禁用了tls1.0和1.1的加密算法,修改配置实际上是把这些加密算法启用,这样的话,客户端在握手时,就会把这些加密算法发给服务器,让服务器从里面选一个它支持的算法)。
从这一点看,应用层也能够控制使用哪些算法来进行jtls握手。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。