SSL-Handshake schlägt fehl – Fehlerhaftes Clientzertifikat

Sie sehen die Dokumentation zu Apigee Edge.
Zur Apigee X-Dokumentation
weitere Informationen

Symptom

Die Clientanwendung empfängt den HTTP-Statuscode 503 mit der Meldung "Service Nicht verfügbar" als Antwort auf eine API-Anfrage. Im UI-Trace sehen Sie, dass error.cause im Zielanfragefluss für die fehlgeschlagenen API-Anfragen den Wert Received fatal alert: bad_certificate hat.

Wenn Sie Zugriff auf Message Processor-Logs haben, wird die Fehlermeldung Received fatal alert: bad_certificate für die fehlgeschlagene API-Anfrage angezeigt. Dieser Fehler wird während des SSL-Handshakevorgangs zwischen dem Nachrichtenprozessor und dem Back-End-Server mit einer 2-Wege-TLS-Einrichtung beobachtet.

Fehlermeldung

Die Clientanwendung erhält den folgenden Antwortcode:

HTTP/1.1 503 Service Unavailable

Außerdem wird möglicherweise die folgende Fehlermeldung angezeigt:

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

Nutzern der privaten Cloud wird für die jeweilige API-Anfrage in den Nachrichtenprozessorprotokollen der folgende Fehler angezeigt: /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

Mögliche Ursachen

Mögliche Ursachen:

Ursache Beschreibung Gilt für die Anleitung zur Fehlerbehebung
Kein Clientzertifikat Der im Zielendpunkt des Zielservers verwendete Schlüsselspeicher hat kein Client-Zertifikat. Private Edge-Nutzer und Nutzer öffentlicher Clouds
Zertifizierungsstelle stimmt nicht überein Die Zertifizierungsstelle des untergeordneten Zertifikats (das erste Zertifikat in der Zertifikatskette) im Schlüsselspeicher des Nachrichtenverarbeiters stimmt mit keiner der vom Back-End-Server akzeptierten Zertifizierungsstellen überein. Private Edge-Nutzer und Nutzer öffentlicher Clouds

Häufige Diagnoseschritte

  1. Aktivieren Sie Trace in der Edge-Benutzeroberfläche, führen Sie den API-Aufruf aus und reproduzieren Sie das Problem.
  2. Gehen Sie in den Trace-Ergebnissen der UI durch jede Phase und ermitteln Sie, wo der Fehler aufgetreten ist. Der Fehler wäre im Zielanfragefluss aufgetreten.
  3. Sehen Sie sich den Ablauf an, in dem der Fehler auftritt. Beachten Sie den Fehler, wie im folgenden Beispiel-Trace gezeigt:

    alt_text

  4. Wie im Screenshot oben zu sehen ist, lautet error.cause error.cause .
  5. Wenn Sie ein Private Cloud-Nutzer sind, gehen Sie so vor:
    1. Sie können die Nachrichten-ID für die fehlgeschlagene API-Anfrage abrufen, indem Sie den Wert des Fehlerheaders X-Apigee.Message-ID in der durch AX im Trace angegebenen Phase ermitteln.
    2. Suchen Sie im Nachrichtenverarbeitungsprotokoll /opt/apigee/var/log/edge-message-processor/system.log nach dieser Nachrichten-ID und prüfen Sie, ob Sie weitere Informationen zum Fehler finden:
      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]
      

      Das Message Processor-Log enthielt einen Stacktrace für den Fehler Received fatal alert: bad_certificate, enthält aber keine weiteren Informationen, die auf die Ursache dieses Problems hinweisen.

  6. Damit Sie dieses Problem weiter untersuchen können, müssen Sie TCP/IP-Pakete mit dem Tool tcpdump erfassen.
    1. Wenn Sie ein Private Cloud-Nutzer sind, können Sie die TCP/IP-Pakete auf dem Back-End-Server oder Message Processor erfassen. Sie sollten sie vorzugsweise auf dem Back-End-Server erfassen, wenn die Pakete auf dem Back-End-Server entschlüsselt werden.
    2. Wenn Sie ein Nutzer der öffentlichen Cloud sind, erfassen Sie die TCP/IP-Pakete auf dem Back-End-Server.
    3. Nachdem Sie sich entschieden haben, wo Sie TCP/IP-Pakete erfassen möchten, verwenden Sie den unten stehenden tcpdump-Befehl, um TCP/IP-Pakete zu erfassen.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Wenn Sie die TCP/IP-Pakete auf dem Message Processor übernehmen, verwenden Sie die öffentliche IP-Adresse des Back-End-Servers im Befehl tcpdump.

      Wenn es mehrere IP-Adressen für den Back-End-Server/Message Processor gibt, müssen Sie einen anderen „tcpdump“-Befehl verwenden. Weitere Informationen zu diesem Tool und anderen Varianten dieses Befehls finden Sie unter tcpdump.

  7. Analysieren Sie die TCP/IP-Pakete mit dem Wireshark-Tool oder einem anderen Ihnen bekannten Tool.

Hier ist die Analyse von Beispieldaten von TCP/IP-Paketen mit dem Wireshark-Tool:

