คุณกำลังดูเอกสารประกอบของ Apigee Edge
ไปที่
เอกสารประกอบของ Apigee X info
ลักษณะปัญหา
แอปพลิเคชันไคลเอ็นต์ได้รับรหัสสถานะ HTTP 503 พร้อม
ข้อความ "Service Unavailable" เป็นการตอบกลับคำขอ API
ในข้อมูลการย้ายข้อมูล UI คุณจะเห็นว่า error.cause
คือ Received fatal alert: bad_certificate ในโฟลว์คำขอเป้าหมาย
สำหรับคำขอ API ที่ล้มเหลว
หากคุณมีสิทธิ์เข้าถึงบันทึกของ Message Processor
คุณจะเห็นข้อความแสดงข้อผิดพลาดเป็น Received fatal alert: bad_certificate
สำหรับคำขอ API ที่ล้มเหลว ข้อผิดพลาดนี้เกิดขึ้นระหว่างกระบวนการแฮนด์เชค SSL
ระหว่าง Message Processor กับเซิร์ฟเวอร์แบ็กเอนด์ในการตั้งค่า TLS แบบ 2 ทาง
ข้อความแสดงข้อผิดพลาด
แอปพลิเคชันไคลเอ็นต์ได้รับโค้ดตอบกลับต่อไปนี้
HTTP/1.1 503 Service Unavailable
นอกจากนี้ คุณอาจเห็นข้อความแสดงข้อผิดพลาดต่อไปนี้
{
"fault": {
"faultstring":"The Service is temporarily unavailable",
"detail":{
"errorcode":"messaging.adaptors.http.flow.ServiceUnavailable"
}
}
}ผู้ใช้ Private Cloud จะเห็นข้อผิดพลาดต่อไปนี้สำหรับคำขอ API ที่เฉพาะเจาะจง
ในบันทึกของ Message Processor /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 ที่ใช้ในปลายทางเป้าหมายของเซิร์ฟเวอร์เป้าหมายไม่มีใบรับรองไคลเอ็นต์ | ผู้ใช้ Edge Private และ Public Cloud |
| ผู้ออกใบรับรองไม่ตรงกัน | ผู้ออกใบรับรองของใบรับรองย่อย (ใบรับรองแรกในกลุ่มใบรับรอง) ใน Keystore ของ Message Processor ไม่ตรงกับผู้ออกใบรับรองที่เซิร์ฟเวอร์แบ็กเอนด์ยอมรับ | ผู้ใช้ Edge Private และ Public Cloud |
ขั้นตอนการวินิจฉัยที่พบบ่อย
- เปิดใช้การย้ายข้อมูลใน UI ของ Edge, เรียก API และจำลองปัญหา
- ในผลลัพธ์การย้ายข้อมูล UI ให้ไปที่แต่ละเฟสและระบุตำแหน่งที่เกิด ข้อผิดพลาด ข้อผิดพลาดน่าจะเกิดขึ้นในโฟลว์คำขอเป้าหมาย
- ตรวจสอบโฟลว์ที่แสดงข้อผิดพลาด คุณควรเห็นข้อผิดพลาดตามที่แสดง
ในข้อมูลการย้ายข้อมูลตัวอย่างด้านล่าง:

