SSL Handshake Failures - Bad Client Certificate

شما در حال مشاهده مستندات Apigee Edge هستید.
به مستندات Apigee X مراجعه کنید .
اطلاعات

علامت

برنامه‌ی کلاینت، کد وضعیت HTTP 503 را به همراه پیام "Service Unavailable" به عنوان پاسخ به یک درخواست API دریافت می‌کند. در ردیابی رابط کاربری، مشاهده خواهید کرد که error.cause در جریان درخواست هدف برای درخواست ناموفق API، Received fatal alert: bad_certificate است.

اگر به گزارش‌های پردازنده پیام دسترسی داشته باشید، متوجه پیام خطایی با عنوان Received fatal alert: bad_certificate برای درخواست ناموفق API خواهید شد. این خطا در طول فرآیند SSL handshake بین پردازنده پیام و سرور backend در یک تنظیم TLS دوطرفه مشاهده می‌شود.

پیام خطا

برنامه کلاینت کد پاسخ زیر را دریافت می‌کند:

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 مورد استفاده در Target Endpoint مربوط به سرور Target هیچ گونه گواهی کلاینتی ندارد. کاربران فضای ابری خصوصی و عمومی اج
عدم تطابق مرجع صدور گواهی مرجع صدور گواهی برگ گواهی (اولین گواهی در زنجیره گواهی) در Keystore پردازنده پیام با هیچ یک از مراجع صدور گواهی پذیرفته شده توسط سرور backend مطابقت ندارد. کاربران فضای ابری خصوصی و عمومی اج

مراحل تشخیص رایج

  1. ردیابی را در رابط کاربری Edge فعال کنید، فراخوانی API را انجام دهید و مشکل را دوباره ایجاد کنید.
  2. در نتایج ردیابی رابط کاربری، در هر مرحله پیمایش کنید و محل وقوع خطا را تعیین کنید. خطا در جریان درخواست هدف رخ داده است.
  3. جریانی که خطا را نشان می‌دهد بررسی کنید، باید خطایی را که در مثال زیر نشان داده شده است، مشاهده کنید:

    alt_text

  4. همانطور که در تصویر بالا مشاهده می‌کنید، error.cause برابر با "Received fatal alert: bad_certificate" است.
  5. اگر از فضای ابری خصوصی استفاده می‌کنید ، دستورالعمل‌های زیر را دنبال کنید:
    1. شما می‌توانید شناسه پیام مربوط به درخواست ناموفق API را با تعیین مقدار هدر خطا " X-Apigee.Message-ID " در فازی که با AX در ردیابی نشان داده شده است، دریافت کنید.
    2. شناسه این پیام را در فایل /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. برای بررسی بیشتر این مشکل، باید بسته‌های TCP/IP را با استفاده از ابزار tcpdump ضبط کنید.
    1. اگر شما یک کاربر ابر خصوصی هستید، می‌توانید بسته‌های TCP/IP را روی سرور backend یا پردازشگر پیام ضبط کنید. ترجیحاً، آنها را روی سرور backend ضبط کنید زیرا بسته‌ها در سرور backend رمزگشایی می‌شوند.
    2. اگر شما یک کاربر ابر عمومی هستید، بسته‌های TCP/IP را در سرور backend ضبط کنید.
    3. پس از اینکه تصمیم گرفتید بسته‌های TCP/IP را از کجا ضبط کنید، از دستور tcpdump زیر برای ضبط بسته‌های TCP/IP استفاده کنید.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      اگر بسته‌های TCP/IP را روی پردازنده پیام دریافت می‌کنید، از آدرس IP عمومی سرور backend در دستور tcpdump استفاده کنید.

      اگر چندین آدرس IP برای سرور backend/پردازنده پیام وجود دارد، باید از دستور tcpdump متفاوتی استفاده کنید. برای اطلاعات بیشتر در مورد این ابزار و سایر انواع این دستور، به tcpdump مراجعه کنید.

  7. بسته‌های TCP/IP را با استفاده از ابزار Wireshark یا ابزار مشابهی که با آن آشنا هستید، تجزیه و تحلیل کنید.

در اینجا تجزیه و تحلیل داده‌های نمونه بسته‌های TCP/IP با استفاده از ابزار Wireshark آمده است:

alt_text

  1. پیام شماره ۴ در tcpdump بالا نشان می‌دهد که پردازشگر پیام (منبع) یک پیام "Client Hello" به سرور backend (مقصد) ارسال کرده است.
  2. پیام شماره ۵ نشان می‌دهد که سرور backend پیام Client Hello را از پردازنده پیام تأیید می‌کند.
  3. سرور backend پیام "Server Hello" را به همراه گواهی خود ارسال می‌کند و سپس از کلاینت درخواست می‌کند که گواهی خود را در پیام شماره ۷ ارسال کند.
  4. پردازشگر پیام، تأیید گواهی را تکمیل می‌کند و پیام ServerHello سرور backend را در پیام شماره ۸ تأیید می‌کند.
  5. پردازشگر پیام، گواهی خود را به سرور پشتیبان در پیام شماره ۹ ارسال می‌کند.
  6. سرور backend دریافت گواهی پردازشگر پیام را در پیام شماره ۱۱ تأیید می‌کند.
  7. با این حال، بلافاصله یک هشدار جدی: گواهی نامعتبر به پردازشگر پیام (پیام شماره ۱۲) ارسال می‌کند. این نشان می‌دهد که گواهی ارسال شده توسط پردازشگر پیام نامعتبر بوده و از این رو تأیید گواهی در سرور backend با شکست مواجه شده است. در نتیجه، SSL Handshake با شکست مواجه شده و اتصال قطع خواهد شد.


    alt_text

  8. حال بیایید به پیام شماره ۹ نگاهی بیندازیم تا محتوای گواهی ارسال شده توسط پردازنده پیام را بررسی کنیم:


    alt_text

  9. همانطور که مشاهده می‌کنید، سرور backend هیچ گواهی‌نامه‌ای از کلاینت دریافت نکرده است ( طول گواهی‌نامه: ۰) . از این رو، سرور backend هشدار نهایی: گواهی‌نامه‌ی نامناسب را ارسال می‌کند.
  10. معمولاً این اتفاق زمانی می‌افتد که کلاینت، یعنی پردازشگر پیام (یک فرآیند مبتنی بر جاوا):
    1. هیچ گواهی کلاینتی در KeyStore خود ندارد، یا؛
    2. قادر به ارسال گواهی کلاینت نیست. این اتفاق زمانی رخ می‌دهد که نتواند گواهی‌ای را پیدا کند که توسط یکی از مراجع صدور گواهی قابل قبول سرور Backend صادر شده باشد. به این معنی که اگر مرجع صدور گواهی گواهی Leaf کلاینت (یعنی اولین گواهی در زنجیره) با هیچ یک از مراجع صدور گواهی قابل قبول سرور Backend مطابقت نداشته باشد، پردازنده پیام گواهی را ارسال نخواهد کرد.

بیایید به هر یک از این علل به صورت جداگانه به شرح زیر نگاه کنیم.

علت: عدم وجود گواهی کلاینت

تشخیص

اگر هیچ گواهی‌نامه‌ای در Keystore مشخص‌شده در بخش SSL Info مربوط به Target Endpoint یا سرور هدف مورد استفاده در Target Endpoint وجود نداشته باشد، دلیل این خطا همین است.

برای تعیین اینکه آیا علت این است یا خیر، مراحل زیر را دنبال کنید:

  1. با استفاده از مراحل زیر، Keystore مورد استفاده در Target Endpoint یا Target Server برای API Proxy خاص را تعیین کنید:
    1. نام مرجع Keystore را از عنصر Keystore در بخش SSLInfo در Target Endpoint یا Target Server دریافت کنید.

      بیایید به یک نمونه از بخش SSLInfo در پیکربندی Target Endpoint نگاهی بیندازیم:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. در مثال بالا، نام مرجع Keystore، " myKeystoreRef" است.
    3. به رابط کاربری Edge بروید و API Proxies -> Environment Configurations را انتخاب کنید.

      تب References را انتخاب کنید و نام مرجع Keystore را جستجو کنید. نام مرجع Keystore خاص را در ستون Reference یادداشت کنید. این نام Keystore شما خواهد بود.


      alt_text

    4. در مثال بالا، می‌توانید متوجه شوید که myKeystoreRef به "myKeystore" ارجاع می‌دهد. بنابراین، نام Keystore، myKeystore است.
  2. با استفاده از رابط کاربری Edge یا با استفاده از List certs for keystore API بررسی کنید که آیا این Keystore حاوی گواهی است یا خیر.
  3. اگر Keystore حاوی گواهی(ها) است، به قسمت «علت: عدم تطابق مرجع صدور گواهی» بروید.
  4. اگر Keystore حاوی هیچ گواهی‌نامه‌ای نباشد، به همین دلیل است که گواهی‌نامه‌ی کلاینت توسط پردازنده‌ی پیام ارسال نمی‌شود.

وضوح تصویر

  1. اطمینان حاصل کنید که زنجیره گواهی کلاینت صحیح و کامل در Keystore خاص در پردازنده پیام بارگذاری شده است.

علت: عدم تطابق مرجع صدور گواهی

