503 服务不可用 - SSL 握手失败

您正在查看 Apigee Edge 文档。
前往 Apigee X 文档
信息

问题

客户端应用收到 HTTP 状态代码 503 Service Unavailable 和错误代码 messaging.adaptors.http.flow.SslHandshakeFailed,以此响应 API 调用。

出错提示

客户端应用获取以下响应代码:

HTTP/1.1 503 Service Unavailable

此外,您可能会看到以下错误消息:

{
   "fault":{
      "faultstring":"SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target",
      "detail":{
         "errorcode":"messaging.adaptors.http.flow.SslHandshakeFailed"
      }
   }
}

可能的原因

由于多种原因,在 Apigee Edge 的消息处理器和后端服务器之间的 SSL 握手过程中出现故障时,您可能会收到状态代码 503 Service Unavailable 和错误代码 messaging.adaptors.http.flow.SslHandshakeFailedfaultstring 中的错误消息通常表示导致此错误的可能的高级原因。

根据 faultstring 中观察到的错误消息,您需要使用适当的技术来排查问题。本剧本介绍了如果您在 faultstring 中看到错误消息 SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target ,该如何排查此错误。

在 Apigee Edge 的消息处理器和后端服务器之间的 SSL 握手过程中,会出现此错误:

  • 如果 Apigee Edge 的消息处理器的truststore
    • 包含与后端服务器的完整证书链不匹配的证书链,或者
    • 不包含后端服务器的完整证书链
  • 如果后端服务器提供的证书链:
    • 包含与目标端点中指定的主机名不匹配的 完全限定域名 (FQDN)
    • 包含的证书链不正确或不完整

此问题的可能原因如下:

原因 说明 适用的问题排查说明
消息处理器的信任库中的证书或证书链不正确/不完整 存储在 Apigee Edge 消息处理器的信任库中的证书和/或其链与后端服务器的证书链不匹配,或者不包含后端服务器的完整证书链。 Edge Private Cloud 和 Public Cloud 用户
后端服务器证书中的 FQDN 与目标端点中的主机名不匹配 后端服务器提供的证书包含的 FQDN 与目标端点中指定的主机名不匹配。 Edge Private Cloud 和 Public Cloud 用户
后端服务器提供的证书或证书链不正确/不完整 后端服务器提供的证书链不正确或不完整。 Edge Private Cloud 和 Public Cloud 用户

常见诊断步骤

您可以使用以下工具/方法来诊断此错误:

API 监控

方法 1:使用 API Monitoring

如需使用 API 监控功能诊断错误,请执行以下操作:

  1. 以具有 适当角色的用户身份 登录 Apigee Edge 界面
  2. 切换到您要调查问题的组织。

  3. 前往分析 > API 监控 > 调查页面。
  4. 选择您发现错误的具体时间范围。
  5. 绘制故障代码时间的对比图。

  6. 选择包含故障代码 messaging.adaptors.http.flow.SslHandshakeFailed 的单元格,如下所示:

    查看放大图片

  7. 系统会显示有关故障代码 messaging.adaptors.http.flow.SslHandshakeFailed 的信息,如下所示:

    查看放大图片

  8. 点击查看日志 ,然后展开失败请求对应的行。

    查看放大图片

  9. 日志窗口中,记下以下详细信息:
    • 请求消息 ID
    • 状态代码503
    • 故障来源target
    • 故障代码messaging.adaptors.http.flow.SslHandshakeFailed

跟踪记录

程序 2:使用 Trace 工具

如需使用 Trace 工具诊断错误,请执行以下操作:

  1. 启用跟踪会话,并选择以下任一选项:
    • 等待出现错误代码为 messaging.adaptors.http.flow.SslHandshakeFailed503 Service Unavailable 错误,或
    • 如果您可以重现问题,请进行 API 调用以重现问题 503 Service Unavailable
  2. 确保已启用显示所有 FlowInfo

  3. 选择一个失败的请求,然后检查轨迹。
  4. 浏览轨迹的不同阶段,找到发生故障的位置。
  5. 您通常会在“Target Request Flow Started”(目标请求流程已启动)阶段之后发现错误,如下所示:

    查看放大图片

  6. 请注意轨迹中的以下值:
    • 错误SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    • error.cause:PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    • error.class: com.apigee.errors.http.server.ServiceUnavailableException
    • 错误 SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 的值表示 SSL 握手失败,因为 Apigee Edge 的消息处理器无法验证后端服务器的证书。
  7. 在轨迹中找到 AX(记录的分析数据)阶段,然后点击它。
  8. 向下滚动到阶段详细信息错误标头部分,确定 X-Apigee-fault-codeX-Apigee-fault-sourceX-Apigee-Message-ID 的值,如下所示:

    查看放大图片

  9. 请注意 X-Apigee-fault-codeX-Apigee-fault-sourceX-Apigee-Message-ID 的值:
  10. 错误标头
    X-Apigee-fault-code messaging.adaptors.http.flow.SslHandshakeFailed
    X-Apigee-fault-source target
    X-Apigee-Message-ID MESSAGE_ID

