C# .NET Core 3.1 无法建立 SSL 连接

问题描述 投票:0回答:4

我在 SAP 的 Docker 容器内使用带有 C# ASP.NET Core 3.1 服务的 OData 服务以及客户自签名证书。

在此期间,我尝试了一千种方法,但错误仍然存在。

System.InvalidOperationException:处理时发生错误 这个请求。 mdt2oowvsap_1 | ---> System.Data.Services.Client.DataServiceTransportException:SSL 无法建立连接,请参阅内部异常。遥控器 根据验证程序,证书无效。

即使是不安全的解决方案,例如使用 HttpClientHandler.ServerCertificateCustomValidationCallback 直接返回 true 也没有改变任何东西。

 public MyService()
 {
        :
        handler = new HttpClientHandler()
        {
            Credentials = new NetworkCredential(Username, Password, Domain),
            PreAuthenticate = true,                
            ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
            {
                if (sslPolicyErrors == SslPolicyErrors.None)
                {
                    logger.LogDebug($"No SSL policy errors!");
                    return true;   //Is valid
                }

                logger.LogDebug($"Get certificate hash: {cert.GetCertHashString()}");
                // From: https://stackoverflow.com/questions/2675133/c-sharp-ignore-certificate-errors
                if (!String.IsNullOrEmpty(certificateHash) && cert.GetCertHashString().Equals(certificateHash))
                {
                    // Get hash string via: openssl s_client -connect <host>:<port> < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin
                    // see: https://stackoverflow.com/questions/5164804/get-certificate-fingerprint-of-https-server-from-command-line
                    logger.LogDebug($"Using certificate hash: {certificateHash}");
                    return true;
                }
                return false;
            },
            UseCookies = true,
            CookieContainer = cookieContainer
        };
        String[] files = Directory.GetFiles("./certs/", "*.*", SearchOption.TopDirectoryOnly);
        logger.LogInformation($"Found {files.Length} certificate files");
        // see: https://stackoverflow.com/questions/40014047/add-client-certificate-to-net-core-httpclient
        foreach (string cfile in files)
        {
            try
            {
                logger.LogDebug($"Try adding {cfile} as trusted client certificate...");
                handler.ClientCertificates.Add(new X509Certificate2(Path.GetFullPath(cfile)));
            }catch(Exception e)
            {
                logger.LogInformation($"Exception while adding certificate file {cfile} to 'ClientCertificates'");
                logger.LogError(e.ToString());
            }
        }
        httpClient = new HttpClient(handler);
        :
 }

最后一次尝试是下载证书并使用 ClientCertificates.Add 将其提供给 HttpClientHandler。没有成功。

使用curl,传递此证书文件即可。

 $> curl --location --request GET 'https://customer.de:1234/sap/opu/odata/something/useful_srv' \
 --header 'Authorization: Basic ABCDEFGHIJKLMNOPQRST='
 curl: (60) SSL certificate problem: self signed certificate
 More details here: https://curl.haxx.se/docs/sslcerts.html
 :
 $> echo -n | openssl s_client -connect customer.de:1234 -servername customer.de | \
 openssl x509 > /full/path/to/customer.cert
 depth=0 CN = customer.de
 verify error:num=18:self signed certificate
 verify return:1
 depth=0 CN = customer.de
 verify return:1
 DONE
 $> 
 $> curl --location --cacert '/full/path/to/customer.cert' --request GET \
 'https://customer.de:1234/sap/opu/odata/something/useful_srv' \
 --header 'Authorization: Basic ABCDEFGHIJKLMNOPQRST='
 <?xml version="1.0" encoding="utf-8"?><app:service xml:lang="de" xml:base="https:blablabla.../></app:service>
 $> _

还有人有其他想法吗?

查看的解决方案(不完整):

提前致谢。

c# asp.net-core ssl httpclient
4个回答
2
投票

问题的解决方案是使“自签名”证书可用于 Docker 容器或其包含的操作系统(Ubuntu)并提供给它

cp 证书/customer.cert /usr/local/share/ca-certificates/customer.crt &&
更新 ca 证书

现在可以通过 SSL 进行通信。


2
投票

我想在 Buckaroo Banzai 的答案中补充一点,对于在 docker 容器中运行 .NET 应用程序的其他人来说,默认情况下甚至可能不会安装 update-ca-certificates 包。

通过执行以下命令获取 shell 访问权限:

sudo docker exec -it containerName /bin/bash

并执行此命令来更新软件包列表,安装并运行 update-ca-certificates:

apt update && \
apt install -y ca-certificates && \ 
update-ca-certificates

现在我可以从容器内运行的 .NET 应用程序再次与我的(和其他人)Web api 进行通信。

要使其永久化,您应该将此代码段添加到 ENTRYPOINT 之前使用的图像的 dockerfile 中。

RUN \ 
  apt update && \
  apt install -y ca-certificates && \
  update-ca-certificates

在此处找到有关此问题发生原因的详细解释,并更好地了解证书颁发机构的工作原理:

什么是CA证书,为什么需要它?


0
投票

问题:使用minio sdk,出现错误:

MinIO API responded with message=Connection error: The SSL connection could not be established, see inner exception.. Status code=0, response=The SSL connection could not be established, see inner exception., content=

我的回答: 我注册了自签名证书:

Import-Certificate -FilePath “public.crt” -CertStoreLocation 'Cert:\LocalMachine\Root'

系统回显: PSParentPath:Microsoft.PowerShell.Security\Certificate::LocalMachine\Root

指纹主题


E021FFABABAF32318D31BB18867F3BFAB788FFC0 OU=BETVSYS ndy@andy-tp(andy),O=Certgen 开发

所以问题解决了。不要更改任何代码。 参考链接: 1 https://github.com/minio/certgen 2 https://github.com/minio/minio-go/issues/1000#issuecomment-550262204


0
投票

谢谢你们的灵感,伙计们。我在 Docker 容器中运行的 Ubuntu 服务器上遇到了类似的问题,我想我会分享我的解决方案,以防有人遇到同样的情况。

Docker 容器环境:

  • Ubuntu 服务器 22.04.3 LTS
  • .NET SDK 8.0.100
  • ASP.NET Core 最小 Web API
  • Blazor Web 应用程序(服务器,而不是 WebAssembly)

解决方案

这篇 Microsoft 文章提供了解决方案,总结如下:

  1. 验证 OpenSSL 是否已安装:
    openssl version -a
  2. 如果未安装:
    sudo apt install openssl
  3. 创建开发者证书:
    dotnet dev-certs https
  4. 导出证书:
    sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
  5. 将证书添加到证书存储区:
    sudo update-ca-certificates
  6. 预期输出:

正在更新 /etc/ssl/certs 中的证书... rehash:警告:跳过 ca-certificates.crt,它不包含完全相同的一个证书或 CRL 添加 1 个,删除 0 个;完毕。运行钩子 /etc/ca-certificates/update.d...完成。

验证

  1. 列出系统默认存储中所有可用的SSL证书:
    ls -lah /etc/ssl/certs
  2. 列出我们刚刚添加的证书:
    ls -lah /etc/ssl/certs | grep https.crt
  3. 预期输出:

https.pem -> /usr/local/share/ca-certificates/aspnet/https.crt

© www.soinside.com 2019 - 2024. All rights reserved.