Lỗi giao tiếp SSL - Chứng chỉ ứng dụng khách không hợp lệ

Bạn đang xem tài liệu về Apigee Edge.
Truy cập vào tài liệu Apigee X.
thông tin

Dấu hiệu

Ứng dụng khách nhận được mã trạng thái HTTP 503 kèm theo thông báo "Dịch vụ không sử dụng được" dưới dạng phản hồi cho một yêu cầu API. Trong dấu vết giao diện người dùng, bạn sẽ thấy error.cause Received fatal alert: bad_certificate trong Target Request Flow (Luồng yêu cầu mục tiêu) cho yêu cầu API không thành công.

Nếu có quyền truy cập vào nhật ký Message Processor, bạn sẽ thấy thông báo lỗi dưới dạng Received fatal alert: bad_certificate cho yêu cầu API không thực hiện được. Lỗi này xảy ra trong quá trình bắt tay SSL giữa Trình xử lý thông báo và máy chủ phụ trợ trong thiết lập TLS 2 chiều.

Thông báo Lỗi

Ứng dụng Client sẽ nhận được mã phản hồi sau:

HTTP/1.1 503 Service Unavailable

Ngoài ra, bạn có thể thấy thông báo lỗi sau:

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

Người dùng Đám mây riêng sẽ thấy lỗi sau đây cho yêu cầu API cụ thể trong nhật ký của Trình xử lý thông báo /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

Nguyên nhân có thể dẫn đến vấn đề này

Sau đây là những nguyên nhân có thể gây ra vấn đề này:

Nguyên nhân Nội dung mô tả Hướng dẫn khắc phục sự cố áp dụng cho
Không có chứng chỉ máy khách Keystore được dùng trong Điểm cuối mục tiêu của Máy chủ mục tiêu không có Chứng chỉ máy khách nào. Người dùng Edge Private Cloud và Public Cloud
Tổ chức phát hành chứng chỉ không khớp Tổ chức phát hành chứng chỉ của chứng chỉ gốc (Chứng chỉ đầu tiên trong chuỗi chứng chỉ) trong Kho khoá của Trình xử lý thông báo không khớp với bất kỳ Tổ chức phát hành chứng chỉ nào được máy chủ phụ trợ chấp nhận. Người dùng Edge Private Cloud và Public Cloud

Các bước chẩn đoán thường gặp

  1. Bật tính năng theo dõi trong giao diện người dùng Edge, thực hiện lệnh gọi API và tái hiện vấn đề.
  2. Trong kết quả theo dõi giao diện người dùng, hãy chuyển qua từng Giai đoạn và xác định vị trí xảy ra lỗi. Lỗi sẽ xảy ra trong Target Request Flow.
  3. Kiểm tra Luồng cho thấy lỗi, bạn sẽ thấy lỗi như trong dấu vết ví dụ bên dưới:

    alt_text

  4. Như bạn thấy trong ảnh chụp màn hình ở trên, error.cause "Received fatal alert: bad_certificate".
  5. Nếu bạn là người dùng Đám mây riêng, hãy làm theo hướng dẫn bên dưới:
    1. Bạn có thể lấy mã thông báo cho yêu cầu API không thành công bằng cách xác định giá trị của Tiêu đề lỗi "X-Apigee.Message-ID" trong Giai đoạn do AX chỉ ra trong dấu vết.
    2. Tìm mã thông báo này trong nhật ký Message Processor /opt/apigee/var/log/edge-message-processor/system.log và xác định xem bạn có thể tìm thấy thêm thông tin nào về lỗi này hay không:
      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]

      Nhật ký Message Processor có dấu vết ngăn xếp cho lỗi Received fatal alert: bad_certificate, nhưng không có thêm thông tin nào cho biết nguyên nhân gây ra vấn đề này.

  6. Để điều tra thêm về vấn đề này, bạn cần thu thập các gói TCP/IP bằng công cụ tcpdump.
    1. Nếu là người dùng Đám mây riêng, bạn có thể thu thập các gói TCP/IP trên máy chủ phụ trợ hoặc Trình xử lý thông báo. Tốt nhất là bạn nên ghi lại các gói này trên máy chủ phụ trợ khi các gói được giải mã trên máy chủ phụ trợ.
    2. Nếu bạn là người dùng Đám mây công khai, hãy ghi lại các gói TCP/IP trên máy chủ phụ trợ.
    3. Sau khi quyết định vị trí mà bạn muốn thu thập các gói TCP/IP, hãy dùng lệnh tcpdump bên dưới để thu thập các gói TCP/IP.
    4. tcpdump -i any -s 0 host <IP address> -w <File name>

      Nếu bạn đang lấy các gói TCP/IP trên Trình xử lý thông báo, hãy sử dụng địa chỉ IP công khai của máy chủ phụ trợ trong lệnh tcpdump.

      Nếu có nhiều địa chỉ IP cho máy chủ phụ trợ/Trình xử lý thông báo, thì bạn cần sử dụng một lệnh tcpdump khác. Hãy tham khảo tcpdump để biết thêm thông tin về công cụ này và các biến thể khác của lệnh này.

  7. Phân tích các gói TCP/IP bằng công cụ Wireshark hoặc công cụ tương tự mà bạn quen dùng.