NGINX

程序 3:使用 NGINX 访问日志

如需使用 NGINX 访问日志诊断错误,请执行以下操作:

  1. 如果您是私有云用户,则可以使用 NGINX 访问日志来确定有关 HTTP 503 Service Unavailable 的关键信息。
  2. 检查 NGINX 访问日志:

    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log

  3. 搜索以查看在特定时长内(如果问题发生在过去)是否存在任何错误代码为 messaging.adaptors.http.flow.SslHandshakeFailed503 错误,或者是否仍有任何请求失败并显示 503
  4. 如果您发现任何 503 错误,且 X-Apigee-fault-code messaging.adaptors.http.flow.SslHandshakeFailed 的值匹配,请确定 X-Apigee-fault-source 的值。

    NGINX 访问日志中的 503 错误示例

    查看放大图片

    上述 NGINX 访问日志中的示例条目具有以下 X-Apigee-fault-codeX-Apigee-fault-source 值:

    标头
    X-Apigee-fault-code messaging.adaptors.http.flow.SslHandshakeFailed
    X-Apigee-fault-source target

消息处理器日志

程序 4:使用消息处理器日志

  1. 使用 API 监控、Trace 工具或 NGINX 访问日志(如常见诊断步骤中所述)确定失败请求的消息 ID。
  2. 在消息处理器日志 (/opt/apigee/var/log/edge-message-processor/logs/system.log) 中搜索特定请求消息 ID。您可能会看到以下错误:

    org:myorg env:test api:MyProxy rev:1
    messageid:myorg-28247-3541813-1
    NIOThread@1 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() :
    SSLClientChannel[Connected: Remote:X.X.X.X:443
    Local:192.168.194.140:55102]@64596 useCount=1
    bytesRead=0 bytesWritten=0 age=233ms  lastIO=233ms
    isOpen=true handshake failed, message: General SSLEngine problem
    

    上述错误表明消息处理器和后端服务器之间的 SSL 握手失败。

    随后,系统会显示包含详细堆栈轨迹的异常,如下所示:

    org:myorg env:test api:MyProxy rev:1
    messageid:myorg-28247-3541813-1
    NIOThread@1 ERROR ADAPTORS.HTTP.FLOW - RequestWriteListener.onException() :
    RequestWriteListener.onException(HTTPRequest@1522922c)
    javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    	at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1478)
    	at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535)
    	... <snipped>
    Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    	at sun.security.ssl.Alerts.getSSLException(Alerts.java:203)
    	at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1728)
    	... <snipped>
    Caused by: sun.security.validator.ValidatorException: PKIX path building failed:
    sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid
    certification path to requested target
    	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
    	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
    	... <snipped>
      

    请注意,握手失败的原因如下:

    Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    这表示 SSL 握手失败,因为 Apigee Edge 的消息处理器无法验证后端服务器的证书。

原因:消息处理器的信任库中的证书或证书链不正确/不完整

诊断

  1. 使用 API Monitoring、Trace 工具或 NGINX 访问日志(如常见诊断步骤中所述)确定所观察到的错误的故障代码故障来源
  2. 如果故障代码messaging.adaptors.http.flow.SslHandshakeFailed,请使用以下方法之一确定错误消息:
  3. 如果错误消息为 sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target",则表示 SSL 握手失败,因为 Apigee Edge 的消息处理器无法验证后端服务器的证书。

您可以分两个阶段调试此问题:

  1. 第 1 阶段:确定后端服务器的证书链
  2. 第 2 阶段:比较存储在消息处理器的信任库中的证书链

第 1 阶段

第 1 阶段:确定后端服务器的证书链

使用以下方法之一确定后端服务器的证书链:

openssl

针对后端服务器的主机名执行 openssl 命令,如下所示:

openssl s_client -connect BACKEND_SERVER_HOST_NAME:PORT#