alt_text

  1. Nachricht 4 im obigen tcpdump zeigt, dass der Message Processor (Quelle) eine "Client Hello"-Nachricht an den Back-End-Server (Ziel) gesendet hat.
  2. Nachricht 5 zeigt, dass der Back-End-Server die Client-Hello-Nachricht vom Message Processor bestätigt.
  3. Der Back-End-Server sendet die Nachricht „Server Hello“ zusammen mit seinem Zertifikat und fordert den Client dann in Nachricht 7 auf, sein Zertifikat zu senden.
  4. Der Message Processor schließt die Verifizierung des Zertifikats ab und bestätigt die ServerHello-Nachricht des Back-End-Servers in Nachricht Nr. 8.
  5. Der Message Processor sendet sein Zertifikat an den Back-End-Server in Nachricht 9.
  6. Der Back-End-Server bestätigt den Empfang des Zertifikats des Message Processor in Nachricht Nr. 11.
  7. Es sendet jedoch sofort eine Schwerwiegende Warnung: Ungültiges Zertifikat an den Message Processor (Nachricht Nr. 12). Dies weist darauf hin, dass das vom Message Processor gesendete Zertifikat fehlerhaft war und daher die Zertifikatsprüfung auf dem Back-End-Server fehlgeschlagen ist. Daher ist der SSL-Handshake fehlgeschlagen und die Verbindung wird geschlossen.


    alt_text

  8. Sehen wir uns nun Nachricht Nr. 9 an, um den Inhalt des Zertifikats zu überprüfen, das vom Message Processor gesendet wurde:


    alt_text

  9. Wie Sie sehen, hat der Back-End-Server kein Zertifikat vom Client erhalten (Zertifikatlänge: 0). Daher sendet der Back-End-Server die Meldung „Schwerwiegende Warnung: Falsches Zertifikat“.
  10. In der Regel geschieht dies, wenn der Client, d. h. Message Processor (ein Java-basierter Prozess):
    1. kein Clientzertifikat im Schlüsselspeicher hat oder
    2. Es kann kein Client-Zertifikat gesendet werden. Dies kann passieren, wenn ein Zertifikat nicht gefunden wird, das von einer der zulässigen Zertifizierungsstellen des Back-End-Servers ausgestellt wurde. Das heißt, wenn die Zertifizierungsstelle des Blattzertifikats des Clients (d.h. das erste Zertifikat in der Kette) mit keiner der zulässigen Zertifizierungsstellen des Back-End-Servers übereinstimmt, sendet der Message Processor das Zertifikat nicht.

Sehen wir uns die einzelnen Ursachen im Folgenden genauer an.

Ursache: Kein Clientzertifikat

Diagnose

Wenn im Schlüsselspeicher im Abschnitt „SSL-Informationen“ des Zielendpunkts oder auf dem im Zielendpunkt verwendeten Zielserver kein Zertifikat angegeben ist, ist das die Ursache für diesen Fehler.

Führen Sie die folgenden Schritte aus, um festzustellen, ob dies die Ursache ist:

  1. Ermitteln Sie den Schlüsselspeicher, der im Zielendpunkt oder auf dem Zielserver für den spezifischen API-Proxy verwendet wird. Gehen Sie dazu so vor:
    1. Rufen Sie den Schlüsselspeicher-Referenznamen aus dem Element Keystore im Abschnitt SSLInfo des Zielendpunkts oder des Zielservers ab.

      Sehen wir uns ein Beispiel für einen SSLInfo-Abschnitt in einer Zielendpunktkonfiguration an:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. Im obigen Beispiel lautet der Schlüsselspeicher-Referenzname myKeystoreRef".
    3. Gehen Sie zur Edge-Benutzeroberfläche und wählen Sie API-Proxies -> Umgebungskonfigurationen aus.

      Wählen Sie den Tab Referenzen aus und suchen Sie nach dem Schlüsselspeicher-Referenznamen. Notieren Sie sich den Namen in der Spalte Reference (Referenz) für die spezifische Keystore-Referenz. Dies ist der Name Ihres Schlüsselspeichers.


      alt_text

    4. Im obigen Beispiel sehen Sie, dass myKeystoreRef einen Verweis auf "myKeystore" hat. Daher lautet der Schlüsselspeichername „myKeystore“.
  2. Prüfen Sie mithilfe der Edge-Benutzeroberfläche oder der Liste der Zertifikate für die Keystore API, ob dieser Schlüsselspeicher das Zertifikat enthält.
  3. Wenn der Schlüsselspeicher Zertifikate enthält, fahren Sie mit Ursache: Abweichende Zertifizierungsstelle fort.
  4. Wenn der Schlüsselspeicher kein Zertifikat enthält, wird das Clientzertifikat aus diesem Grund nicht vom Message Processor gesendet.

Auflösung

  1. Stellen Sie sicher, dass die richtige und vollständige Client-Zertifikatskette in den spezifischen Schlüsselspeicher im Message Processor hochgeladen wird.

Ursache: Abweichende Zertifizierungsstelle