Sau đây là kết quả phân tích dữ liệu mẫu về các gói TCP/IP bằng công cụ Wireshark:

alt_text

  1. Thông báo số 4 trong tcpdump ở trên cho thấy Trình xử lý thông báo (nguồn) đã gửi thông báo "Client Hello" đến máy chủ phụ trợ (đích đến).
  2. Thông báo số 5 cho biết máy chủ phụ trợ xác nhận thông báo Xin chào của ứng dụng từ Trình xử lý thông báo.
  3. Máy chủ phụ trợ gửi thông báo "Server Hello" (Xin chào máy chủ) cùng với Chứng chỉ của máy chủ, sau đó yêu cầu Ứng dụng gửi Chứng chỉ của ứng dụng trong Thông báo số 7.
  4. Message Processor hoàn tất quá trình xác minh Chứng chỉ và xác nhận thông báo ServerHello của máy chủ phụ trợ trong Thông báo số 8.
  5. Trình xử lý thông báo sẽ gửi Chứng chỉ của mình đến máy chủ phụ trợ trong Thông báo số 9.
  6. Máy chủ phụ trợ xác nhận đã nhận được Chứng chỉ của Trình xử lý thông báo trong Thông báo số 11.
  7. Tuy nhiên, nó sẽ gửi ngay Cảnh báo nghiêm trọng: Chứng chỉ không hợp lệ đến Trình xử lý thông báo (Thông báo số 12). Điều này cho biết Chứng chỉ do Trình xử lý thông báo gửi đi không hợp lệ, do đó, quy trình Xác minh chứng chỉ không thành công trên máy chủ phụ trợ. Do đó, quá trình Bắt tay giao thức SSL không thành công và kết nối sẽ bị đóng.


    alt_text

  8. Bây giờ, hãy xem Thông báo số 9 để kiểm tra nội dung của chứng chỉ do Trình xử lý thông báo gửi:


    alt_text

  9. Như bạn có thể nhận thấy, máy chủ phụ trợ không nhận được Chứng chỉ nào từ Máy khách (Độ dài chứng chỉ: 0). Do đó, máy chủ phụ trợ sẽ gửi Cảnh báo nghiêm trọng: Chứng chỉ không hợp lệ.
  10. Thông thường, điều này xảy ra khi Máy khách, tức là Trình xử lý thông báo (một quy trình dựa trên Java):
    1. Không có Chứng chỉ ứng dụng nào trong KeyStore hoặc;
    2. Không thể gửi Chứng chỉ ứng dụng. Điều này có thể xảy ra nếu không tìm thấy Chứng chỉ do một trong các Tổ chức phát hành chứng chỉ chấp nhận được của Máy chủ phụ trợ cấp. Tức là nếu Tổ chức phát hành chứng chỉ của Chứng chỉ gốc của ứng dụng (tức là Chứng chỉ đầu tiên trong chuỗi) không khớp với bất kỳ Tổ chức phát hành chứng chỉ nào mà máy chủ phụ trợ chấp nhận, thì Trình xử lý thông báo sẽ không gửi chứng chỉ.

Hãy xem xét từng nguyên nhân riêng biệt như sau.