请注意上述命令输出中的证书链:

openssl 命令输出中的后端服务器证书链示例

Certificate chain
 0 s:/CN=mocktarget.apigee.net
   i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4
 1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4
   i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
 2 s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
   i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1

tcpdump

  1. 如果您是公共云用户,请在后端服务器上捕获 TCP/IP 数据包。
  2. 如果您是私有云用户,则可以在后端服务器或消息处理器上捕获 TCP/IP 数据包。最好在后端服务器上捕获这些数据包,因为数据包是在后端服务器上解密的。
  3. 使用以下 tcpdump 命令捕获 TCP/IP 数据包:

    tcpdump -i any -s 0 host IP_ADDRESS -w FILE_NAME
    
  4. 使用 Wireshark 工具或您熟悉的类似工具分析 TCP/IP 数据包。

    Tcpdump 示例分析

    查看放大图片

    • 数据包 #43:消息处理器(来源)向后端服务器(目的地)发送了 Client Hello 消息。
    • 数据包 44:后端服务器确认已收到来自消息处理器的 Client Hello 消息。
    • 数据包 #45:后端服务器发送 Server Hello 消息以及其证书。
    • 数据包 #46:消息处理器确认已收到 Server Hello 消息和证书。
    • 数据包 47:消息处理器发送 FIN, ACK 消息,随后在数据包 48 中发送 RST, ACK

      这表示消息处理器对后端服务器证书的验证失败。这是因为消息处理器没有任何与后端服务器的证书相匹配的证书,或者无法信任后端服务器的证书(根据其 [消息处理器] 信任库中可用的证书)。

    • 您可以返回并查看数据包 #45,确定后端服务器发送的证书链

      查看放大图片

    • 在此示例中,您可以看到服务器已发送一个具有 common name (CN) = mocktarget.apigee.net 的叶证书,随后又发送了一个具有 CN= GTS CA 1D4 的中间证书和一个具有 CN = GTX Root R1 的根证书。

    如果您已确定服务器的证书验证失败,请前往第 2 阶段:比较后端服务器的证书与存储在消息处理器的信任库中的证书

第 2 阶段

