400 请求错误 - SSL 证书错误

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

问题

客户端应用收到 HTTP 400 - 无效请求响应,并显示“SSL 证书错误”消息。在为传入 Apigee Edge 的连接启用双向 TLS 设置的情况下,此错误通常由 Edge 路由器发送。

错误消息

客户端应用会收到以下响应代码:

HTTP/1.1 400 Bad Request

然后是以下 HTML 错误页面:

<html>
  <head>
    <title>400 The SSL certificate error</title>
  </head>
  <body bgcolor="white">
    <center> <h1>400 Bad Request</h1>
    </center>
    <center>The SSL certificate error</center>
    <hr>
    <center>nginx</center>
  </body>
</html>

可能的原因

此问题的可能原因如下:

原因 说明 适用的问题排查说明
客户端证书已过期 客户端发送的证书已过期。 Edge Private 和 Public Cloud 用户
客户端发送的证书不正确 如果客户端应用发送的证书与 Edge 路由器的信任库中存储的证书不匹配,则会抛出此错误。 Edge Private 和 Public Cloud 用户
信任库中缺少客户端根证书 如果 Edge 路由器的信任库中缺少客户端的 CA 签名根证书,则会抛出此错误。 Edge Private 和 Public Cloud 用户
Edge 路由器中未加载客户端证书 如果上传到信任库的客户端证书未加载到路由器上,则会抛出此错误。 Edge Private Cloud 用户

原因:客户端证书已过期

对于双向 TLS,当客户端发送的证书已过期时,通常会发生此问题。在双向 TLS 中,客户端和服务器都会交换各自的公共证书以完成握手。客户端验证服务器证书,服务器验证客户端证书。

在 Edge 中,双向 TLS 是在虚拟主机级别实现的,其中服务器证书会添加到密钥库,而客户端证书会添加到信任库。

在 TLS 握手期间,如果发现客户端证书已过期,服务器将发送 400 - 错误请求,并附带消息“SSL 证书错误”。

诊断

  1. 登录 Edge 界面,查看发出 API 请求的特定虚拟主机配置(管理 > 虚拟主机),或使用 Get virtual host API 管理 API 获取特定虚拟主机的定义。

    双向 TLS 通信的虚拟主机通常如下所示:

    <VirtualHost name="myTLSVHost">
        <HostAliases>
            <HostAlias>api.myCompany.com</HostAlias>
        </HostAliases>
        <Port>443</Port>
        <SSLInfo>
            <Enabled>true</Enabled>
            <ClientAuthEnabled>true</ClientAuthEnabled>
            <KeyStore>ref://myKeystoreRef</KeyStore>
            <KeyAlias>myKeyAlias</KeyAlias>
            <TrustStore>ref://myTruststoreRef</TrustStore>
        </SSLInfo>
    </VirtualHost>
  2. 确定虚拟主机中使用的信任库引用。在上面的示例中,信任库引用名称为 myTruststoreRef

  3. 确定 Truststore 引用所指向的 Truststore。
    1. 在 Edge 界面中,依次前往管理 > 环境 > 引用,然后搜索 Truststore 引用名称。
    2. 请注意特定信任库参考的参考列中的名称。 这将是您的信任库名称。

      显示参考列表的 Edge 界面
      图 1

      在上面的示例中,请注意 myTruststoreRef 具有对 myTruststore 的引用。因此,信任库名称为 myTruststore

  4. 在 Edge 界面中的管理 > 环境 > TLS 密钥库中,导航到“TLS 密钥库”,然后找到第 3 步中找到的信任库。
  5. 选择特定信任库(在上述第 3 步中确定)下的证书,如下所示:

    图 2

    在上面的示例中,别名为 client-cert-markw 的证书显示已过期。

  6. 检查信任库中证书别名的证书是否已过期。
  7. 如果证书未过期,请前往其他原因的常见诊断步骤

分辨率

获取新证书并上传该证书:

  1. 创建新的信任库,例如 myNewTruststore
  2. 将新证书上传到新创建的信任库。
  3. 按照修改引用中的步骤,修改特定虚拟主机中使用的信任库引用,以指向新的信任库。

    在上述示例中,将引用 myTruststoreRef 指向 myNewTruststore。

