SSL 握手失敗 - 用戶端憑證錯誤

查看 Apigee Edge 說明文件。
前往 Apigee X說明文件
資訊

問題

用戶端應用程式收到 HTTP 狀態碼 503, 訊息:"Service Unavailable" 表示 API 要求。 您將在 UI 追蹤記錄中觀察到 error.cause 目標要求流程中的狀態為 Received fatal alert: bad_certificate

如果您可以存取訊息處理者記錄, 那麼,您會看到錯誤訊息為 Received fatal alert: bad_certificate 。系統會在 SSL 握手期間發現這項錯誤 程序使用 TLS 設定 2 種方式在訊息處理器和後端伺服器之間進行傳輸。

錯誤訊息

用戶端應用程式會取得下列回應代碼:

HTTP/1.1 503 Service Unavailable

此外,您也可能會看到下列錯誤訊息:

{
 "fault": {
    "faultstring":"The Service is temporarily unavailable",
    "detail":{
        "errorcode":"messaging.adaptors.http.flow.ServiceUnavailable"
    }
 }
}

私有雲使用者針對特定 API 要求會看到以下錯誤訊息 在訊息處理器記錄 /opt/apigee/var/log/edge-message-processor/system.log 中:

2017-10-23 05:28:57,813 org:org-name env:env-name api:apiproxy-name rev:revision-number messageid:message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() : SSLClientChannel[C:IP address:port # Remote host:IP address:port #]@65461 useCount=1 bytesRead=0 bytesWritten=0 age=529ms lastIO=529ms handshake failed, message: Received fatal alert: bad_certificate

可能原因

這個問題的可能原因如下:

原因 說明 疑難排解操作說明
沒有用戶端憑證 在目標伺服器的目標端點中使用的 KeyStore 沒有任何用戶端憑證。 邊緣私人與公用雲端使用者
憑證授權單位不相符 分葉憑證的憑證授權單位 (憑證鏈結中的第一個憑證) ,不符合後端伺服器接受的任何憑證授權單位。 邊緣私人與公用雲端使用者

常見診斷步驟

  1. 在 Edge UI 中啟用追蹤記錄、發出 API 呼叫,然後重現問題。
  2. 在 UI 追蹤記錄結果中瀏覽每個階段,並決定 發生錯誤。目標要求流程中發生錯誤。
  3. 檢查顯示錯誤的流程,您應該觀察錯誤,如圖所示 在下方追蹤記錄範例中:

    alt_text

  4. 如上方螢幕截圖所示,error.cause 「已收到嚴重警示: bad_certificate」
  5. 如果您是 Private Cloud 使用者,請按照下列說明操作:
    1. 您可以判定失敗 API 要求的訊息 ID, 錯誤標題「X-Apigee.Message-ID」的值 中所述的程序。
    2. 在訊息處理者記錄中搜尋這個郵件 ID /opt/apigee/var/log/edge-message-processor/system.log並確定 如要進一步瞭解錯誤,可以參閱下列說明:
      2017-10-23 05:28:57,813 org:org-name env:env-name api:apiproxy-name
      rev:revision-number messageid:message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() :
      SSLClientChannel[C:IP address:port # Remote host:IP address:port #]@65461 useCount=1
      bytesRead=0 bytesWritten=0 age=529ms lastIO=529ms handshake failed, message: Received fatal alert: bad_certificate
      2017-10-23 05:28:57,813 org:org-name env:env-name api:apiproxy-name
      rev:revision-number messageid:message_id NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() : SSLInfo:
      KeyStore:java.security.KeyStore@52de60d9 KeyAlias:KeyAlias TrustStore:java.security.KeyStore@6ec45759
      2017-10-23 05:28:57,814 org:org-name env:env-name api:apiproxy-name
      rev:revision-number messageid:message_id NIOThread@0 ERROR ADAPTORS.HTTP.FLOW - RequestWriteListener.onException() :
      RequestWriteListener.onException(HTTPRequest@6071a73d)
      javax.net.ssl.SSLException: Received fatal alert: bad_certificate
      at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[na:1.8.0_101]
      at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666) ~[na:1.8.0_101]
      at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634) ~[na:1.8.0_101]
      at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800) ~[na:1.8.0_101]
      at com.apigee.nio.NIOSelector$SelectedIterator.findNext(NIOSelector.java:496) [nio-1.0.0.jar:na]
      at com.apigee.nio.util.NonNullIterator.computeNext(NonNullIterator.java:21) [nio-1.0.0.jar:na]
      at com.apigee.nio.util.AbstractIterator.hasNext(AbstractIterator.java:47) [nio-1.0.0.jar:na]
      at com.apigee.nio.NIOSelector$2.findNext(NIOSelector.java:312) [nio-1.0.0.jar:na]
      at com.apigee.nio.NIOSelector$2.findNext(NIOSelector.java:302) [nio-1.0.0.jar:na]
      at com.apigee.nio.util.NonNullIterator.computeNext(NonNullIterator.java:21) [nio-1.0.0.jar:na]
      at com.apigee.nio.util.AbstractIterator.hasNext(AbstractIterator.java:47) [nio-1.0.0.jar:na]
      at com.apigee.nio.handlers.NIOThread.run(NIOThread.java:59) [nio-1.0.0.jar:na]
      

      訊息處理器記錄含有錯誤堆疊追蹤 Received fatal alert: bad_certificate,但沒有 有關帳戶分解原因的進一步資訊。

  6. 若要進一步調查這個問題,您必須使用以 tcpdump 工具。
    1. 如果您是 Private Cloud 使用者,可以擷取 後端伺服器或訊息處理器上的 TCP/IP 封包。 建議在封包解密時,將這些封包擷取到後端伺服器 後端伺服器
    2. 如果您是公用雲端使用者,請擷取 TCP/IP 寫入封包中
    3. 確定要擷取 TCP/IP 封包的位置後,請使用 tcpdump 擷取 TCP/IP 封包的指令。
    4. tcpdump -i any -s 0 host <IP address> -w <File name>
      敬上

      如果您透過訊息處理器接收 TCP/IP 封包,請使用 後端伺服器的公開 IP 位址:tcpdump 指令。

      如果後端伺服器/訊息處理器有多個 IP 位址,則 您就必須使用不同的 tcpdump 指令詳情請參閱 tcpdump 進一步瞭解這項工具和其他指令變化版本。

  7. 使用您熟悉的 Wireshark 工具或類似工具分析 TCP/IP 封包。

