您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档。 信息
问题
如果客户端和服务器无法使用 TLS/SSL 协议建立通信,则会发生 TLS/SSL 握手失败。如果在 Apigee Edge 中发生此错误,客户端应用将收到 HTTP 状态 503 以及服务不可用消息。在发生 TLS/SSL 握手失败的任何 API 调用后,您都会看到此错误消息。
错误消息
HTTP/1.1 503 Service Unavailable
当 TLS/SSL 握手失败时,您也可以看到此错误消息:
Received fatal alert: handshake_failure
可能的原因
TLS(传输层安全协议,其前身为 SSL)是在网络服务器和 Web 客户端(例如浏览器或应用)之间建立加密链接的标准安全技术。握手过程可让 TLS/SSL 客户端和服务器建立一组可与其通信的密钥。在此过程中,客户端和服务器:
- 同意要使用的协议版本。
- 选择要使用的加密算法。
- 通过交换和验证数字证书来相互进行身份验证。
如果 TLS/SSL 握手成功,TLS/SSL 客户端和服务器会安全地互相传输数据。否则,如果 TLS/SSL 握手失败,则连接会终止,并且客户端会收到 503 Service Unavailable
错误。
TLS/SSL 握手失败的可能原因如下:
原因 | 说明 | 谁可以执行问题排查步骤 |
---|---|---|
协议不匹配 | 服务器不支持该客户端使用的协议。 | 私有云和公有云用户 |
加密套件不匹配 | 服务器不支持客户端使用的加密套件。 | 私有云和公有云用户 |
证书不正确 | 客户端使用的网址中的主机名与服务器端存储的证书中的主机名不匹配。 | 私有云和公有云用户 |
客户端或服务器端存储的证书链不完整或无效。 | 私有云和公有云用户 | |
客户端向服务器发送不正确或已过期的证书,或从服务器发送到客户端。 | 私有云和公有云用户 | |
已启用 SNI 的服务器 | 后端服务器已启用服务器名称指示 (SNI);但是,客户端无法与 SNI 服务器通信。 | 仅限 Private Cloud 用户 |
协议不匹配
如果服务器在传入(北向)或传出(南向)连接不支持客户端使用的协议,则会发生 TLS/SSL 握手失败。另请参阅 了解北向和南向连接。
诊断
- 确定错误是发生在北向连接还是南向连接中。如需有关如何作出此判定的进一步指导,请参阅 确定问题的根源。
- 运行
tcpdump 实用程序以收集更多信息:
- 如果您是 Private Cloud 用户,则可以在相关客户端或服务器上收集
tcpdump
数据。客户端可以是客户端应用(针对传入或北向连接),也可以是消息处理器(针对传出或南向连接)。根据您在第 1 步中所确定的,服务器可以是边缘路由器(用于传入或北向连接),也可以是后端服务器(用于传出或南向连接)。 - 如果您是公有云用户,您只能在客户端应用(针对传入或北向连接)或后端服务器上(针对传出或南向连接)收集
tcpdump
数据,因为您无权访问边缘路由器或消息处理器。
tcpdump -i any -s 0 host IP address -w File name
如需详细了解如何使用tcpdump
命令,请参阅 tcpdump 数据。 - 如果您是 Private Cloud 用户,则可以在相关客户端或服务器上收集
- 使用 Wireshark 工具或类似工具分析
tcpdump
数据。 - 以下是使用 Wireshark 对
tcpdump 进行分析的示例:
- 在此示例中,消息处理器和后端服务器(传出连接或南向连接)之间发生了 TLS/SSL 握手失败。
- 以下
tcpdump
输出中的消息 4 显示消息处理器(来源)向后端服务器(目标)发送了一条“Client Hello”消息。
如果您选择
Client Hello
消息,则消息处理器会使用 TLSv1.2 协议,如下所示:- 消息 5 显示后端服务器确认了来自消息处理器的“Client Hello”消息。
- 后端服务器会立即向消息处理器发送 严重提醒:关闭通知(消息 6)。这意味着 TLS/SSL 握手失败,连接将关闭。
进一步查看消息 6 可以发现,TLS/SSL 握手失败的原因在于后端服务器仅支持 TLSv1.0 协议,如下所示:
- 由于消息处理器与后端服务器使用的协议不匹配,因此后端服务器发送了以下消息:Fatal Alert Message: Close Notifications。
分辨率
消息处理器在 Java 8 上运行,并默认使用 TLSv1.2 协议。如果后端服务器不支持 TLSv1.2 协议,您可以采取以下任一措施来解决此问题:
- 升级您的后端服务器以支持 TLSv1.2 协议。建议您使用此解决方案,因为协议 TLSv1.2 更安全。
- 如果您因某种原因无法立即升级后端服务器,则可以按照以下步骤强制消息处理器使用 TLSv1.0 协议与后端服务器通信:
- 如果您未在代理的 TargetEndpoint 定义中指定目标服务器,请将
Protocol
元素设置为TLSv1.0
,如下所示:<TargetEndpoint name="default"> … <HTTPTargetConnection> <SSLInfo> <Enabled>true</Enabled> <Protocols> <Protocol>TLSv1.0</Protocol> </Protocols> </SSLInfo> <URL>https://myservice.com</URL> </HTTPTargetConnection> … </TargetEndpoint>
- 如果您为代理配置了 目标服务器,请使用 此管理 API 在特定目标服务器配置中将协议设置为 TLSv1.0。
- 如果您未在代理的 TargetEndpoint 定义中指定目标服务器,请将
密码不匹配
如果在 Apigee Edge 中的传入(北向)或传出(南向)连接上不支持客户端使用的加密套件算法,则您会看到 TLS/SSL 握手失败。另请参阅 了解北向和南向连接。
诊断
- 确定错误是发生在北向连接还是南向连接中。如需有关如何作出此判定的进一步指导,请参阅确定问题的根源。
- 运行
tcpdump 实用程序以收集更多信息:
- 如果您是 Private Cloud 用户,则可以在相关客户端或服务器上收集
tcpdump
数据。客户端可以是客户端应用(针对传入或北向连接),也可以是消息处理器(针对传出或南向连接)。根据您在第 1 步中所确定的,服务器可以是边缘路由器(用于传入或北向连接),也可以是后端服务器(用于传出或南向连接)。 - 如果您是公有云用户,您只能在客户端应用(针对传入或北向连接)或后端服务器上(针对传出或南向连接)收集
tcpdump
数据,因为您无权访问边缘路由器或消息处理器。
tcpdump -i any -s 0 host IP address -w File name
如需详细了解如何使用tcpdump
命令,请参阅 tcpdump 数据。 - 如果您是 Private Cloud 用户,则可以在相关客户端或服务器上收集
- 使用 Wireshark 工具或您熟悉的任何其他工具分析
tcpdump
数据。 - 以下是使用 Wireshark 对
tcpdump
输出进行的示例分析:- 在此示例中,客户端应用与边缘路由器(北向连接)之间发生了 TLS/SSL 握手失败。
tcpdump
输出是在 Edge 路由器上收集的。 以下
tcpdump
输出中的消息 4 显示客户端应用(来源)向边缘路由器(目标)发送了“Client Hello”消息。选择客户端 Hello 消息可表明客户端应用使用的是 TLSv1.2 协议。
- 消息 5 显示边缘路由器确认来自客户端应用的“Client Hello”消息。
- Edge 路由器立即向客户端应用发送一条严重提醒:握手失败(消息 6)。这意味着 TLS/SSL 握手失败,连接将关闭。
- 进一步了解消息 6,显示了以下信息:
- 边缘路由器支持 TLSv1.2 协议。这意味着客户端应用与边缘路由器之间的协议匹配。
但是,Edge 路由器仍会向客户端应用发送致命提醒:握手失败,如以下屏幕截图所示:
- 该错误可能是由以下某个问题导致的:
- 客户端应用未使用 Edge Router 支持的加密套件算法。
- 边缘路由器已启用 SNI,但客户端应用不发送服务器名称。
tcpdump
输出中的消息 4 列出了客户端应用支持的加密套件算法,如下所示:/opt/nginx/conf.d/0-default.conf
文件中列出了边缘路由器支持的加密套件算法。在此示例中,边缘路由器仅支持高加密套件算法。- 客户端应用不使用任何高加密套件算法。 这种不匹配就是 TLS/SSL 握手失败的原因。
- 由于边缘路由器启用了 SNI,请向下滚动到
tcpdump
输出中的消息 #4,并确认客户端应用在正确发送服务器名称,如下图所示:
- 如果此名称有效,您可以推断出 TLS/SSL 握手失败,因为客户端应用使用的加密套件算法不受边缘路由器支持。
- 在此示例中,客户端应用与边缘路由器(北向连接)之间发生了 TLS/SSL 握手失败。
分辨率
您必须确保客户端使用服务器支持的加密套件算法。如需解决“诊断”部分中所述的问题,请下载并安装 Java Cryptography Extension (JCE) 软件包,并将其包含在 Java 安装中,以支持高加密套件算法。
证书不正确
如果在 Apigee Edge 的传入(北向)或传出(南向)连接中,密钥库/truststore 中的证书不正确,则发生 TLS/SSL 握手失败。另请参阅 了解北向和南向连接。
如果问题是“北向”问题,您可能会看到不同的错误消息,具体取决于根本原因。
以下部分列出了示例错误消息以及诊断和解决此问题的步骤。
错误消息
您可能会看到不同的错误消息,具体取决于 TLS/SSL 握手失败的原因。 以下是调用 API 代理时可能会看到的错误消息示例:
* SSL certificate problem: Invalid certificate chain * Closing connection 0 curl: (60) SSL certificate problem: Invalid certificate chain More details here: http://curl.haxx.se/docs/sslcerts.html
可能的原因
此问题的典型原因如下:
原因 | 说明 | 谁可以执行问题排查步骤 |
主机名不匹配 |
网址中使用的主机名与路由器密钥库中的证书不匹配。例如,如果网址中使用的主机名为 myorg.domain.com ,而证书的 CN 中的主机名为 CN=something.domain.com. ,就会出现不匹配的情况
|
Edge Private 和公有云用户 |
证书链不完整或不正确 | 证书链不完整或不正确。 | 仅限 Edge Private 和公有云用户 |
服务器或客户端发送的证书已过期或未知 | 服务器或客户端在北向连接或南向连接时发送已过期或未知的证书。 | Edge Private Cloud 和 Edge 公有云用户 |
主机名不匹配
诊断
- 请记下由以下 Edge Management API 调用返回的网址中使用的主机名:
curl -v https://myorg.domain.com/v1/getinfo
例如:curl -v https://api.enterprise.apigee.com/v1/getinfo
- 获取存储在特定密钥库中的证书中使用的 CN。您可以使用以下边缘管理 API 来获取证书的详细信息:
-
在密钥库中获取证书名称:
如果您是 Private Cloud 用户,请按如下方式使用 Management API:
curl -v https://management-server-ip:port/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs
如果您是公有云用户,请按如下方式使用 Management API:
curl -v https://api.enterprise.apigee.com/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs
-
使用 Edge Management API 获取密钥库中证书的详细信息。
如果您是 Private Cloud 用户:
curl -v https://management-server-ip:port/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs/cert-name
如果您是 Public Cloud 用户:
curl -v https://api.enterprise.apigee.com/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs/cert-name
证书示例:
"certInfo": [ { "basicConstraints": "CA:FALSE", "expiryDate": 1456258950000, "isValid": "No", "issuer": "SERIALNUMBER=07969287, CN=Go Daddy Secure Certification Authority, OU=http://certificates.godaddy.com/repository, O=\"GoDaddy.com, Inc.\", L=Scottsdale, ST=Arizona, C=US", "publicKey": "RSA Public Key, 2048 bits", "serialNumber": "07:bc:a7:39:03:f1:56", "sigAlgName": "SHA1withRSA", "subject": "CN=something.domain.com, OU=Domain Control Validated, O=something.domain.com", "validFrom": 1358287055000, "version": 3 },
主证书中主题名称的 CN 为
something.domain.com.
由于 API 请求网址中使用的主机名(请参阅上面的第 1 步)与证书中的主题名称不匹配,因此您会收到 TLS/SSL 握手失败。
-
在密钥库中获取证书名称:
分辨率
此问题可以通过以下两种方式之一解决:
- 如果您还没有证书,请获取主题 CN 具有通配符证书的证书(如果您还没有证书),然后将新的完整证书链上传到密钥库。例如:
"subject": "CN=*.domain.com, OU=Domain Control Validated, O=*.domain.com",
- 如果您还没有主题 CN,请使用 your-org 获取具有现有主题 CN 的证书(如果您还没有证书)。your-domain 作为主题备用名称,然后将完整的证书链上传到密钥库。
参考
证书链不完整或不正确
诊断
- 获取存储在特定密钥库中的证书中使用的 CN。您可以使用以下边缘管理 API 来获取证书的详细信息:
-
在密钥库中获取证书名称:
如果您是 Private Cloud 用户:
curl -v https://management-server-ip:port/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs
如果您是 Public Cloud 用户:
curl -v https://api.enterprise.apigee.com/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs
-
获取密钥库中证书的详细信息:
如果您是 Private Cloud 用户:
curl -v https://management-server-ip:port/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs/cert-name
如果您是 公有云用户:
curl -v https://api.enterprise.apigee.com/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs/cert-name
- 请验证证书及其链,确认其遵循 证书链的工作原理一文(旨在确保证书链有效且完整)中提供的准则。如果存储在密钥库中的证书链不完整或无效,您会看到 TLS/SSL 握手失败。
- 以下图片展示了包含无效证书链且中间证书和根证书不匹配的示例证书:
颁发者和主题不匹配的中间证书和根证书示例
-
在密钥库中获取证书名称:
分辨率
- 获取包含完整且有效的证书链的证书(如果您还没有证书)。
- 运行以下 openssl 命令以验证证书链是否正确且完整:
openssl verify -CAfile root-cert -untrusted intermediate-cert main-cert
- 将经过验证的证书链上传到密钥库。
服务器或客户端发送的证书已过期或未知
如果服务器/客户端在北向连接或南向连接中发送了错误/已过期的证书,则另一端(服务器/客户端)会拒绝该证书,从而导致 TLS/SSL 握手失败。
诊断
- 确定错误是发生在北向连接还是南向连接中。如需有关如何作出此判定的进一步指导,请参阅 确定问题的根源。
- 运行
tcpdump 实用程序以收集更多信息:
- 如果您是 Private Cloud 用户,则可以在相关客户端或服务器上收集
tcpdump
数据。客户端可以是客户端应用(针对传入或北向连接),也可以是消息处理器(针对传出或南向连接)。根据您在第 1 步中所确定的,服务器可以是边缘路由器(用于传入或北向连接),也可以是后端服务器(用于传出或南向连接)。 - 如果您是公有云用户,您只能在客户端应用(针对传入或北向连接)或后端服务器上(针对传出或南向连接)收集
tcpdump
数据,因为您无权访问边缘路由器或消息处理器。
tcpdump -i any -s 0 host IP address -w File name
如需详细了解如何使用tcpdump
命令,请参阅 tcpdump 数据。 - 如果您是 Private Cloud 用户,则可以在相关客户端或服务器上收集
- 使用 Wireshark 或类似工具分析
tcpdump
数据。 - 根据
tcpdump
输出结果,确定在验证步骤中拒绝证书的主机(客户端或服务器)。 - 如果数据未加密,您可以从
tcpdump
输出中检索从另一端发送的证书。这有助于比较此证书是否与信任库中可用的证书匹配。 - 查看示例
tcpdump
,了解消息处理器和后端服务器之间的 SSL 通信。显示证书未知错误的示例
tcpdump
- 消息处理器(客户端)在消息 59 中向后端服务器(服务器)发送“Client Hello”。
- 后端服务器在消息 #61 中向消息处理器发送“Server Hello”。
- 二者会相互验证所使用的协议和加密套件算法。
- 后端服务器在消息 #68 中向消息处理器发送证书和服务器 Hello Done 消息。
- 消息处理器会在消息 #70 中发送严重提醒“Description: Certificate Unknown”。
- 深入了解消息 70,除了提醒消息之外,没有其他详细信息,如下所示:
- 查看消息 #68,获取有关后端服务器发送的证书的详细信息,如下图所示:
- 如上图所示,后端服务器的证书及其完整链都位于“证书”部分下。
- 如果路由器(北向)或消息处理器(南向)发现证书未知(如上例所示),请按以下步骤操作:
- 获取存储在特定信任库中的证书及其链。(请参阅路由器的虚拟主机配置和消息处理器的目标端点配置)。您可以使用以下 API 获取证书的详细信息:
-
在信任库中获取证书名称:
curl -v https://management-server-ip:port/v1/organizations/org-name/environments/env-name/keystores/truststore-name/certs
-
获取信任库中证书的详情:
curl -v https://management-server-ip:port/v1/organizations/org-name/environments/env-name/keystores/truststore-name/certs/cert-name
-
在信任库中获取证书名称:
- 检查存储在路由器(北向)或消息处理器(南向)的信任库中的证书是否与客户端应用(北向)或目标服务器的密钥库(南向)中存储的证书匹配,或与从
tcpdump
输出获取的证书匹配。如果不匹配,则这就是 TLS/SSL 握手失败的原因。
- 获取存储在特定信任库中的证书及其链。(请参阅路由器的虚拟主机配置和消息处理器的目标端点配置)。您可以使用以下 API 获取证书的详细信息:
- 如果客户端应用(北向)或目标服务器(南向)发现证书未知,请按以下步骤操作:
- 获取存储在特定密钥库中的证书使用的完整证书链。(请参阅路由器的虚拟主机配置和消息处理器的目标端点配置。)您可以使用以下 API 获取证书的详细信息:
-
获取密钥库中的证书名称:
curl -v https://management-server-ip:port/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs
-
获取密钥库中证书的详细信息:
curl -v https://management-server-ip:port/v1/organizations/org-name/environments/env-name/keystores/keystore-name/certs/cert-name
-
获取密钥库中的证书名称:
- 检查存储在路由器(北向)或消息处理器(南向)的密钥库中的证书是否与客户端应用(北向)或目标服务器(南向)的信任存储区中存储的证书匹配,或者与从
tcpdump
输出获取的证书匹配。如果不一致,则表示 SSL 握手失败。
- 获取存储在特定密钥库中的证书使用的完整证书链。(请参阅路由器的虚拟主机配置和消息处理器的目标端点配置。)您可以使用以下 API 获取证书的详细信息:
- 如果发现服务器/客户端发送的证书已过期,则接收客户端/服务器会拒绝证书,并且您会在
tcpdump
中看到以下提醒消息:提醒(级别:严重;说明:证书已过期)
- 验证相应主机密钥库中的证书是否已过期。
分辨率
如需解决上例中发现的问题,请将有效的后端服务器的证书上传到消息处理器上的信任方。
下表总结了根据问题原因解决问题的步骤。
原因 | 说明 | 分辨率 |
证书过期 |
NorthBound
|
将新证书及其完整链上传到相应主机上的密钥库。 |
SouthBound
|
将新证书及其完整链上传到相应主机上的密钥库。 | |
未知证书 |
NorthBound
|
将有效证书上传到相应主机上的信任库。 |
SouthBound
|
将有效证书上传到相应主机上的信任库。 |
已启用 SNI 的服务器
如果客户端正在与已启用服务器名称指示 (SNI) 的服务器通信,但该客户端未启用 SNI,则可能会发生 TLS/SSL 握手失败。在北向或 Edge 的南向连接中都可能发生这种情况。
首先,您需要识别所使用的服务器的主机名和端口号,并检查它是否启用了 SNI。
已启用 SNI 的服务器标识
- 执行
openssl
命令并尝试连接到相关的服务器主机名(Edge 路由器或后端服务器),而不传递服务器名称,如下所示:openssl s_client -connect hostname:port
您可能会获得证书,有时您可能会在 openssl 命令中发现握手失败,如下所示:
CONNECTED(00000003) 9362:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64.50.6/src/ssl/s23_clnt.c:593
- 执行
openssl
命令,并通过传递服务器名称来尝试连接到相关的服务器主机名(Edge 路由器或后端服务器),如下所示:openssl s_client -connect hostname:port -servername hostname
- 如果您在第 1 步和第 2 步获得握手失败,或者在第 1 步和第 2 步获得不同的证书,则表示指定的服务器已启用 SNI。
确定服务器已启用 SNI 后,您可以按照以下步骤检查 TLS/SSL 握手失败是否是由客户端无法与 SNI 服务器通信造成的。
诊断
- 确定错误是发生在北向连接还是南向连接中。如需有关如何作出此判定的进一步指导,请参阅 确定问题的根源。
- 运行
tcpdump 实用程序以收集更多信息:
- 如果您是 Private Cloud 用户,则可以在相关客户端或服务器上收集
tcpdump
数据。客户端可以是客户端应用(针对传入或北向连接),也可以是消息处理器(针对传出或南向连接)。根据您在第 1 步中所确定的,服务器可以是边缘路由器(用于传入或北向连接),也可以是后端服务器(用于传出或南向连接)。 - 如果您是公有云用户,您只能在客户端应用(针对传入或北向连接)或后端服务器上(针对传出或南向连接)收集
tcpdump
数据,因为您无权访问边缘路由器或消息处理器。
tcpdump -i any -s 0 host IP address -w File name
如需详细了解如何使用tcpdump
命令,请参阅 tcpdump 数据。 - 如果您是 Private Cloud 用户,则可以在相关客户端或服务器上收集
- 使用 Wireshark 或类似工具分析
tcpdump
输出。 - 以下是使用 Wireshark 对
tcpdump
进行的示例分析:- 在此示例中,边缘消息处理器和后端服务器(南向连接)之间发生了 TLS/SSL 握手失败。
- 以下
tcpdump
输出中的消息 4 显示消息处理器(来源)向后端服务器(目的地)发送了一条“Client Hello”消息。 - 选择“Client Hello”消息即表明消息处理器使用的是 TLSv1.2 协议。
- 消息 4 显示后端服务器确认了来自消息处理器的“Client Hello”消息。
- 后端服务器立即向消息处理器发送一条严重警报:握手失败(消息 5)。这意味着 TLS/SSL 握手失败,连接将关闭。
- 查看消息 6,了解以下信息
- 后端服务器支持 TLSv1.2 协议。这意味着消息处理器和后端服务器之间的协议匹配。
- 但是,后端服务器仍会向消息处理器发送 Fatal Alert: Handshake Failure(严重提醒:握手失败),如下图所示:
- 此错误可能是由以下某种原因造成的:
- 消息处理器未使用后端服务器支持的加密套件算法。
- 后端服务器已启用 SNI,但客户端应用没有发送服务器名称。
- 请更详细地查看
tcpdump
输出中的消息 3 (Client Hello)。请注意,缺少 Extension: server_name,如下所示: - 这可确认消息处理器没有将 server_name 发送到已启用 SNI 的后端服务器。
- 这是导致 TLS/SSL 握手失败的原因,也是后端服务器向消息处理器发送严重提醒:握手失败的原因。
- 验证消息处理器上
system.properties
中的jsse.enableSNIExtension property
是否设置为 false,以确认消息处理器未启用与启用 SNI 的服务器进行通信。
分辨率
通过执行以下步骤,启用消息处理器以与启用 SNI 的服务器进行通信:
- 创建
/opt/apigee/customer/application/message-processor.properties
文件(如果尚不存在)。 - 将以下行添加到此文件中:
conf_system_jsse.enableSNIExtension=true
- 将此文件的所有者 chown 分配给
apigee:apigee
:chown apigee:apigee /opt/apigee/customer/application/message-processor.properties
- 重启消息处理器。
/opt/apigee/apigee-service/bin/apigee-service message-processor restart
- 如果您有多个消息处理器,请对所有消息处理器重复第 1 步到第 4 步。
如果您无法确定 TLS/SSL 握手失败的原因并解决问题,或者需要任何进一步帮助,请与 Apigee Edge 支持团队联系。分享有关问题的完整详细信息以及 tcpdump
输出。