其他原因的常见诊断步骤

  1. 如需调查此问题,您需要使用 tcpdump 工具捕获 TCP/IP 数据包。
    1. 如果您是 Private Cloud 用户,则可以在客户端应用或路由器上捕获 TCP/IP 数据包。
    2. 如果您是公共云用户,请在客户端应用上捕获 TCP/IP 数据包。
    3. 确定要捕获 TCP/IP 数据包的位置后,请使用以下 tcpdump 命令来捕获 TCP/IP 数据包:

      tcpdump -i any -s 0 host <IP address> -w <File name>

      注意:如果您要在路由器上捕获 TCP/IP 数据包,请在 tcpdump 命令中使用客户端应用的公共 IP 地址。

      如果您要获取客户端应用上的 TCP/IP 数据包,请使用 tcpdump 命令中虚拟主机所用主机名的公共 IP 地址。

      如需详细了解此工具和此命令的其他变体,请参阅 tcpdump

  2. 使用 Wireshark 工具或您熟悉的类似工具分析收集的 TCP/IP 数据包。

以下是使用 Wireshark 工具对示例 TCP/IP 数据包数据进行的分析:

  1. tcpdump(下图)中的数据包 #30 显示,客户端应用(来源)向路由器(目的地)发送了 “Client Hello”消息。
  2. 数据包 #34 显示,路由器确认了来自客户端应用的 Client Hello 消息。
  3. 路由器在数据包 #35 中发送“服务器 Hello”,然后发送其证书,并在数据包 #38 中请求客户端应用发送其证书。
  4. 在数据包 #38 中,路由器发送 “证书请求”数据包,检查“Distinguished Names”(专有名称)部分,其中提供了有关客户端证书、其链和路由器(服务器)接受的证书授权机构的详细信息。
  5. 图 3
  6. 客户端应用在数据包 # 41 中发送其证书。检查数据包 # 41 中的证书验证部分,确定客户端应用发送的证书。

    图 4
  7. 验证客户端应用发送的证书及其链(数据包 #41)的主题和颁发者是否与路由器接受的证书及其链(数据包 #38)相匹配。如果存在不一致的情况,则会导致此错误。因此,路由器(服务器)会向客户端应用发送加密的提醒(数据包 #57),然后发送 FIN、ACK(数据包 58),最终连接会终止。
  8. 证书及其链不匹配可能是由以下部分中所述的场景造成的。

原因:客户端发送的证书不正确

如果客户端应用发送的证书和/或其链的主题/颁发者与路由器(服务器)的信任库中存储的证书和/或其链不匹配,通常就会发生这种情况。

诊断

  1. 登录 Edge 界面,查看发出 API 请求的特定虚拟主机配置(管理 > 虚拟主机),或使用 Get virtual host API 管理 API 获取特定虚拟主机的定义。

    双向 TLS 通信的虚拟主机通常如下所示:

        <VirtualHost name="myTLSVHost">
            <HostAliases>
                <HostAlias>api.myCompany.com</HostAlias>
            </HostAliases>
            <Port>443</Port>
            <SSLInfo>
                <Enabled>true</Enabled>
                <ClientAuthEnabled>true</ClientAuthEnabled>
                <KeyStore>ref://myKeystoreRef</KeyStore>
                <KeyAlias>myKeyAlias</KeyAlias>
                    <TrustStore>ref://myCompanyTruststoreRef</TrustStore>
            </SSLInfo>
        </VirtualHost>
  2. 确定虚拟主机中使用的信任库引用。

    在上述示例中,信任库引用名称为 myCompanyTruststoreRef

  3. 确定 Truststore 引用所指向的 Truststore。
    1. 在 Edge 界面中,依次前往管理 > 环境引用,然后搜索信任库引用名称。
    2. 请注意特定信任库参考的参考列中的名称。 这将是您的信任库名称。

      显示信任库引用的 Edge 界面。
      图 5

      在上面的示例中,请注意 myCompanyTruststoreRef 具有对 myCompanyTruststore 的引用。因此,信任库名称为 myCompanyTruststore。

  4. 使用以下 API 获取存储在信任库(在上一步中确定)中的证书:
    1. 列出密钥库或信任库的证书 API

      此 API 会列出特定信任库中的所有证书。

    2. 从密钥库或信任库 API 获取证书详细信息

      此 API 会返回特定 Truststore 中特定证书的相关信息。

  5. 检查存储在 myCompanyTruststore 中的每个证书及其链的签发者和正文是否与上述 TCP/IP 数据包(请参阅数据包 #38)中显示的证书及其链的签发者和正文一致。如果存在不一致的情况,则表示上传到信任库的证书未加载到 Edge 路由器中。 请参阅原因:客户端证书未加载到 Edge 路由器中
  6. 如果在第 5 步中未发现任何不匹配项,则表明客户端应用未发送正确的证书及其链。

分辨率

确保客户端应用将正确的证书及其链发送到 Edge。

原因:信任库中缺少客户端根证书

如果 Edge 路由器的信任库中缺少客户端的 CA 签名根证书,则会抛出此错误。

诊断

  1. 登录 Edge 界面,查看发出 API 请求的特定虚拟主机配置(管理 > 虚拟主机 > virtual_host),或者使用 获取虚拟主机 API 来获取特定虚拟主机的定义。

    双向 TLS 通信的虚拟主机通常如下所示:

        <VirtualHost name="myTLSVHost">
            <HostAliases>
                <HostAlias>api.myCompany.com</HostAlias>
            </HostAliases>
            <Port>443</Port>
            <SSLInfo>
                <Enabled>true</Enabled>
                <ClientAuthEnabled>true</ClientAuthEnabled>
                <KeyStore>ref://myKeystoreRef</KeyStore>
                <KeyAlias>myKeyAlias</KeyAlias>
                <TrustStore>ref://myCompanyTruststoreRef</TrustStore>
            </SSLInfo>
        </VirtualHost>
  2. 确定虚拟主机中使用的信任库引用。在前面的示例中,信任库引用名称为 myCompanyTruststoreRef
  3. 确定信任库引用所使用的实际信任库。
  4. 在 Edge 界面中,依次前往管理 > 环境 > 引用,然后搜索信任库引用名称。
  5. 特定信任库引用的信任库名称位于引用列中。

    图 6

    在此示例中,请注意 myCompanyTruststoreRef 在“参考”列中具有 myCompanyTruststore。因此,信任库名称为 myCompanyTruststore

  6. 使用以下 API 获取存储在信任库(在上一步中确定)中的证书:
    1. 列出密钥库或信任库的证书 API。此 API 会列出信任库中的所有证书。
    2. 从密钥库或信任库 API 获取证书详细信息。此 API 会返回信任库中特定证书的相关信息。
  7. 检查证书是否包含完整链,包括特定客户端发送的根证书(如 TCP/IP 数据包中所示,请参阅图 4)。信任库必须包含根证书以及客户端的叶证书或叶证书和中间证书。如果信任库中缺少客户端的有效根证书,就会导致此错误。

    不过,如果信任库中存在客户端的完整证书链(包括根证书),则表示上传到信任库的证书可能未加载到 Edge 路由器中。如果属于这种情况,请参阅原因:客户端证书未加载到 Edge 路由器中

分辨率

确保 Apigee Edge 路由器的信任存储区中包含正确的客户端证书(包括根证书)。

原因:客户端证书未加载到 Edge 路由器中

  1. 如果您是 Public Cloud 用户,请与 Apigee Edge 支持团队联系。
  2. 如果您是 Private Cloud 用户,请按照以下说明在每个路由器上操作:
    1. 检查特定虚拟主机是否存在文件 /opt/nginx/conf.d/OrgName_envName_vhostName-client.pem。如果该文件不存在,请前往下方的解决方法部分。
    2. 如果该文件存在,请使用以下 openssl 命令获取 Edge 路由器上可用证书的详细信息:
      openssl -in <OrgName_envName_vhostName-client.pem> -text -noout
    3. 检查证书的颁发者、主题和失效日期。如果上述任何一项与在 Edge 界面中的信任库或使用管理 API 观察到的内容不一致,则会导致错误。
    4. 路由器可能未重新加载上传的证书。

分辨率

重启路由器,确保加载最新的证书,具体步骤如下:

apigee-service edge-router restart

重新运行 API 并检查结果。如果问题仍然存在,请前往收集诊断信息

收集诊断信息

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

  1. 如果您是公共云用户,请提供以下信息:
    1. 组织名称
    2. 环境名称
    3. API 代理名称
    4. 虚拟主机名
    5. 主机别名
    6. 用于重现错误的完整 curl 命令
    7. 在客户端应用上捕获的 TCP/IP 数据包
  2. 如果您是 Private Cloud 用户,请提供以下信息:
    1. 使用 Get virtual host API 获取的虚拟主机名及其定义
    2. 主机别名
    3. 观察到的完整错误消息
    4. 在客户端应用或路由器上捕获的 TCP/IP 数据包。
    5. 列出密钥库中的证书 API 的输出,以及使用 Get cert details API 获取的每个证书的详细信息。
  3. 详细说明您尝试过本 Playbook 中的哪些部分,以及任何其他有助于我们快速解决此问题的见解。