• .NET 5在Docker中访问MSSQL报错


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

    1 SSL版本错误

    最近在公司用.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 <docker-name> /bin/bash
    # cat /etc/ssl/openssl.cnf
    
    .......
    [system_default_sect] 
    MinProtocol = TLSv1.2 
    CipherString = DEFAULT@SECLEVEL=2

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

    # docker exec -it <docker-name> /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 base
    WORKDIR /app
    RUN sed -i 's/TLSv1.2/TLSv1/g' /etc/ssl/openssl.cnf
    EXPOSE 80
    
    FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
    WORKDIR /src
    COPY ["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 publish
    RUN dotnet publish "AuthCenter.API.csproj" -c Release -o /app/publish
    
    FROM base AS final
    WORKDIR /app
    COPY --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协议的介绍:点此阅读

    4 总结

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

  • 相关阅读:
    基于 mysql 异步驱动的非阻塞 Mybatis【待验证】
    Hive SQL优化方式及使用技巧
    使用Guava-RateLimiter限流控制qps
    hive 时间戳函数之unix_timestamp,from_unixtime
    Hive实现自增列的两种方法
    shell 下 urlencode/urldecode 编码/解码的方法
    awk使用shell变量,shell获取awk中的变量值
    shell脚本删除远程过期文件
    linux下多进程同时操作文件
    hive学习----Hive表的创建
  • 原文地址:https://www.cnblogs.com/edisonchou/p/dotnet5_on_docker_problem_tlsv1.html
Copyright © 2020-2023  润新知