- ตามที่เห็นในภาพหน้าจอด้านบน error.cause คือ "Received fatal alert: bad_certificate".
- หากคุณเป็นผู้ใช้ Private Cloud ให้ทำตามวิธีการด้านล่าง:
- คุณสามารถรับรหัสข้อความสำหรับคำขอ API ที่ล้มเหลวได้โดยการกำหนดค่าของส่วนหัวข้อผิดพลาด "
X-Apigee.Message-ID" ในเฟสที่ระบุโดย AX ในข้อมูลการย้ายข้อมูล - ค้นหารหัสข้อความนี้ในบันทึกของ Message Processor
/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]
บันทึกของ Message Processor มีสแต็กเทรซสำหรับข้อผิดพลาด
Received fatal alert: bad_certificateแต่ไม่มี ข้อมูลเพิ่มเติมที่ระบุสาเหตุของปัญหานี้
- คุณสามารถรับรหัสข้อความสำหรับคำขอ API ที่ล้มเหลวได้โดยการกำหนดค่าของส่วนหัวข้อผิดพลาด "
- หากต้องการตรวจสอบปัญหานี้เพิ่มเติม คุณจะต้องบันทึกแพ็กเก็ต TCP/IP โดยใช้
tcpdump เครื่องมือ
- หากคุณเป็นผู้ใช้ Private Cloud คุณจะบันทึก แพ็กเก็ต TCP/IP ในเซิร์ฟเวอร์แบ็กเอนด์หรือ Message Processor ได้ เราขอแนะนำให้บันทึกในเซิร์ฟเวอร์แบ็กเอนด์เนื่องจากระบบจะถอดรหัสแพ็กเก็ตใน เซิร์ฟเวอร์แบ็กเอนด์
- หากคุณเป็นผู้ใช้ Public Cloud ให้บันทึกแพ็กเก็ต TCP/IP ในเซิร์ฟเวอร์แบ็กเอนด์
- เมื่อตัดสินใจได้แล้วว่าจะบันทึกแพ็กเก็ต TCP/IP ที่ใด ให้ใช้คำสั่ง tcpdump ด้านล่างเพื่อบันทึกแพ็กเก็ต TCP/IP
tcpdump -i any -s 0 host <IP address> -w <File name>
หากคุณบันทึกแพ็กเก็ต TCP/IP ใน Message Processor ให้ใช้ที่อยู่ IP สาธารณะของเซิร์ฟเวอร์แบ็กเอนด์ในคำสั่ง
tcpdumpหากเซิร์ฟเวอร์แบ็กเอนด์/Message Processor มีที่อยู่ IP หลายรายการ แล้ว คุณจะต้องใช้คำสั่ง tcpdump อื่น โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับเครื่องมือนี้และคำสั่งอื่นๆ ที่คล้ายกันได้ที่ tcpdump
- วิเคราะห์แพ็กเก็ต TCP/IP โดยใช้เครื่องมือ Wireshark หรือเครื่องมือที่คล้ายกันที่คุณคุ้นเคย
ต่อไปนี้คือการวิเคราะห์ข้อมูลแพ็กเก็ต TCP/IP ตัวอย่างโดยใช้เครื่องมือ Wireshark