Nguyên nhân: Không có chứng chỉ ứng dụng

Chẩn đoán

Nếu không có Chứng chỉ nào trong Kho khoá được chỉ định trong phần Thông tin SSL của Điểm cuối mục tiêu hoặc máy chủ mục tiêu được dùng trong Điểm cuối mục tiêu, thì đó là nguyên nhân gây ra lỗi này.

Hãy làm theo các bước bên dưới để xác định xem đây có phải là nguyên nhân hay không:

  1. Xác định Kho khoá đang được dùng trong Điểm cuối mục tiêu hoặc Máy chủ mục tiêu cho Proxy API cụ thể bằng cách làm theo các bước bên dưới:
    1. Lấy tên tham chiếu Kho khoá từ phần tử Kho khoá trong phần SSLInfo trong Điểm cuối mục tiêu hoặc Máy chủ mục tiêu.

      Hãy xem một phần SSLInfo mẫu trong Cấu hình điểm cuối mục tiêu:

      <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://myKeystoreRef</KeyStore>
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>ref://myTrustStoreRef</TrustStore>
      </SSLInfo>
    2. Trong ví dụ trên, tên tham chiếu Keystore là "myKeystoreRef".
    3. Chuyển đến giao diện người dùng Edge rồi chọn API Proxies -> Environment Configurations (API Proxy -> Cấu hình môi trường).

      Chọn thẻ Tệp đối chiếu rồi tìm tên đối chiếu Kho khoá. Ghi lại tên trong cột Tham chiếu cho tham chiếu Keystore cụ thể. Đây sẽ là tên Kho khoá của bạn.


      alt_text

    4. Trong ví dụ trên, bạn có thể nhận thấy rằng myKeystoreRef có tham chiếu đến "myKeystore". Do đó, tên Keystore là myKeystore.
  2. Kiểm tra xem Kho khoá này có chứa Chứng chỉ hay không bằng cách sử dụng Giao diện người dùng Edge hoặc API Liệt kê chứng chỉ cho kho khoá.
  3. Nếu Keystore có chứa(các) Chứng chỉ, hãy chuyển sang Nguyên nhân: Tổ chức phát hành chứng chỉ không khớp.
  4. Nếu Keystore không chứa bất kỳ Chứng chỉ nào, thì đó là lý do khiến Trình xử lý thông báo không gửi Chứng chỉ máy khách.

Độ phân giải

  1. Đảm bảo rằng chuỗi Chứng chỉ máy khách phù hợp và đầy đủ được tải lên Kho khoá cụ thể trong Trình xử lý thông báo.

Nguyên nhân: Tổ chức phát hành chứng chỉ không khớp

Thông thường, khi Máy chủ yêu cầu Máy khách gửi Chứng chỉ của mình, Máy chủ sẽ cho biết tập hợp các Tổ chức phát hành hoặc Tổ chức phát hành chứng chỉ được chấp nhận. Nếu Tổ chức phát hành/Tổ chức phát hành chứng chỉ của chứng chỉ gốc (tức là Chứng chỉ đầu tiên trong chuỗi Chứng chỉ) trong Kho khoá của Trình xử lý thông báo không khớp với bất kỳ Tổ chức phát hành chứng chỉ nào mà máy chủ phụ trợ chấp nhận, thì Trình xử lý thông báo (là một quy trình dựa trên Java) sẽ không gửi Chứng chỉ đến máy chủ phụ trợ.

