You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker与Ocelot环境下自签名证书PartialChain错误排查求助

问题描述

本地部署两个Docker容器:

  • 容器1:基于Ocelot实现的API网关,监听端口6001
  • 容器2:后端服务,监听端口7001

已通过OpenSSL生成自签名证书,网关的Ocelot配置如下:

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/Role",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "192.168.0.101",
          "Port": 7001
        }
      ],
      "UpstreamPathTemplate": "/api/role",
      "UpstreamHttpMethod": [ "get" ]
    }   
  ],
  "GlobalConfiguration": {
    "BaseURL": "https://192.168.0.101:6001"
  }
}

直接访问https://192.168.0.101:7001/api/role和https://192.168.0.101:6001/api/index时,浏览器无证书错误可正常访问,但通过网关访问https://192.168.0.101:6001/api/role时出现问题:

  1. 浏览器显示“This page isn’t working”
  2. 控制台报错:
gateway  | info: Ocelot.RateLimit.Middleware.ClientRateLimitMiddleware[0]
gateway  |       requestId: 0HN0H1OSQDUEG:00000001, previousRequestId: No PreviousRequestId, message: 'EndpointRateLimiting is not enabled for /api/Role'
gateway  | info: Ocelot.Authentication.Middleware.AuthenticationMiddleware[0]
gateway  |       requestId: 0HN0H1OSQDUEG:00000001, previousRequestId: No PreviousRequestId, message: 'No authentication needed for /api/role'
gateway  | info: Ocelot.Authorization.Middleware.AuthorizationMiddleware[0]
gateway  |       requestId: 0HN0H1OSQDUEG:00000001, previousRequestId: No PreviousRequestId, message: '/api/Role route does not require user to be authorized'
gateway  | warn: Ocelot.Responder.Middleware.ResponderMiddleware[0]
gateway  |       requestId: 0HN0H1OSQDUEG:00000001, previousRequestId: No PreviousRequestId, message: 'Error Code: ConnectionToDownstreamServiceError Message: Error connecting to downstream service, exception: System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
gateway  |        ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: PartialChain
gateway  |          at System.Net.Security.SslStream.SendAuthResetSignal(ReadOnlySpan`1 alert, ExceptionDispatchInfo exception)
gateway  |          at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
gateway  |          at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
gateway  |          at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)

需求:在Docker Desktop上使用自签名证书部署SSL容器,请问遗漏了哪些配置?


解决方案

核心问题

错误日志中的PartialChain表明:浏览器已手动信任自签名证书,但网关容器内的.NET运行时环境未将该证书加入信任根存储,导致无法验证后端服务的证书链完整性。

遗漏的配置及修复步骤

1. 将自签名CA证书导入网关容器的信任存储

网关作为客户端访问后端HTTPS服务时,需要信任后端的自签名证书。需将生成的CA证书导入容器的系统信任根:

  • Linux容器:修改网关Dockerfile,添加证书导入步骤:
    # 假设CA证书文件为ca.crt,复制到容器证书目录
    COPY ca.crt /usr/local/share/ca-certificates/
    # 更新系统证书存储
    RUN update-ca-certificates
    
  • Windows容器:导入到Windows根证书存储:
    COPY ca.crt C:/temp/
    RUN certutil -addstore -f "Root" C:/temp/ca.crt
    

2. 确保自签名证书包含正确的SAN字段

生成自签名证书时,必须添加Subject Alternative Name(SAN),包含后端服务的IP(192.168.0.101)或主机名,否则网关会认为证书标识不匹配。

  • 创建OpenSSL配置文件openssl.cnf:
    [req]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_ca
    
    [req_distinguished_name]
    commonName = 192.168.0.101
    
    [v3_ca]
    subjectAltName = IP:192.168.0.101
    
  • 生成证书时指定配置文件:
    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -config openssl.cnf -nodes
    

3. 测试环境临时配置:跳过证书验证(生产禁用)

若仅为测试,可临时让Ocelot的HttpClient跳过证书验证:

  • 修改Ocelot配置,添加HttpHandlerOptions:
    {
      "Routes": [
        {
          "DownstreamPathTemplate": "/api/Role",
          "DownstreamScheme": "https",
          "DownstreamHostAndPorts": [
            {
              "Host": "192.168.0.101",
              "Port": 7001
            }
          ],
          "UpstreamPathTemplate": "/api/role",
          "UpstreamHttpMethod": [ "get" ],
          "HttpHandlerOptions": {
            "ServerCertificateCustomValidationCallback": "IgnoreCertificateError"
          }
        }   
      ],
      "GlobalConfiguration": {
        "BaseURL": "https://192.168.0.101:6001"
      }
    }
    
  • 在网关代码中注册自定义验证逻辑:
    services.AddOcelot()
        .AddDelegatingHandler(() => new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = (_, _, _, _) => true
        });
    

4. 验证容器网络互通

进入网关容器,测试是否能正常访问后端服务:

docker exec -it <gateway-container-id> curl https://192.168.0.101:7001/api/role

若curl返回相同证书错误,说明容器未信任证书,按步骤1修复即可。


内容的提问来源于stack exchange,提问作者Abhishek Vyas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:48:14