Nieudane uzgadnianie połączenia SSL – nieprawidłowy certyfikat klienta

Wyświetlasz dokumentację Apigee Edge.
Otwórz dokumentację Apigee X.
info

Krótki opis problemu

Aplikacja kliencka otrzymuje kod stanu HTTP 503 z komunikatem „Service Unavailable” w odpowiedzi na żądanie do interfejsu API. W śledzeniu w interfejsie użytkownika zobaczysz, że w przypadku nieudanego żądania do interfejsu API error.cause to Received fatal alert: bad_certificate w sekcji Target Request Flow (Przepływ żądania do serwera docelowego).

Jeśli masz dostęp do logów procesora komunikatów, zobaczysz komunikat o błędzie jako Received fatal alert: bad_certificate w przypadku nieudanego żądania do interfejsu API. Ten błąd występuje podczas procesu uzgadniania SSL między procesorem komunikatów a serwerem backendu w konfiguracji TLS dwukierunkowej.

Komunikat o błędzie

Aplikacja kliencka otrzymuje ten kod odpowiedzi:

HTTP/1.1 503 Service Unavailable

Może też pojawić się ten komunikat o błędzie:

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

Użytkownicy Private Cloud zobaczą ten błąd w przypadku konkretnego żądania do interfejsu API w logach procesora komunikatów /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

Możliwe przyczyny

Możliwe przyczyny tego problemu:

Przyczyna Opis Instrukcje rozwiązywania problemów, których dotyczy
Brak certyfikatu klienta Magazyn kluczy używany w punkcie końcowym serwera docelowego nie zawiera certyfikatu klienta. Użytkownicy Edge Private i Public Cloud
Niezgodność urzędu certyfikacji Urząd certyfikacji certyfikatu liścia (pierwszego certyfikatu w łańcuchu certyfikatów) w magazynie kluczy procesora komunikatów nie pasuje do żadnego z urzędów certyfikacji akceptowanych przez serwer backendu. Użytkownicy Edge Private i Public Cloud

Typowe czynności diagnostyczne

  1. Włącz śledzenie w interfejsie Edge, wywołaj interfejs API i odtwórz problem.
  2. W wynikach śledzenia w interfejsie użytkownika przejdź przez każdy etap i określ, gdzie wystąpił błąd. Błąd wystąpił w sekcji Target Request Flow (Przepływ żądania do serwera docelowego).
  3. Sprawdź przepływ, w którym występuje błąd. Powinien on wyglądać tak jak w przykładowym śledzeniu poniżej:

    alt_text

  4. Jak widać na zrzucie ekranu powyżej, error.cause to "Received fatal alert: bad_certificate".
  5. Jeśli jesteś użytkownikiem Private Cloud, wykonaj te czynności:
    1. Identyfikator wiadomości w przypadku nieudanego żądania do interfejsu API możesz uzyskać, określając wartość nagłówka błędu "X-Apigee.Message-ID" na etapie wskazanym przez AX w śledzeniu.
    2. Wyszukaj ten identyfikator wiadomości w logu procesora komunikatów /opt/apigee/var/log/edge-message-processor/system.log i sprawdź czy możesz znaleźć dodatkowe informacje o błędzie:
      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]

      Log procesora komunikatów zawiera ślad stosu błędu Received fatal alert: bad_certificate, ale nie zawiera żadnych dodatkowych informacji wskazujących na przyczynę tego problemu.

  6. Aby dokładniej zbadać ten problem, musisz przechwycić pakiety TCP/IP za pomocą tcpdump.
    1. Jeśli jesteś użytkownikiem Private Cloud, możesz przechwycić pakiety TCP/IP na serwerze backendu lub procesorze komunikatów. Najlepiej przechwycić je na serwerze backendu, ponieważ pakiety są na nim odszyfrowywane.
    2. Jeśli jesteś użytkownikiem Public Cloud, przechwyć pakiety TCP/IP na serwerze backendu.
    3. Gdy zdecydujesz, gdzie chcesz przechwycić pakiety TCP/IP, użyj tego poniższego polecenia tcpdump , aby je przechwycić.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Jeśli przechwytujesz pakiety TCP/IP na procesorze komunikatów, w poleceniu tcpdump użyj publicznego adresu IP serwera backendu.

      Jeśli serwer backendu lub procesor komunikatów ma kilka adresów IP, musisz użyć innego polecenia tcpdump. Więcej informacji o tym narzędziu i innych wariantach tego polecenia znajdziesz w dokumentacji tcpdump.

  7. Przeanalizuj pakiety TCP/IP za pomocą narzędzia Wireshark lub podobnego narzędzia, które znasz.

Oto analiza przykładowych danych pakietów TCP/IP za pomocą narzędzia Wireshark:

alt_text

  1. Wiadomość nr 4 w tcpdump powyżej pokazuje, że procesor komunikatów (źródło) wysłał wiadomość „Client Hello” do serwera backendu (miejsce docelowe).
  2. Wiadomość nr 5 pokazuje, że serwer backendu potwierdza wiadomość Client Hello od procesora komunikatów.
  3. Serwer backendu wysyła wiadomość "Server Hello" wraz z certyfikatem, a następnie prosi klienta o wysłanie certyfikatu w wiadomości nr 7.
  4. Procesor komunikatów kończy weryfikację certyfikatu i potwierdza wiadomość ServerHello serwera backendu w wiadomości nr 8.
  5. Procesor komunikatów wysyła swój certyfikat do serwera backendu w wiadomości nr 9.
  6. Serwer backendu potwierdza otrzymanie certyfikatu procesora komunikatów w wiadomości nr 11.
  7. Jednak natychmiast wysyła do procesora komunikatów Fatal Alert: Bad Certificate (Wiadomość nr 12). Oznacza to, że certyfikat wysłany przez procesor komunikatów był nieprawidłowy, dlatego weryfikacja certyfikatu na serwerze backendu nie powiodła się. W rezultacie uzgadnianie SSL nie powiodło się i połączenie zostanie zamknięte.


    alt_text

  8. Przyjrzyjmy się teraz wiadomości nr 9, aby sprawdzić zawartość certyfikatu wysłanego przez procesor komunikatów:


    alt_text

  9. Jak widać, serwer backendu nie otrzymał żadnego certyfikatu od klienta (Certificate Length: 0). Dlatego serwer backendu wysyła komunikat Fatal Alert: Bad Certificate.
  10. Zwykle dzieje się tak, gdy klient, czyli procesor komunikatów (proces oparty na Javie):
    1. nie ma certyfikatu klienta w magazynie kluczy lub
    2. nie może wysłać certyfikatu klienta. Może się tak zdarzyć, jeśli nie może znaleźć certyfikatu wydanego przez jeden z urzędów certyfikacji akceptowanych przez serwer backendu. Oznacza to, że jeśli urząd certyfikacji certyfikatu liścia klienta (czyli pierwszego certyfikatu w łańcuchu) nie pasuje do żadnego z urzędów certyfikacji akceptowanych przez serwer backendu, procesor komunikatów nie wyśle certyfikatu.

Przyjrzyjmy się teraz każdej z tych przyczyn osobno.

Przyczyna: brak certyfikatu klienta

Diagnostyka

Jeśli w magazynie kluczy określonym w sekcji SSL Info punktu końcowego serwera docelowego lub serwera docelowego używanego w punkcie końcowym serwera docelowego nie ma certyfikatu, jest to przyczyna tego błędu.

Aby sprawdzić, czy to jest przyczyna problemu, wykonaj te czynności:

  1. Określ magazyn kluczy używany w punkcie końcowym serwera docelowego lub serwerze docelowym w przypadku konkretnego proxy interfejsu API, wykonując te czynności:
    1. Pobierz nazwę odwołania do magazynu kluczy z elementu Keystore w sekcji SSLInfo w punkcie końcowym serwera docelowego lub serwerze docelowym.

      Oto przykładowa sekcja SSLInfo w konfiguracji punktu końcowego serwera docelowego:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. W powyższym przykładzie nazwa odwołania do magazynu kluczy to „myKeystoreRef”.
    3. Otwórz interfejs Edge i kliknij API Proxies (Proxy interfejsu API) –> Environment Configurations (Konfiguracje środowiska).

      Kliknij kartę References (Odwołania) i wyszukaj nazwę odwołania do magazynu kluczy. Zanotuj nazwę w kolumnie Reference (Odwołanie) dla konkretnego odwołania do magazynu kluczy. Będzie to nazwa magazynu kluczy.


      alt_text

    4. W powyższym przykładzie widać, że myKeystoreRef odwołuje się do „myKeystore”. Dlatego nazwa magazynu kluczy to myKeystore.
  2. Sprawdź, czy ten magazyn kluczy zawiera certyfikat, korzystając z interfejsu Edge lub interfejsu API List certs for keystore.
  3. Jeśli magazyn kluczy zawiera certyfikaty, przejdź do sekcji Przyczyna: niezgodność urzędu certyfikacji.
  4. Jeśli magazyn kluczy nie zawiera żadnego certyfikatu, jest to powód, dla którego certyfikat klienta nie jest wysyłany przez procesor komunikatów.

Rozwiązanie

  1. Upewnij się, że prawidłowy i kompletny łańcuch certyfikatów klienta został przesłany do konkretnego magazynu kluczy w procesorze komunikatów.