Hãy làm theo các bước dưới đây để xác nhận xem có phải trường hợp này hay không:

  1. Liệt kê các chứng chỉ cho API kho khoá.
  2. Lấy thông tin chi tiết của từng Chứng chỉ thu được ở Bước 1 ở trên bằng cách sử dụng API Lấy chứng chỉ cho kho khoá.
  3. Ghi lại đơn vị phát hành của Chứng chỉ gốc (tức là Chứng chỉ đầu tiên trong chuỗi chứng chỉ) được lưu trữ trong Kho khoá.

    Chứng chỉ gốc mẫu

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

    Trong ví dụ trên, tổ chức phát hành/Cơ quan cấp giấy chứng nhận là "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"

  4. Xác định danh sách các Tổ chức phát hành hoặc Cơ quan cấp chứng chỉ được máy chủ phụ trợ chấp nhận bằng một trong những kỹ thuật sau:

    Kỹ thuật 1: Sử dụng lệnh openssl bên dưới:

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

    Tham khảo phần có tiêu đề "Acceptable Client Certificate CA names" (Tên CA của chứng chỉ máy khách được chấp nhận) trong đầu ra của lệnh này như minh hoạ dưới đây:

    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

    Kỹ thuật 2: Kiểm tra gói Certificate Request trong Gói TCP/IP, trong đó máy chủ phụ trợ yêu cầu Máy khách gửi chứng chỉ của máy khách:

    Trong các gói TCP/IP mẫu được minh hoạ ở trên, gói Certificate Request là thông báo số 7. Tham khảo phần "Tên riêng biệt", trong đó có Cơ quan cấp chứng chỉ được chấp nhận của máy chủ phụ trợ.

    alt_text

  5. Xác minh xem Tổ chức phát hành chứng chỉ thu được ở bước 3 có khớp với danh sách Tổ chức phát hành hoặc Tổ chức phát hành chứng chỉ được máy chủ phụ trợ chấp nhận thu được ở bước 4 hay không. Nếu có sự không khớp, thì Trình xử lý thông báo sẽ không gửi Chứng chỉ ứng dụng đến máy chủ phụ trợ.

    Trong ví dụ trên, bạn có thể nhận thấy rằng đơn vị phát hành Chứng chỉ gốc của ứng dụng khách trong Kho khoá của Trình xử lý thông báo không khớp với bất kỳ Cơ quan cấp chứng chỉ được chấp nhận nào của máy chủ phụ trợ. Do đó, Message Processor không gửi Chứng chỉ máy khách đến máy chủ phụ trợ. Điều này khiến quá trình bắt tay SSL không thành công và máy chủ phụ trợ gửi thông báo "Fatal alert: bad_certificate".

Độ phân giải

  1. Đảm bảo rằng chứng chỉ có tổ chức phát hành/Tổ chức phát hành chứng chỉ khớp với tổ chức phát hành/Tổ chức phát hành chứng chỉ của Chứng chỉ gốc của ứng dụng (chứng chỉ đầu tiên trong chuỗi) được lưu trữ trong Truststore của máy chủ phụ trợ.
  2. Trong ví dụ được mô tả trong Sổ tay này, Chứng chỉ có tổ chức phát hành "issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com" đã được thêm vào Truststore của máy chủ phụ trợ để giải quyết vấn đề.

Nếu vấn đề vẫn tiếp diễn, hãy chuyển đến phần Thông tin chẩn đoán bắt buộc.

Phải thu thập thông tin chẩn đoán

Nếu vấn đề vẫn tiếp diễn ngay cả sau khi bạn làm theo hướng dẫn ở trên, vui lòng thu thập thông tin chẩn đoán sau. Liên hệ và chia sẻ các thông tin đó với Nhóm hỗ trợ Apigee Edge:

  1. Nếu bạn là người dùng Đám mây công khai, hãy cung cấp những thông tin sau:
    1. Tên tổ chức
    2. Tên môi trường
    3. Tên Proxy API
    4. Hoàn tất lệnh curl để tái tạo lỗi
    5. Tệp theo dõi cho thấy lỗi
    6. Các gói TCP/IP được thu thập trên máy chủ phụ trợ
  2. Nếu bạn là người dùng Đám mây riêng, hãy cung cấp những thông tin sau:
    1. Thông báo lỗi hoàn chỉnh đã quan sát được
    2. Gói API Proxy
    3. Tệp theo dõi cho thấy lỗi
    4. Nhật ký Bộ xử lý tin nhắn /opt/apigee/var/log/edge-message-processor/logs/system.log
    5. Các gói TCP/IP được thu thập trên máy chủ phụ trợ hoặc Trình xử lý thông báo.
    6. Đầu ra của Nhận chứng chỉ cho API kho khoá.
  3. Thông tin chi tiết về những phần trong Sổ tay này mà bạn đã thử và mọi thông tin chi tiết khác sẽ giúp chúng tôi nhanh chóng giải quyết vấn đề này.