阶段 2:比较后端服务器的证书与存储在消息处理器的信任库中的证书

  1. 确定后端服务器的证书链
  2. 使用以下步骤确定存储在消息处理器的信任库中的证书:
    1. TargetEndpointSSLInfo 部分中的 TrustStore 元素获取信任库引用名称。

      我们来看一下 TargetEndpoint 配置中的示例 SSLInfo 部分:

      <TargetEndpoint name="default">
      ...
         <HTTPTargetConnection>
            <Properties />
            <SSLInfo>
               <Enabled>true</Enabled>
               <ClientAuthEnabled>true</ClientAuthEnabled>
               <KeyStore>ref://myKeystoreRef</KeyStore>
               <KeyAlias>myKey</KeyAlias>
               <TrustStore>
                  ref://myCompanyTrustStoreRef
               </TrustStore>
            </SSLInfo>
         </HTTPTargetConnection>
         ...
      </TargetEndpoint>
    2. 在上面的示例中,TrustStore 参考名称为 myCompanyTruststoreRef
    3. 在 Edge 界面中,依次选择环境 > 引用。请注意特定信任库参考的参考列中的名称。这将是您的信任库名称。

      查看放大图片

    4. 在上述示例中,信任库名称为:

      myCompanyTruststoreRef: myCompanyTruststore

  3. 使用以下 API 获取存储在信任库(在上一步中确定)中的证书:

    1. 获取密钥库或信任库的所有证书。此 API 会列出特定信任区中的所有证书。

      公有云用户

      curl -v -X GET https//api.enterprise.apigee.com/v1/organizations/ORGANIZATION_NAME/environments/ENVIRONMENT_NAME/keystores/KEYSTORE_NAME/certs -H "Authorization: Bearer $TOKEN"
      

      Private Cloud 用户

      curl -v -X GET http://MANAGEMENT_HOST:PORT_#/v1/organizations/ORGANIZATION_NAME/environments/ENVIRONMENT_NAME/keystores/KEYSTORE_NAME/certs -H "Authorization: Bearer $TOKEN"
      

      地点

      • ORGANIZATION_NAME 是组织的名称
      • ENVIRONMENT_NAME 是环境的名称
      • KEYSTORE_NAME 是密钥库的名称
      • $TOKEN 设置为您的 OAuth 2.0 访问令牌,如获取 OAuth 2.0 访问令牌中所述
      • 使用 curl中介绍了此示例中使用的 curl 选项

      示例输出

      示例信任库 myCompanyTruststore 中的证书如下:

      [
        "serverCert"
      ]
    2. 从密钥库或信任库中获取特定证书的证书详细信息。 此 API 会返回特定信任库中特定证书的相关信息。

      公有云用户

      curl -v -X GET https//api.enterprise.apigee.com/v1/organizations/ORGANIZATION_NAME/environments/ENVIRONMENT_NAME/keystores/KEYSTORE_NAME/certs/CERT_NAME -H "Authorization: Bearer $TOKEN"
      

      Private Cloud 用户

      curl -v -X GET http://MANAGEMENT_HOST:PORT_#>/v1/organizations/ORGANIZATION_NAME/environments/ENVIRONMENT_NAME/keystores/KEYSTORE_NAME/certs/CERT_NAME -H "Authorization: Bearer $TOKEN"
      

      地点

      • ORGANIZATION_NAME 是组织的名称
      • ENVIRONMENT_NAME 是环境的名称
      • KEYSTORE_NAME 是密钥库的名称
      • CERT_NAME 是证书的名称
      • $TOKEN 设置为您的 OAuth 2.0 访问令牌,如获取 OAuth 2.0 访问令牌中所述
      • 使用 curl中介绍了此示例中使用的 curl 选项

      输出示例

      serverCert 的详细信息显示了主题和签发者,如下所示:

      叶/实体证书

      "subject": "CN=mocktarget.apigee.net",
      "issuer": "CN=GTS CA 1D4, O=Google Trust Services LLC, C=US",

      中间证书

      "subject" : "CN=GTS CA 1D4, O=Google Trust Services LLC, C=US",
      "issuer" : "CN=GTS Root R1, O=Google Trust Services LLC, C=US",
  4. 验证在第 1 步中获得的实际服务器证书与在第 3 步中获得的信任库中存储的证书是否一致。如果不匹配,则会导致此问题。

    从上面的示例中,我们一次查看一个证书:

    1. 叶证书

      从后端服务器

      s:/CN=mocktarget.apigee.net
      i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4

      来自消息处理器(客户端)的信任库

      "subject": "CN=mocktarget.apigee.net",
      "issuer": "CN=GTS CA 1D4, O=Google Trust Services LLC, C=US",

      存储在信任库中的叶证书与后端服务器的叶证书一致。

    2. 中间证书

      从后端服务器

      s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4
      i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1

      来自消息处理器(客户端)的信任库

      "subject" : "CN=GTS CA 1D4, O=Google Trust Services LLC, C=US",
      "issuer" : "CN=GTS Root R1, O=Google Trust Services LLC, C=US",

      信任库中存储的中间证书与后端服务器的中间证书一致。

    3. 根证书

      从后端服务器

      s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
      i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1

      消息处理器的信任存储区中完全缺少根证书。

    4. 由于信任存储区中缺少根证书,消息处理器会抛出以下异常:

      sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

      并向客户端应用返回带有错误代码 messaging.adaptors.http.flow.SslHandshakeFailed503 Service Unavailable

分辨率

  1. 确保您拥有后端服务器的正确且完整的证书链。
  2. 如果您是公共云用户,请按照 更新 Cloud 的 TLS 证书中的说明将证书更新到 Apigee Edge 的消息处理器信任库。
  3. 如果您是私有云用户,请按照 为私有云更新 TLS 证书中的说明将证书更新到 Apigee Edge 的消息处理器信任库。

原因:后端服务器证书中的 FQDN 与目标端点中的主机名不匹配

如果后端服务器提供的证书链包含与目标端点中指定的主机名不匹配的 FQDN,则 Apigee Edge 的消息处理器会返回错误 SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

