社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

填坑 | .NET 5在Docker中访问MSSQL报错

dotNET跨平台 • 3 年前 • 517 次点击  

【.NET Core作者 / Edison Zhou

不知道你有没有在.NET Core/.NET 5的Docker访问MS SQL Server数据库,如果有,那么很有可能会遇到这个错误。

1SSL版本错误

最近在公司用.NET 5重构部分业务服务,由于之前老系统使用了MS SQL Server数据库,因此本次重构也决定继续使用。但是,在将.NET 5应用部署到Docker中通过Swagger测试时,却报了以下一个错误:

Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 35 - An internal exception was caught) ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.

从字面意思来看,看不出来是啥,只能定位这一句 SSL_ERROR_SSL。搜索一番,发现在.NET Core/.NET 5的容器镜像中的OpenSSL的最低协议版本要求为TLSv1.2,而我们的MS SQL Server所用的版本较低,不支持TLSv1.2只支持TLSv1

我们可以进入容器内部去验证下:

# docker exec -it  /bin/bash# cat /etc/ssl/openssl.cnf
.......[system_default_sect] MinProtocol = TLSv1.2 CipherString = DEFAULT@SECLEVEL=2

因此,明确了问题,直接在容器内部更改一下:将TLSv1.2改为TLSv1即可

# docker exec -it  /bin/bash# vi /etc/ssl/openssl.cnf
.......[system_default_sect] MinProtocol = TLSv1 CipherString = DEFAULT@SECLEVEL=2

更改完成后,再次访问接口,就不会报错了。

2修改Dockerfile

上面的方法只是一个临时方案,重新打镜像运行又会恢复为TLSv1.2。因此,我们需要更改Dockerfile,让其在源镜像中就更改为TLSv1。

这里以一个简单的Dockerfile为例,只需要在微软.NET 5镜像源的层中增加一行指令即可:

RUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnf

完整Dockerfile示例:

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS baseWORKDIR /appRUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnfEXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS buildWORKDIR /srcCOPY ["AuthCenter.API/AuthCenter.API.csproj", "AuthCenter.API/"]RUN dotnet restore "AuthCenter.API/AuthCenter.API.csproj"COPY . .WORKDIR "/src/AuthCenter.API"RUN dotnet build "AuthCenter.API.csproj" -c Release -o /app/build
FROM build AS publishRUN dotnet publish "AuthCenter.API.csproj" -c Release -o /app/publish
FROM base AS finalWORKDIR /appCOPY --from=publish /app/publish .ENTRYPOINT ["dotnet", "AuthCenter.API.dll"]

其他相关联的OpenSSL错误:

Microsfot.Data.SqlClient.SqlException(0x80131904):A connection was successfully established with the server, but then an error occurred during the pre-login handshake.(provide:SSL Provider,error:31 - Encryption(ssl/tls) handshake failed)

这个错误和上面的error: 35类似,也是TLS协议版本较高,而SQL Server不支持。修改方法也是改为TLSv1,这里需要注意的是,我发现网上很多文章都是建议改为TLSv1.0,也就是下面的指令:

RUN sed -i 's/TLSv1.2/TLSv1.0/g' /etc/ssl/openssl.cnf

对于网上大多数童鞋,上面的语句是适用的,但是也有一些和我一样的,即使使用了上面的语句还不行。一番搜索发现,需要改为TLSv1(即去掉小数点)才能工作。

3关于TLS协议

TLS是在TCP传输层之上,应用层之下实现的网络安全方案。在TCP/IP四层网络模型中属于应用层协议。TLS协议在两个通信应用程序之间提供数据保密性和数据完整性,另外还提供了连接身份可靠性方案。

UDP则使用DTLS协议实现安全传输,和TLS协议类似。

TLS协议的设计目的如下:

(1)加密安全:TLS应用于双方之间建立安全连接,通过加密,签名,数据摘要保障信息安全。

(2互操作性:程序员在不清楚TLS协议的情况下,只要对端代码符合RFC标准的情况下都可以实现互操作。

(3可扩展性:在必要时可以通过扩展机制添加新的公钥和机密方法,避免创建新协议。

(4相对效率:加密需要占用大量CPU,尤其是公钥操作。TLS协议握手完成后,通过对称密钥加密数据。TLS还集成了会话缓存方案,减少需要从头建立连接的情况。

TLS协议所处的位置如下所示:

更多关于TLS协议的介绍:

https://www.cnblogs.com/Jack-Blog/p/13170728.html

End总结

在要求安全性越来越高的前提下,TLSv1.2被广泛应用,为了适配MS SQL Server的低版本,可以选择在Dockefile中降低TLS协议最低版本要求来解决问题。不过,这毕竟是一个不安全的方法,如果有条件,还是建议升级MS SQL Server所在服务器的TLS配置,使其支持TLSv1.2。

年终总结:Edison的2020年终总结
数字化转型:Edison的数字化转型之旅总结
C#刷题:C#刷剑指Offer算法题系列文章目录
.NET面试:.NET开发面试知识体系八股文
.NET大会:2020年中国.NET开发者大会PDF资料


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/119589
 
517 次点击