- ข้อความ #4 ใน tcpdump ด้านบนแสดงให้เห็นว่า Message Processor (ต้นทาง) ส่งข้อความ "Client Hello" ไปยังเซิร์ฟเวอร์แบ็กเอนด์ (ปลายทาง)
- ข้อความ #5 แสดงให้เห็นว่าเซิร์ฟเวอร์แบ็กเอนด์รับทราบข้อความ Client Hello จาก Message Processor
- เซิร์ฟเวอร์แบ็กเอนด์ส่งข้อความ "Server Hello" พร้อมกับใบรับรอง จากนั้นขอให้ไคลเอ็นต์ส่งใบรับรองในข้อความ #7
- Message Processor ตรวจสอบใบรับรองเสร็จสมบูรณ์และรับทราบ ข้อความ ServerHello ของเซิร์ฟเวอร์แบ็กเอนด์ในข้อความ #8
- Message Processor ส่งใบรับรองไปยังเซิร์ฟเวอร์แบ็กเอนด์ในข้อความ #9
- เซิร์ฟเวอร์แบ็กเอนด์รับทราบการรับใบรับรองของ Message Processor Certificate ในข้อความ #11
อย่างไรก็ตาม เซิร์ฟเวอร์จะส่งการแจ้งเตือนร้ายแรง: ใบรับรองไม่ถูกต้อง ไปยัง Message Processor ทันที (ข้อความ #12) ซึ่งแสดงให้เห็นว่าใบรับรองที่ Message Processor ส่งมาไม่ถูกต้อง ดังนั้นการตรวจสอบใบรับรองจึงล้มเหลวใน เซิร์ฟเวอร์แบ็กเอนด์ ด้วยเหตุนี้ การแฮนด์เชค SSL จึงล้มเหลวและระบบจะปิดการเชื่อมต่อ

ตอนนี้มาดูข้อความ #9 เพื่อตรวจสอบเนื้อหาของใบรับรองที่ Message Processor ส่งมา

- คุณจะเห็นว่าเซิร์ฟเวอร์แบ็กเอนด์ไม่ได้รับใบรับรองจากไคลเอ็นต์ (ความยาวใบรับรอง: 0) ดังนั้น เซิร์ฟเวอร์แบ็กเอนด์จึงส่งการแจ้งเตือนร้ายแรง: ใบรับรองไม่ถูกต้อง
- โดยปกติแล้วเหตุการณ์นี้จะเกิดขึ้นเมื่อไคลเอ็นต์ ซึ่งก็คือ Message Processor (กระบวนการที่ใช้ Java) มีลักษณะดังนี้
- ไม่มีใบรับรองไคลเอ็นต์ใน Keystore หรือ
- ส่งใบรับรองไคลเอ็นต์ไม่ได้ เหตุการณ์นี้อาจเกิดขึ้นหากไคลเอ็นต์ไม่พบ ใบรับรองที่ออกโดยผู้ออกใบรับรองที่เซิร์ฟเวอร์แบ็กเอนด์ยอมรับ หมายความว่า หากผู้ออกใบรับรองของใบรับรองย่อยของไคลเอ็นต์ (เช่น ใบรับรองแรกในกลุ่มใบรับรอง) ไม่ตรงกับผู้ออกใบรับรองที่เซิร์ฟเวอร์แบ็กเอนด์ยอมรับ Message Processor จะไม่ส่งใบรับรอง
มาดูสาเหตุแต่ละข้อแยกกันดังนี้
สาเหตุ: ไม่มีใบรับรองไคลเอ็นต์
การวินิจฉัย
หากไม่มีใบรับรองใน Keystore ที่ระบุไว้ในส่วนข้อมูล SSL ของปลายทางเป้าหมาย หรือเซิร์ฟเวอร์เป้าหมายที่ใช้ในปลายทางเป้าหมาย นั่นคือสาเหตุของข้อผิดพลาดนี้
ทำตามขั้นตอนด้านล่างเพื่อดูว่านี่คือสาเหตุหรือไม่
- ระบุ Keystore ที่ใช้ในปลายทางเป้าหมายหรือเซิร์ฟเวอร์เป้าหมาย
สำหรับพร็อกซี API ที่เฉพาะเจาะจงโดยทำตามขั้นตอนด้านล่าง:
- รับชื่ออ้างอิง Keystore จากองค์ประกอบ Keystore
ในส่วน SSLInfo ในปลายทางเป้าหมายหรือเซิร์ฟเวอร์เป้าหมาย
มาดูส่วน SSLInfo ตัวอย่างในการกำหนดค่าปลายทางเป้าหมายกัน
<SSLInfo> <Enabled>true</Enabled> <ClientAuthEnabled>true</ClientAuthEnabled> <KeyStore>ref://myKeystoreRef</KeyStore> <KeyAlias>myKey</KeyAlias> <TrustStore>ref://myTrustStoreRef</TrustStore> </SSLInfo>
- ในตัวอย่างด้านบน ชื่ออ้างอิง Keystore คือ "myKeystoreRef"
- ไปที่ UI ของ Edge แล้วเลือกพร็อกซี API -> การกำหนดค่าสภาพแวดล้อม
เลือกแท็บข้อมูลอ้างอิง แล้วค้นหาชื่ออ้างอิง Keystore จดชื่อในคอลัมน์ข้อมูลอ้างอิง สำหรับข้อมูลอ้างอิง Keystore ที่เฉพาะเจาะจง ชื่อนี้จะเป็นชื่อ Keystore

- ในตัวอย่างด้านบน คุณจะเห็นว่า myKeystoreRef มีข้อมูลอ้างอิง ถึง "myKeystore" ดังนั้นชื่อ Keystore คือ myKeystore
- รับชื่ออ้างอิง Keystore จากองค์ประกอบ Keystore
ในส่วน SSLInfo ในปลายทางเป้าหมายหรือเซิร์ฟเวอร์เป้าหมาย
- ตรวจสอบว่า Keystore นี้มีใบรับรองหรือไม่โดยใช้ UI ของ Edge หรือ List certs for keystore API
- หาก Keystore มีใบรับรอง ให้ไปที่ สาเหตุ: ผู้ออกใบรับรองไม่ตรงกัน.
- หาก Keystore ไม่มีใบรับรอง นั่นคือเหตุผลที่ Message Processor ไม่ได้ส่งใบรับรองไคลเอ็นต์
ความละเอียด
- ตรวจสอบว่าได้อัปโหลดกลุ่มใบรับรองไคลเอ็นต์ที่ถูกต้องและสมบูรณ์ไปยัง Keystore ที่เฉพาะเจาะจงใน Message Processor แล้ว
สาเหตุ: ผู้ออกใบรับรองไม่ตรงกัน
โดยทั่วไป เมื่อเซิร์ฟเวอร์ขอให้ไคลเอ็นต์ส่งใบรับรอง เซิร์ฟเวอร์จะ ระบุชุดผู้ออกใบรับรองหรือผู้ออกใบรับรองที่ยอมรับ หากผู้ออกใบรับรองของใบรับรองย่อย (เช่น ใบรับรองแรกในกลุ่มใบรับรอง) ใน Keystore ของ Message Processor ไม่ตรงกับผู้ออกใบรับรองที่เซิร์ฟเวอร์แบ็กเอนด์ยอมรับ Message Processor (ซึ่งเป็น กระบวนการที่ใช้ Java) จะไม่ส่งใบรับรองไปยังเซิร์ฟเวอร์แบ็กเอนด์
ทำตามขั้นตอนด้านล่างเพื่อยืนยันว่ากรณีนี้เกิดขึ้นหรือไม่
- List certs for keystore API.
- รับรายละเอียดของใบรับรองแต่ละรายการที่ได้รับในขั้นตอนที่ 1 ด้านบนโดยใช้ Get cert for keystore API
- จดผู้ออกใบรับรองย่อย (เช่น ใบรับรองแรกในกลุ่มใบรับรอง) ที่จัดเก็บไว้ใน 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" - ระบุรายการผู้ออกใบรับรองหรือผู้ออกใบรับรองที่เซิร์ฟเวอร์แบ็กเอนด์ยอมรับโดยใช้เทคนิคใดเทคนิคหนึ่งต่อไปนี้
เทคนิคที่ 1: ใช้คำสั่ง 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
เทคนิคที่ 2: ตรวจสอบแพ็กเก็ต
Certificate Requestใน แพ็กเก็ต TCP/IP ซึ่งเซิร์ฟเวอร์แบ็กเอนด์ขอให้ไคลเอ็นต์ส่งใบรับรอง:ในแพ็กเก็ต TCP/IP ตัวอย่างที่แสดงด้านบน
Certificate Requestแพ็กเก็ตคือข้อความ #7 ดูส่วน "ชื่อที่แยกความแตกต่าง" ซึ่งมีผู้ออกใบรับรองที่เซิร์ฟเวอร์แบ็กเอนด์ยอมรับ
ตรวจสอบว่าผู้ออกใบรับรองที่ได้รับในขั้นตอนที่ 3 ตรงกับรายการ ผู้ออกใบรับรองหรือผู้ออกใบรับรองที่เซิร์ฟเวอร์แบ็กเอนด์ยอมรับซึ่งได้รับในขั้นตอนที่ 4 หรือไม่ หากไม่ตรงกัน Message Processor จะไม่ส่งใบรับรองไคลเอ็นต์ ไปยังเซิร์ฟเวอร์แบ็กเอนด์
ในตัวอย่างด้านบน คุณจะเห็นว่าผู้ออกใบรับรองย่อยของไคลเอ็นต์ ใน Keystore ของ Message Processor ไม่ตรงกับ ผู้ออกใบรับรองที่เซิร์ฟเวอร์แบ็กเอนด์ยอมรับ ดังนั้น Message Processor จึงไม่ ส่งใบรับรองไคลเอ็นต์ไปยังเซิร์ฟเวอร์แบ็กเอนด์ ซึ่งทำให้การแฮนด์เชค SSL ล้มเหลวและเซิร์ฟเวอร์แบ็กเอนด์ส่งข้อความ "
Fatal alert: bad_certificate"
ความละเอียด
- ตรวจสอบว่าใบรับรองที่มีผู้ออกใบรับรองที่ตรงกับ ผู้ออกใบรับรองย่อยของไคลเอ็นต์ (ใบรับรองแรก ในกลุ่มใบรับรอง) จัดเก็บไว้ใน Truststore ของเซิร์ฟเวอร์แบ็กเอนด์
- ในตัวอย่างที่อธิบายไว้ในเพลย์บุ๊กนี้ เราได้เพิ่มใบรับรองที่มีผู้ออกใบรับรอง
"issuer" : "CN=MyCompany Test SHA2 CA G2, DC=testcore, DC=test, DC=dir, DC=mycompany, DC=com"ลงใน Truststore ของเซิร์ฟเวอร์แบ็กเอนด์เพื่อแก้ปัญหา
หากยังพบปัญหาอยู่ ให้ไปที่ ข้อมูลการวินิจฉัยที่ต้องรวบรวม
ข้อมูลการวินิจฉัยที่ต้องรวบรวม
หากยังพบปัญหาอยู่แม้จะทำตามวิธีการข้างต้นแล้ว โปรดรวบรวมข้อมูลการวินิจฉัยต่อไปนี้ ติดต่อและแชร์ข้อมูลดังกล่าวกับทีมสนับสนุนของ Apigee Edge:
- หากคุณเป็นผู้ใช้ Public Cloud โปรดระบุข้อมูลต่อไปนี้
- ชื่อองค์กร
- ชื่อสภาพแวดล้อม
- ชื่อพร็อกซี API
- คำสั่ง curl ที่สมบูรณ์เพื่อจำลองข้อผิดพลาด
- ไฟล์การย้ายข้อมูลที่แสดงข้อผิดพลาด
- แพ็กเก็ต TCP/IP ที่บันทึกไว้ในเซิร์ฟเวอร์แบ็กเอนด์
- หากคุณเป็นผู้ใช้ Private Cloud โปรดระบุข้อมูลต่อไปนี้
- ข้อความแสดงข้อผิดพลาดทั้งหมดที่พบ
- App Bundle ของพร็อกซี API
- ไฟล์การย้ายข้อมูลที่แสดงข้อผิดพลาด
- บันทึกของ Message Processor
/opt/apigee/var/log/edge-message-processor/logs/system.log - แพ็กเก็ต TCP/IP ที่บันทึกไว้ในเซิร์ฟเวอร์แบ็กเอนด์หรือ Message Processor
- เอาต์พุตของ Get cert for keystore API.
- รายละเอียดเกี่ยวกับส่วนต่างๆ ในเพลย์บุ๊กนี้ที่คุณได้ลองทำตามแล้ว รวมถึงข้อมูลเชิงลึกอื่นๆ ที่จะช่วยให้เราแก้ปัญหานี้ได้อย่างรวดเร็ว