以下分析使用 Wireshark 工具的 TCP/IP 封包資料樣本:

alt_text

  1. 上方 tcpdump 中的訊息 #4 顯示「Message Processor」(來源) 傳送「Client Hello」訊息至後端伺服器 (目的地)。
  2. 訊息 #5 顯示後端伺服器已確認 Client Hello 訊息 來自訊息處理器
  3. 後端伺服器傳送「Server Hello」訊息和憑證 然後要求「用戶端」在「訊息 #7」中傳送憑證。
  4. 訊息處理者完成憑證驗證並確認 並在訊息 #8 中顯示後端伺服器的 ServerHello 訊息
  5. 「訊息處理者」以「訊息 #9」將其憑證傳送至後端伺服器。
  6. 後端伺服器確認已收到訊息處理者的 訊息 #11 中的憑證。
  7. 不過,該應用程式會立即傳送「嚴重快訊:錯誤憑證」給 訊息處理器 (訊息 #12)。這代表憑證是 訊息處理器發生錯誤,因此憑證驗證失敗 後端伺服器因此,SSL 握手會失敗並建立連線 即將打烊


    alt_text

  8. 現在讓我們看看「訊息 #9」,檢查「訊息處理者」傳送的憑證內容:


    alt_text

  9. 如您所見,後端伺服器未從用戶端取得任何憑證 (憑證長度:0)。因此,後端伺服器會傳送「嚴重快訊:錯誤憑證」。
  10. 通常發生於「用戶端」,也就是「訊息處理器」(以 Java 為基礎的程序):
    1. 未在 KeyStore 中沒有用戶端憑證;或
    2. 無法傳送用戶端憑證。如果找不到 由其中一個後端伺服器可接受的憑證授權單位核發的憑證。 這意味著,如果用戶端的節能憑證的憑證授權單位 (亦即鏈結中的第一個憑證) 與任何後端伺服器的 接受的憑證授權單位後,「訊息處理者」就不會傳送憑證。

這些原因分別說明如下。

原因:沒有用戶端憑證

診斷

如果「SSL 資訊」區段中的 KeyStore 中沒有憑證 目標端點或目標伺服器中使用的目標伺服器, 這就是導致出現錯誤的原因

請按照下列步驟判斷原因:

  1. 決定目標端點或目標伺服器中使用的 KeyStore ,執行下列步驟:
    1. Keystore 元素取得 KeyStore 參照名稱 目標端點或目標伺服器的 SSLInfo 區段中。

      以下是「目標端點設定」中的 SSLInfo 部分範例:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. 在上述範例中,KeyStore 參照名稱為「myKeystoreRef」。
    3. 前往 Edge UI,然後依序選取「API Proxy」->環境設定。

      選取「References」分頁標籤,然後搜尋 KeyStore 參照名稱。 記下「參考資料」欄中的名稱,以取得特定 KeyStore 參考資料。 這會是您的 KeyStore 名稱。


      alt_text

    4. 在上述範例中,您可以看到 myKeystoreRef 具有參考值 「myKeystore」因此 KeyStore 名稱為 myKeystore。
  2. 請使用 Edge UI 或 列出 KeyStore API 的憑證
  3. 如果 KeyStore 內有憑證,則移至 原因:憑證授權單位不符
  4. 如果 KeyStore 不含任何憑證 「訊息處理者」不會傳送用戶端憑證。

解析度

  1. 確保已將正確且完整的用戶端憑證鏈結上傳到訊息處理器中的特定 KeyStore。

原因:憑證授權單位不符

一般而言,當伺服器向用戶端要求用戶端傳送憑證時, 會指出接受的核發者或憑證授權單位組合。 如果分葉憑證的核發者/憑證授權單位 (也就是第一個 訊息處理者 KeyStore 中的憑證鏈結 與後端伺服器接受的任何憑證授權單位不符, 則「訊息處理器」(這是 Java 式程序) 不會將憑證傳送至後端伺服器。

請按照下列步驟操作:

  1. 列出 KeyStore API 的憑證
  2. 使用 取得 KeyStore API 的憑證
  3. 記下儲存在 KeyStore 中的分葉憑證核發者 (也就是憑證鏈結中的第一個憑證)

    節能綠葉憑證範例

    {
      "certInfo" : [ {
        "basicConstraints" : "CA:FALSE",
        "expiryDate" : 1578889324000,
        "isValid" : "Yes",
        "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com",
        "publicKey" : "RSA Public Key, 2048 bits",
        "serialNumber" : "65:00:00:00:d2:3e:12:d8:56:fa:e2:a9:69:00:06:00:00:00:d2",
        "sigAlgName" : "SHA256withRSA",
        "subject" : "CN=nonprod-api.mycompany.com, OU=ITS, O=MyCompany, L=MELBOURNE, ST=VIC, C=AU",
        "subjectAlternativeNames" : [ ],
        "validFrom" : 1484281324000,
        "version" : 3
      } ],
      "certName" : "nonprod-api.mycompany.com.key.pem-cert"
    }
    

    在上述範例中,核發者/憑證授權單位為 "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"敬上

  4. 請使用下列其中一種技術判斷後端伺服器接受的核發者或憑證授權單位清單:

    技巧 #1:使用以下 opensl 指令:

    openssl s_client -host <backend server host name> -port <Backend port#> -cert <Client Certificate> -key <Client Private Key>
    

    請參閱「可接受的用戶端憑證 CA 名稱」一節 在這個指令的輸出內容中顯示,如下所示:

    Acceptable client certificate CA names
    /C=AU/ST=VIC/L=MELBOURNE/O=MyCompany/OU=ITS/CN=nonprod-api.mycompany.com
    /C=AU/ST=VIC/L=MELBOURNE/O=MyCompany/OU=ITS/CN=nonprod-api.mycompany.com
    

    技巧 #2:檢查 Certificate Request 封包位於 TCP/IP 封包,後端伺服器在此伺服器中要求用戶端傳送其憑證:

    在上方顯示的範例 TCP/IP 封包中,Certificate Request 則封包為 #7 訊息請參閱「辨別名稱」一節 ,其中包含後端伺服器的「可接受的憑證授權單位」。

    alt_text

  5. 確認步驟 3 中取得的憑證授權單位是否與清單相符 您在步驟 4 取得的 後端伺服器接受的核發者或憑證授權單位 如果不相符,「訊息處理者」就不會傳送用戶端憑證 將要求轉送至後端伺服器

    在上方範例中,您可以看到用戶端的節能綠葉憑證核發機構 訊息處理器 KeyStore 中的任何後端伺服器 接受的憑證授權單位。因此,「訊息處理者」 將用戶端憑證傳送到後端伺服器 這會導致 SSL 握手失敗,後端伺服器會傳送「Fatal alert: bad_certificate」撰寫新的電子郵件訊息

解析度

  1. 確認與核發者/憑證授權單位相符的憑證 用戶端分葉憑證的核發者/憑證授權單位 (第一個憑證) ) 會儲存在後端伺服器的 Truststore 中。
  2. 在這個應對手冊的例子中,我們使用的是核發機構的憑證 "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"敬上 將 新增至後端伺服器的 Truststore 中,以解決問題。

如果問題仍未解決,請參閱「Must Gather 診斷資訊」。

必須收集診斷資訊

如果依上述說明操作後仍無法解決問題, 請收集下列診斷資訊。聯絡並分享給 Apigee Edge 支援

  1. 如果您是公有雲使用者,請提供下列資訊:
    1. 機構名稱
    2. 環境名稱
    3. API Proxy 名稱
    4. 完成 curl 指令即可重現錯誤
    5. 顯示錯誤的追蹤檔
    6. 在後端伺服器上擷取的 TCP/IP 封包
  2. 如果您是 Private Cloud 使用者,請提供以下資訊:
    1. 觀察到完整的錯誤訊息
    2. API Proxy 套裝組合
    3. 顯示錯誤的追蹤檔
    4. 訊息處理器記錄 /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. 在後端伺服器或訊息處理器擷取的 TCP/IP 封包。
    6. 取得 KeyStore API 的憑證的輸出內容。
  3. 有關您嘗試過的 Playbook 部分和任何其他內容的詳細資料 這些資料可協助我們快速解決這個問題。