معمولاً وقتی سرور از کلاینت درخواست ارسال گواهی‌نامه‌اش را می‌کند، مجموعه‌ای از صادرکنندگان یا مراجع صدور گواهی‌نامه پذیرفته‌شده را نشان می‌دهد. اگر صادرکننده/مرجع صدور گواهی‌نامه برگ (یعنی اولین گواهی‌نامه در زنجیره گواهی‌نامه) در Keystore پردازنده پیام با هیچ یک از مراجع صدور گواهی‌نامه پذیرفته‌شده توسط سرور backend مطابقت نداشته باشد، پردازنده پیام (که یک فرآیند مبتنی بر جاوا است) گواهی‌نامه را به سرور backend ارسال نخواهد کرد.

برای تأیید این موضوع، از مراحل زیر استفاده کنید:

  1. فهرست گواهینامه‌های API مربوط به keystore .
  2. جزئیات هر گواهی‌نامه‌ای که در مرحله ۱ بالا به دست آمده را با استفاده از Get cert for 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. با استفاده از یکی از تکنیک‌های زیر، فهرست صادرکنندگان یا مراجع صدور گواهی مورد قبول سرور backend را تعیین کنید:

    تکنیک شماره ۱: از دستور openssl زیر استفاده کنید:

    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

    تکنیک شماره ۲: بسته Certificate Request را در بسته‌های TCP/IP بررسی کنید، جایی که سرور backend از کلاینت درخواست ارسال گواهی خود را می‌کند:

    در نمونه بسته‌های TCP/IP نشان داده شده در بالا، بسته Certificate Request ، پیام شماره ۷ است. به بخش «نام‌های متمایز» مراجعه کنید که شامل مجوزهای گواهی قابل قبول سرور backend است.

    alt_text

  5. بررسی کنید که آیا مرجع صدور گواهی (Certificate Authority) به دست آمده در مرحله ۳ با فهرست صادرکنندگان یا مراجع صدور گواهی مورد قبول سرور backend که در مرحله ۴ به دست آمده است، مطابقت دارد یا خیر. در صورت عدم تطابق، پردازنده پیام، گواهی کلاینت را به سرور backend ارسال نخواهد کرد.

    در مثال بالا، می‌توانید متوجه شوید که صادرکننده‌ی گواهی‌نامه‌ی برگ کلاینت در Keystore پردازنده‌ی پیام، با هیچ یک از مجوزهای گواهی‌نامه‌ی پذیرفته‌شده‌ی سرور backend مطابقت ندارد. از این رو، پردازنده‌ی پیام، گواهی‌نامه‌ی کلاینت را به سرور backend ارسال نمی‌کند. این باعث می‌شود که فرآیند دست‌دهی SSL با شکست مواجه شود و سرور backend پیام " Fatal alert: bad_certificate " را ارسال کند.

وضوح تصویر

  1. اطمینان حاصل کنید که گواهی صادر شده توسط صادرکننده/مرجع صدور گواهی که با صادرکننده/مرجع صدور گواهی برگ مشتری (اولین گواهی در زنجیره) مطابقت دارد، در Truststore سرور backend ذخیره شده است.
  2. در مثالی که در این راهنما توضیح داده شده است، گواهی با صادرکننده "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" به Truststore سرور backend اضافه شد تا مشکل حل شود.

اگر مشکل همچنان ادامه داشت، به «اطلاعات تشخیصی مورد نیاز برای جمع‌آوری» بروید.

باید اطلاعات تشخیصی جمع‌آوری شود

اگر مشکل حتی پس از دنبال کردن دستورالعمل‌های بالا ادامه داشت، لطفاً اطلاعات تشخیصی زیر را جمع‌آوری کنید. با پشتیبانی Apigee Edge تماس بگیرید و آنها را به اشتراک بگذارید:

  1. اگر کاربر فضای ابری عمومی هستید، اطلاعات زیر را ارائه دهید:
    1. نام سازمان
    2. نام محیط
    3. نام پروکسی API
    4. دستور curl را برای بازتولید خطا کامل کنید
    5. فایل ردیابی که خطا را نشان می‌دهد
    6. بسته‌های TCP/IP که در سرور backend ضبط می‌شوند
  2. اگر کاربر Private Cloud هستید، اطلاعات زیر را ارائه دهید:
    1. پیام خطای کامل مشاهده شد
    2. بسته پروکسی API
    3. فایل ردیابی که خطا را نشان می‌دهد
    4. گزارش‌های پردازشگر پیام /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. بسته‌های TCP/IP که در سرور backend یا پردازنده پیام ضبط می‌شوند.
    6. خروجی Get cert برای API مربوط به keystore .
  3. جزئیات مربوط به بخش‌هایی از این دفترچه راهنما که شما امتحان کرده‌اید و هرگونه اطلاعات دیگری که به ما در تسریع حل این مشکل کمک می‌کند.