Kegagalan Jabat Tangan SSL - Sertifikat Klien Buruk

Anda sedang melihat dokumentasi Apigee Edge.
Buka Dokumentasi Apigee X.
info

ini.

Gejala

Aplikasi klien menerima kode status HTTP 503 dengan pesan "Service available" sebagai respons terhadap permintaan API. Dalam rekaman aktivitas UI, Anda akan mengamati bahwa error.cause adalah Received fatal alert: bad_certificate dalam Alur Permintaan Target untuk permintaan API yang gagal.

Jika Anda memiliki akses ke log Pemroses Pesan, Anda akan melihat pesan error sebagai Received fatal alert: bad_certificate untuk permintaan API yang gagal. Error ini diamati selama handshake SSL proses antara Pemroses Pesan dan server backend dalam penyiapan TLS 2 arah.

Pesan Error

Aplikasi Klien mendapatkan kode respons berikut:

HTTP/1.1 503 Service Unavailable

Selain itu, Anda mungkin melihat pesan error berikut:

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

Pengguna Private Cloud akan melihat error berikut untuk permintaan API tertentu di log Pemroses Pesan /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

Kemungkinan Penyebab

Kemungkinan penyebab masalah ini adalah sebagai berikut:

Cause Deskripsi Petunjuk Pemecahan Masalah yang Berlaku
Tidak Ada Sertifikat Klien Keystore yang digunakan di Endpoint Target Server Target tidak memiliki Sertifikat Klien. Pengguna Edge Private dan Cloud Publik
Ketidakcocokan Certificate Authority Certificate Authority (Otoritas Sertifikat) sertifikat entitas akhir (Sertifikat pertama dalam rantai Sertifikat) pada Keystore Pemroses Pesan tidak cocok dengan Certificate Authority mana pun yang diterima oleh server backend. Pengguna Edge Private dan Cloud Publik

Langkah-Langkah Diagnosis Umum

  1. Aktifkan pelacakan di UI Edge, lakukan panggilan API, dan rekonstruksi masalah.
  2. Dalam hasil pelacakan UI, navigasikan setiap Fase dan tentukan di mana terjadi kesalahan. Error akan terjadi di Alur Permintaan Target.
  3. Periksa Flow yang menampilkan error, Anda harus mengamati error seperti yang ditunjukkan pada contoh trace di bawah ini:

    alt_text

  4. Seperti yang Anda lihat pada screenshot di atas, error.cause adalah "Menerima pemberitahuan fatal: bad_certificate".
  5. Jika Anda adalah pengguna Private Cloud, ikuti petunjuk di bawah ini:
    1. Anda bisa mendapatkan ID pesan untuk permintaan API yang gagal dengan menentukan nilai Header Error "X-Apigee.Message-ID" dalam Fase yang ditunjukkan oleh AX dalam pelacakan.
    2. Telusuri ID pesan ini di log Pemroses Pesan /opt/apigee/var/log/edge-message-processor/system.log dan tentukan jika Anda dapat menemukan informasi lebih lanjut tentang error tersebut:
      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 Pemroses Pesan memiliki stack trace untuk error Received fatal alert: bad_certificate, tetapi tidak memiliki informasi lebih lanjut yang menunjukkan penyebab masalah ini.

  6. Untuk menyelidiki masalah ini lebih lanjut, Anda harus menangkap paket TCP/IP menggunakan tcpdump.
    1. Jika Anda adalah pengguna Private Cloud, maka Anda dapat menangkap paket TCP/IP di server backend atau {i>Message Processor<i}. Sebaiknya, tangkap file tersebut di server backend saat paket didekripsi di server backend.
    2. Jika Anda adalah pengguna Cloud Publik, tangkap TCP/IP paket di server backend.
    3. Setelah Anda memutuskan di mana Anda ingin menangkap paket TCP/IP, gunakan di bawah tcpdump perintah untuk menangkap paket TCP/IP.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Jika Anda mengambil paket TCP/IP pada {i>Message Processor<i}, maka gunakan alamat IP publik server backend di perintah tcpdump.

      Jika ada beberapa alamat IP untuk server backend/Pemroses Pesan, maka Anda perlu menggunakan perintah {i>tcpdump<i} yang berbeda. Rujuk ke tcpdump untuk informasi selengkapnya tentang alat ini dan untuk varian lain dari perintah ini.

  7. Analisis paket TCP/IP menggunakan alat Wireshark atau alat serupa yang sudah Anda kenal.

Berikut adalah analisis sampel data paket TCP/IP menggunakan alat Wireshark:

alt_text

  1. Pesan #4 dalam {i>tcpdump<i} di atas menunjukkan bahwa Pemroses Pesan (sumber) mengirim pesan "Client Hello" ke server backend (tujuan).
  2. Pesan #5 menunjukkan bahwa server backend menerima pesan Client Hello dari Pemroses Pesan.
  3. Server backend mengirimkan "Server Hello" beserta Sertifikatnya, dan kemudian meminta Klien untuk mengirimkan Sertifikatnya dalam Pesan #7.
  4. Pemroses Pesan menyelesaikan verifikasi Sertifikat dan mengonfirmasi pesan {i>ServerHello <i}server backend di Pesan #8.
  5. Pemroses Pesan mengirimkan Sertifikatnya ke server backend di Pesan #9.
  6. Server backend mengonfirmasi penerimaan permintaan Sertifikat dalam Pesan #11.
  7. Namun, Google akan langsung mengirim Peringatan Fatal: Sertifikat Buruk ke Pemroses Pesan (Pesan #12). Ini menunjukkan bahwa Sertifikat yang dikirim oleh {i>Message Processor<i} buruk dan karenanya Verifikasi Sertifikat gagal pada server backend. Akibatnya, SSL Handshake gagal dan koneksi akan ditutup.


    alt_text

  8. Sekarang mari kita lihat Pesan #9 untuk memeriksa isi sertifikat yang dikirim oleh {i>Message Processor<i}:


    alt_text

  9. Seperti yang dapat Anda perhatikan, server backend tidak mendapatkan Sertifikat apa pun dari Klien (Durasi Sertifikat: 0). Oleh karena itu, server backend mengirimkan Fatal Alert: Bad Certificate.
  10. Biasanya ini terjadi ketika Klien, yaitu, Pemroses Pesan (proses berbasis Java):
    1. Tidak memiliki Sertifikat Klien di KeyStore-nya, atau;
    2. Tidak dapat mengirim Sertifikat Klien. Hal ini dapat terjadi jika sistem tidak dapat menemukan Sertifikat yang diterbitkan oleh salah satu Certificate Authority yang dapat diterima di Server Backend. Artinya, jika {i>Certificate Authority<i} dari {i>Leaf Certificate<i} Klien (yaitu, Sertifikat pertama dalam rantai) tidak cocok dengan konfigurasi server backend dapat diterima, maka Pemroses Pesan tidak akan mengirimkan sertifikat.

Mari kita lihat masing-masing penyebab ini secara terpisah seperti berikut.

Penyebab: Tidak Ada Sertifikat Klien

Diagnosis

Jika tidak ada Sertifikat di Keystore yang ditentukan di bagian Info SSL Endpoint Target atau server target yang digunakan dalam Endpoint Target, maka itulah penyebab {i>error<i} ini.

Ikuti langkah-langkah di bawah untuk menentukan apakah ini penyebabnya:

  1. Menentukan Keystore yang digunakan di Endpoint Target atau Server Target untuk Proxy API tertentu dengan menggunakan langkah-langkah di bawah:
    1. Mendapatkan nama referensi Keystore dari elemen Keystore di bagian SSLInfo di Endpoint Target atau Server Target.

      Mari kita lihat contoh bagian SSLInfo di Konfigurasi Endpoint Target:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. Pada contoh di atas, nama referensi Keystore adalah "myKeystoreRef".
    3. Buka UI Edge dan pilih API Proxies -> Konfigurasi Lingkungan.

      Pilih tab References dan telusuri nama referensi Keystore. Catat nama di kolom Reference untuk referensi Keystore tertentu. Nama ini akan menjadi nama Keystore Anda.


      alt_text

    4. Pada contoh di atas, Anda dapat melihat bahwa myKeystoreRef memiliki referensi ke "myKeystore". Oleh karena itu, nama Keystore adalah myKeystore.
  2. Periksa apakah Keystore ini berisi Sertifikat menggunakan UI Edge atau Mencantumkan sertifikat untuk API keystore.
  3. Jika Keystore berisi Sertifikat, beralihlah ke Penyebab: Ketidakcocokan Certificate Authority.
  4. Jika Keystore tidak berisi Sertifikat apa pun, maka itulah alasannya Sertifikat Klien tidak dikirim oleh Pemroses Pesan.

Resolusi

  1. Pastikan rantai Sertifikat Klien yang benar dan lengkap diupload ke Keystore tertentu di Pemroses Pesan.

Penyebab: Ketidakcocokan Certificate Authority

Umumnya ketika Server meminta klien untuk mengirim Sertifikat, itu menunjukkan serangkaian Penerbit atau {i>Certificate Authorities<i} yang diterima. Jika Penerbit/Otoritas Sertifikat sertifikat entitas akhir (yaitu, dalam rantai Sertifikat) di Keystore Pemroses Pesan, tidak cocok dengan {i>Certificate Authorities <i}apa pun yang diterima oleh server {i>backend<i}, Pemroses Pesan (yang merupakan proses berbasis Java) akan tidak mengirim Sertifikat ke server backend.

Gunakan langkah-langkah di bawah untuk mengonfirmasi apakah hal ini yang terjadi:

  1. Mencantumkan sertifikat untuk API keystore.
  2. Dapatkan Rincian dari setiap Sertifikat yang diperoleh pada Langkah #1 di atas menggunakan Dapatkan sertifikat untuk API keystore.
  3. Catat penerbit leaf Certificate (yaitu Sertifikat pertama dalam rantai sertifikat) yang disimpan di Keystore.

    Contoh Sertifikat Ikon Daun Nest

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

    Dalam contoh di atas, penerbit/Certificate Authority "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"

  4. Tentukan daftar Penerbit atau Certificate Authority yang diterima server backend menggunakan salah satu teknik berikut:

    Teknik #1: Gunakan perintah openssl di bawah ini:

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

    Lihat bagian berjudul "Nama CA Sertifikat Klien yang Dapat Diterima" dalam output perintah ini seperti yang ditunjukkan di bawah ini:

    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
    

    Teknik #2: Periksa paket Certificate Request di TCP/IP Packets, tempat server backend meminta Klien mengirim sertifikatnya:

    Dalam contoh paket TCP/IP yang ditunjukkan di atas, Certificate Request paketnya adalah pesan #7. Lihat bagian "Nama yang Dibedakan", yang berisi Certificate Authority yang dapat diterima di server backend.

    alt_text

  5. Verifikasi apakah Certificate Authority yang diperoleh di langkah#3 cocok dengan daftar yang ada dari Penerbit atau Certificate Authority yang diterima server backend yang diperoleh di langkah #4. Jika ada ketidakcocokan, Pemroses Pesan tidak akan mengirim Sertifikat Klien ke server backend.

    Pada contoh di atas, Anda dapat melihat bahwa penerbit {i>Leaf Certificate<i} Klien di Keystore Pemroses Pesan tidak cocok dengan server backend mana pun Certificate Authority yang Diterima. Karenanya, Pemroses Pesan tidak mengirim Sertifikat Klien ke server backend. Hal ini menyebabkan handshake SSL gagal dan server backend mengirim "Fatal alert: bad_certificate" untuk membuat pesan email baru.

Resolusi

  1. Pastikan sertifikat dengan penerbit/Certificate Authority yang sesuai penerbit/Otoritas Sertifikat {i>Leaf Certificate<i} Klien (sertifikat pertama di jaringan) disimpan di Truststore server backend.
  2. Dalam contoh yang dijelaskan di Playbook ini, Sertifikat dengan penerbit "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" ditambahkan ke Truststore server backend untuk menyelesaikan masalah.

Jika masalah masih berlanjut, buka Harus Mengumpulkan Informasi Diagnostik.

Harus Mengumpulkan Informasi Diagnostik

Jika masalah berlanjut bahkan setelah mengikuti petunjuk di atas, kumpulkan informasi diagnostik berikut. Hubungi dan bagikan ke Dukungan Apigee Edge:

  1. Jika Anda adalah pengguna Cloud Publik, berikan informasi berikut:
    1. Nama Organisasi
    2. Nama Lingkungan
    3. Nama Proxy API
    4. Menyelesaikan perintah curl untuk mereproduksi error
    5. File Rekaman Aktivitas yang menampilkan error
    6. Paket TCP/IP yang ditangkap di server backend
  2. Jika Anda adalah pengguna Private Cloud, berikan informasi berikut:
    1. Pesan Error Lengkap diamati
    2. Paket Proxy API
    3. File Rekaman Aktivitas yang menampilkan error
    4. Log Pemroses Pesan /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Paket TCP/IP yang diambil di server backend atau {i>Message Processor<i}.
    6. Output Dapatkan sertifikat untuk API keystore.
  3. Detail tentang bagian mana saja dalam Playbook ini yang telah Anda coba dan bagian lainnya wawasan yang akan membantu kita menyelesaikan masalah dengan cepat.