Przyczyna: niezgodność urzędu certyfikacji

Gdy serwer prosi klienta o wysłanie certyfikatu, wskazuje zwykle zestaw akceptowanych wystawców lub urzędów certyfikacji. Jeśli wystawca lub urząd certyfikacji certyfikatu liścia (czyli pierwszego certyfikatu w łańcuchu certyfikatów) w magazynie kluczy procesora komunikatów nie pasuje do żadnego z urzędów certyfikacji akceptowanych przez serwer backendu, procesor komunikatów (który jest procesem opartym na Javie) nie wyśle certyfikatu do serwera backendu.

Aby sprawdzić, czy tak jest w Twoim przypadku, wykonaj te czynności:

  1. Użyj interfejsu API List certs for keystore.
  2. Pobierz szczegóły każdego certyfikatu uzyskanego w kroku 1, korzystając z interfejsu API Get cert for keystore.
  3. Zanotuj wystawcę certyfikatu liścia (czyli pierwszego certyfikatu w łańcuchu certyfikatów) przechowywanego w magazynie kluczy.

    Przykładowy certyfikat liścia

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

    W powyższym przykładzie wystawca lub urząd certyfikacji to "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"

  4. Określ akceptowaną listę wystawców lub urzędów certyfikacji serwera backendu, korzystając z jednej z tych metod:

    Metoda 1. Użyj tego polecenia openssl:

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

    W danych wyjściowych tego polecenia znajdź sekcję „Acceptable Client Certificate CA names” (Akceptowane nazwy urzędów certyfikacji certyfikatów klienta), jak pokazano poniżej:

    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

    Metoda 2. Sprawdź pakiet Certificate Request w pakietach TCP/IP, w których serwer backendu prosi klienta o wysłanie certyfikatu:

    W przykładowych pakietach TCP/IP pokazanych powyżej pakiet Certificate Request to wiadomość nr 7. Znajdź sekcję „Distinguished Names” (Nazwy wyróżniające), która zawiera akceptowane urzędy certyfikacji serwera backendu.

    alt_text

  5. Sprawdź, czy urząd certyfikacji uzyskany w kroku 3 pasuje do listy akceptowanych wystawców lub urzędów certyfikacji serwera backendu uzyskanej w kroku 4. Jeśli występuje niezgodność, procesor komunikatów nie wyśle certyfikatu klienta do serwera backendu.

    W powyższym przykładzie widać, że wystawca certyfikatu liścia klienta w magazynie kluczy procesora komunikatów nie pasuje do żadnego z serwerów backendu akceptowanych urzędów certyfikacji. Dlatego procesor komunikatów nie wysyła certyfikatu klienta do serwera backendu. Powoduje to niepowodzenie uzgadniania SSL, a serwer backendu wysyła komunikat „Fatal alert: bad_certificate”.

Rozwiązanie

  1. Upewnij się, że certyfikat z wystawcą lub urzędem certyfikacji, który pasuje do wystawcy lub urzędu certyfikacji certyfikatu liścia klienta (pierwszego certyfikatu w łańcuchu), jest przechowywany w magazynie zaufanych certyfikatów serwera backendu.
  2. W przykładzie opisanym w tym przewodniku, aby rozwiązać problem, do magazynu zaufanych certyfikatów serwera backendu dodano certyfikat z wystawcą "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com".

Jeśli problem nadal występuje, przejdź do sekcji Informacje diagnostyczne, które należy zebrać.

Informacje diagnostyczne, które należy zebrać

Jeśli problem nadal występuje po wykonaniu powyższych instrukcji, zbierz te informacje diagnostyczne. Skontaktuj się z zespołem pomocy Apigee Edge i udostępnij mu te informacje: Apigee Edge Support:

  1. Jeśli jesteś użytkownikiem Public Cloud, podaj te informacje:
    1. Nazwa organizacji
    2. Nazwa środowiska
    3. Nazwa proxy interfejsu API
    4. Pełne polecenie curl umożliwiające odtworzenie błędu
    5. Plik śledzenia, w którym widać błąd
    6. Pakiety TCP/IP przechwycone na serwerze backendu
  2. Jeśli jesteś użytkownikiem Private Cloud, podaj te informacje:
    1. Pełny komunikat o błędzie
    2. Pakiet proxy interfejsu API
    3. Plik śledzenia, w którym widać błąd
    4. Logi procesora komunikatów /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Pakiety TCP/IP przechwycone na serwerze backendu lub procesorze komunikatów.
    6. Dane wyjściowe interfejsu API Get cert for keystore.
  3. Szczegółowe informacje o tym, które sekcje tego przewodnika zostały przez Ciebie sprawdzone, oraz wszelkie inne informacje, które pomogą nam szybciej rozwiązać ten problem.