诊断

  1. 检查您发现此错误的 API 代理中的特定目标端点,并记下后端服务器的主机名:

    TargetEndpoint 示例

    <TargetEndpoint name="default">
       …
       <HTTPTargetConnection>
          <Properties />
          <SSLInfo>
             <Enabled>true</Enabled>
             <TrustStore>ref://myTrustStoreRef</TrustStore>
          </SSLInfo>
          <URL>https://backend.company.com/resource</URL>
       </HTTPTargetConnection>
    </TargetEndpoint>

    在上面的示例中,后端服务器的主机名为 backend.company.com

  2. 使用 openssl 命令确定后端服务器证书中的 FQDN,如下所示:

    openssl s_client -connect BACKEND_SERVER_HOST_NAME>:PORT_#>
    

    例如:

    openssl s_client -connect backend.company.com:443
    

    检查 Certificate chain 部分,并记下在叶证书的主题中指定为 CN 一部分的 FQDN。

    Certificate chain
     0 s:/CN=backend.apigee.net
       i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4
     1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4
       i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
     2 s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
       i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
    

    在上面的示例中,后端服务器的 FQDN 为 backend.apigee.net

  3. 如果从第 1 步获得的后端服务器的主机名与从第 2 步获得的 FQDN 不匹配,则会导致此错误。
  4. 在上述示例中,目标端点中的主机名为 backend.company.com。不过,后端服务器证书中的 FQDN 名称为 backend.apigee.net。由于它们不匹配,因此您会收到此错误。

分辨率

您可以使用以下任一方法来解决此问题:

正确的 FQDN

使用正确的 FQDN、有效且完整的证书链更新后端服务器的密钥库

  1. 如果您没有具有正确 FQDN 的后端服务器证书,请从相应的 CA(证书授权机构)获取正确的证书。
  2. 验证您是否拥有有效且完整的后端服务器证书链

  3. 获得有效且完整的证书链后,请确保叶证书或实体证书中后端服务器的 FQDN 与目标端点中指定的主机名完全相同,然后使用完整的证书链更新后端的密钥库

更正后端服务器

使用正确的后端服务器主机名更新目标端点

  1. 如果目标端点中指定的主机名不正确,请更新目标端点,使其包含与后端服务器证书中的 FQDN 相匹配的正确主机名。
  2. 保存对 API 代理所做的更改。

    在上述示例中,如果后端服务器主机名指定有误,您可以使用后端服务器证书中的 FQDN(即 backend.apigee.net)进行修正,如下所示:

    <TargetEndpoint name="default">
       …
       <HTTPTargetConnection>
          <Properties />
          <SSLInfo>
             <Enabled>true</Enabled>
             <TrustStore>ref://myTrustStoreRef</TrustStore>
          </SSLInfo>
          <URL>https://backend.apigee.net/resource</URL>
       </HTTPTargetConnection>
    </TargetEndpoint>

原因:后端服务器提供的证书或证书链不正确/不完整

诊断

  1. 通过针对后端服务器的主机名执行 openssl 命令来获取后端服务器的证书链,如下所示:
    openssl s_client -connect BACKEND_SERVER_HOST_NAME:PORT_#
    

    记下上述命令输出中的 Certificate chain

    openssl 命令输出中的后端服务器证书链示例

    Certificate chain
     0 s:/CN=mocktarget.apigee.net
       i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4
     1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4
       i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
       
  2. 验证您是否拥有正确且完整的证书链,如验证证书链中所述。
  3. 如果您没有后端服务器的有效且完整的证书链,那么这就是导致此问题的原因。

    在上面显示的示例后端服务器的证书链中,缺少根证书。因此,您会收到此错误。

分辨率

使用有效且完整的证书链更新后端服务器的密钥库:

  1. 验证您是否拥有有效且完整的后端服务器证书链

  2. 更新后端服务器的密钥库中的有效且完整的证书链。

如果问题仍然存在,请前往 必须收集的诊断信息

必须收集的诊断信息

如果按照上述说明操作后问题仍然存在,请收集以下诊断信息,然后联系 Apigee Edge 支持团队

  • 如果您是公共云用户,请提供以下信息:
    • 组织名称
    • 环境名称
    • API 代理名称
    • 完成 curl 命令以重现错误
    • 显示错误的轨迹文件
    • openssl 命令的输出:

      openssl s_client -connect BACKEND_SERVER_HOST_NAME:PORT_#

    • 在后端服务器上捕获的 TCP/IP 数据包
  • 如果您是私有云用户,请提供以下信息:
    • 观察到的完整错误消息
    • API 代理软件包
    • 显示错误的轨迹文件
    • 消息处理器日志 /opt/apigee/var/log/edge-message-processor/logs/system.log
    • openssl 命令的输出:
      openssl s_client -connect BACKEND_SERVER_HOST_NAME:PORT_#
    • 在后端服务器或消息处理器上捕获的 TCP/IP 数据包。
    • 获取密钥库或信任库的所有证书 API 的输出,以及使用 从密钥库或信任库获取证书详细信息 API 获取的每个证书的详细信息。

参考