Wenn der Server den Client zum Senden seines Zertifikats anfordert, wird im Allgemeinen die Gruppe akzeptierter Aussteller oder Zertifizierungsstellen angezeigt. Wenn der Aussteller/die Zertifizierungsstelle des untergeordneten Zertifikats (d.h. des ersten Zertifikats in der Zertifikatskette) im Schlüsselspeicher des Nachrichtenprozessors mit keiner der vom Back-End-Server akzeptierten Zertifizierungsstellen übereinstimmt, sendet der Nachrichtenprozessor (ein Java-basierter Prozess) das Zertifikat nicht an den Back-End-Server.

Mit den folgenden Schritten können Sie überprüfen, ob dies der Fall ist:

  1. Zertifikate für die Keystore API auflisten.
  2. Rufen Sie die Details zu jedem Zertifikat ab, das Sie in Schritt 1 oben erhalten haben. Verwenden Sie dazu Zertifikat für Keystore API abrufen.
  3. Notieren Sie sich den Aussteller des untergeordneten Zertifikats (d.h. das erste Zertifikat in der Zertifikatskette), das im Schlüsselspeicher gespeichert ist.

    Beispiel für ein Blattzertifikat

    {
      "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"
    }
    

    Im obigen Beispiel ist der Aussteller bzw. die Zertifizierungsstelle "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com".

  4. Ermitteln Sie die vom Back-End-Server akzeptierte Liste der Aussteller oder Zertifizierungsstellen mit einer der folgenden Methoden:

    Verfahren 1: Verwenden Sie den folgenden Befehl „openssl“:

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

    Weitere Informationen finden Sie in der Ausgabe des Befehls wie unten dargestellt im Abschnitt Acceptable Client Certificate CA names (Zulässige CA-Namen für Clientzertifikate):

    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
    

    Technik 2: Prüfen Sie das Certificate Request-Paket in TCP/IP-Paketen, bei denen der Back-End-Server den Client zum Senden seines Zertifikats auffordert:

    In den oben gezeigten Beispiel-TCP/IP-Paketen ist das Certificate Request-Paket die Nachricht 7. Weitere Informationen finden Sie im Abschnitt „Distinguished Names“ (Distinguished Names), in dem die zulässigen Zertifizierungsstellen des Back-End-Servers aufgeführt sind.

    alt_text

  5. Prüfen Sie, ob die in Schritt 3 erhaltene Zertifizierungsstelle mit der Liste der akzeptierten Aussteller oder Zertifizierungsstellen des Back-End-Servers aus Schritt 4 übereinstimmt. Wenn es eine Abweichung gibt, sendet der Nachrichtenprozessor das Clientzertifikat nicht an den Back-End-Server.

    Im obigen Beispiel können Sie feststellen, dass der Aussteller des Blattzertifikats des Clients im Schlüsselspeicher des Nachrichtenverarbeiters mit keiner der akzeptierten Zertifizierungsstellen des Back-End-Servers übereinstimmt. Daher sendet der Message Processor das Clientzertifikat nicht an den Back-End-Server. Dies führt dazu, dass der SSL-Handshake fehlschlägt und der Back-End-Server die Nachricht "Fatal alert: bad_certificate" sendet.

Auflösung

  1. Achten Sie darauf, dass das Zertifikat des Ausstellers/der Zertifizierungsstelle, das mit dem Aussteller bzw. der Zertifizierungsstelle des Blattzertifikats des Clients (erstes Zertifikat in der Kette) übereinstimmt, im Truststore des Back-End-Servers gespeichert ist.
  2. In dem in diesem Playbook beschriebenen Beispiel wurde das Zertifikat des Ausstellers "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" dem Truststore des Back-End-Servers hinzugefügt, um das Problem zu beheben.

Wenn das Problem weiterhin besteht, lesen Sie den Artikel Diagnoseinformationen müssen erfasst werden.

Diagnoseinformationen müssen erfasst werden

Wenn das Problem auch nach Befolgen der obigen Anleitung weiterhin besteht, stellen Sie die folgenden Diagnoseinformationen zusammen. Kontaktieren Sie sie und geben Sie sie für den Apigee Edge-Support frei:

  1. Wenn Sie die öffentliche Cloud nutzen, geben Sie die folgenden Informationen an:
    1. Name der Organisation
    2. Name der Umgebung
    3. API-Proxy-Name
    4. Führen Sie den curl-Befehl aus, um den Fehler zu reproduzieren
    5. Trace-Datei mit dem Fehler
    6. Auf dem Back-End-Server erfasste TCP/IP-Pakete
  2. Wenn Sie die private Cloud nutzen, geben Sie die folgenden Informationen an:
    1. Vollständige Fehlermeldung angezeigt
    2. API-Proxy-Bundle
    3. Trace-Datei mit dem Fehler
    4. Message Processor-Protokolle /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. TCP/IP-Pakete, die auf dem Back-End-Server oder Message Processor erfasst werden.
    6. Ausgabe von Get cert for keystore API.
  3. Details zu den Abschnitten in diesem Playbook, die du ausprobiert hast, und zu anderen Informationen, die uns helfen könnten, dieses Problem zu beschleunigen.