Tomcat [9.0.26] - SSLHandshake 异常

Posted

技术标签:

【中文标题】Tomcat [9.0.26] - SSLHandshake 异常【英文标题】:Tomcat [9.0.26] - SSLHandshake Exception 【发布时间】:2020-04-01 13:52:23 【问题描述】:

我在 tomcat(版本 9.0.26)中的应用程序正在与第三方 HTTPS 网络服务交互。在 SSL 协商过程中,握手失败,我正在寻求调试帮助。

Tomcat启动参数为:

INFO:命令行参数: -Djavax.net.ssl.trustStore=C:\tomcat32\9.0.26\conf\MyTrustStore.p12 2019 年 12 月 8 日上午 8:56:08 org.apache.catalina.startup.VersionLoggerListener 日志信息:命令 行参数:-Djavax.net.ssl.trustStorePassword=MyPass 2019 年 12 月 8 日 上午 8:56:08 org.apache.catalina.startup.VersionLoggerListener 日志信息: 命令行参数:-Djavax.net.ssl.trustStoreType=PKCS12 Dec 08, 2019 年上午 8:56:08 org.apache.catalina.startup.VersionLoggerListener 日志 信息:命令行参数: -Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager 2019 年 12 月 8 日上午 8:56:08 org.apache.catalina.core.AprLifecycleListener 生命周期事件信息:加载的基于 APR 的 Apache Tomcat 本机库 [1.2.23] 使用 APR 版本 [1.7.0]。 2019 年 12 月 8 日上午 8:56:08 org.apache.catalina.core.AprLifecycleListener 生命周期事件信息:APR 能力:IPv6 [true]、sendfile [true]、接受过滤器 [false]、 随机[真]。 2019 年 12 月 8 日上午 8:56:08 org.apache.catalina.core.AprLifecycleListener 生命周期事件信息: APR/OpenSSL 配置:useAprConnector [false]、useOpenSSL [true] 2019 年 12 月 8 日上午 8:56:08 org.apache.catalina.core.AprLifecycleListener initializeSSL 信息:OpenSSL 已成功初始化 [OpenSSL 1.1.1c 2019 年 5 月 28 日] 2019 年 12 月 8 日上午 8:56:09 org.apache.coyote.AbstractProtocol 初始化信息:正在初始化 ProtocolHandler ["http-nio-8080"] 2019 年 12 月 8 日上午 8:56:10 org.apache.coyote.AbstractProtocol 初始化信息:正在初始化 ProtocolHandler [“ajp-nio-8009”] 2019 年 12 月 8 日上午 8:56:10 org.apache.catalina.startup.Catalina 加载信息:服务器初始化 在 [2,592] 毫秒内 2019 年 12 月 8 日上午 8:56:10 org.apache.catalina.core.StandardService startInternal INFO: 开始 服务 [卡特琳娜]

在启用 SSL 调试日志时,我在日志下面捕获了

允许不安全的重新协商:false 允许遗留的 hello 消息:true 是 初始握手:true 是否安全重新协商:false 忽略 不支持的密码套件:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLSv1 忽略不支持的密码套件: TLSv1 的 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 忽略不支持 密码套件:TLSv1 忽略的 TLS_RSA_WITH_AES_256_CBC_SHA256 不支持的密码套件:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 TLSv1 忽略不支持的密码套件: TLSv1 的 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 忽略不支持 密码套件:TLSv1 忽略的 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 不支持的密码套件:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 TLSv1 忽略不支持的密码套件: TLSv1.1 的 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 忽略 不支持的密码套件:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLSv1.1 忽略不支持的密码套件: TLSv1.1 的 TLS_RSA_WITH_AES_256_CBC_SHA256 忽略不支持 密码套件:TLSv1.1 的 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 忽略不受支持的密码套件: TLSv1.1 的 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 忽略不支持 密码套件:TLSv1.1 忽略的 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 不支持的密码套件:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 TLSv1.1 %% 没有缓存的客户端会话更新握手状态: client_hello1即将握手状态:server_hello[2] * ClientHello, TLSv1.2 RandomCookie: GMT: 1558998647 bytes = 181, 223, 221, 91, 197, 4, 57, 190, 202, 50, 65, 37, 54, 151, 211, 23, 88 , 35、181、111、187、68、160、166、229、25、76、123 会话 ID: 密码套件:[TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA、TLS_RSA_WITH_AES_256_CBC_SHA、 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA、TLS_DHE_RSA_WITH_AES_256_CBC_SHA、 TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA、TLS_RSA_WITH_AES_128_CBC_SHA、 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA、TLS_DHE_RSA_WITH_AES_128_CBC_SHA、 TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 压缩方法: 0 扩展 elliptic_curves,曲线名称:secp256r1, secp384r1, secp521r1、sect283k1、sect283r1、sect409k1、sect409r1、sect571k1、 sect571r1, secp256k1 扩展 ec_point_formats,格式: [未压缩] 扩展签名算法、签名算法: SHA512 与 ECDSA,SHA512 与 RSA,SHA384 与 ECDSA,SHA384 与 RSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA1withECDSA, SHA1withRSA、SHA1withDSA 扩展 extended_master_secret 扩展 server_name, server_name: [type=host_name (0), 价值=certservicesgateway.Bingonline.com] http-nio-8080-exec-3,写入:TLSv1.2 握手,长度 = 236 http-nio-8080-exec-3,读取:TLSv1.2 握手,长度 = 89 支票 握手状态:server_hello[2] ServerHello, TLSv1.2 RandomCookie: GMT: 1119462208 bytes = 96, 236, 134, 31, 185, 89, 247, 95, 189, 217, 105, 127, 42, 183, 115, 120, 142, 31, 103, 111, 54, 50, 166, 58, 130, 107, 63, 128 会话 ID: 15、155、163、64、244、187、119、250、40、154、103、47、201、208、 211、136、114、116、248、159、173、34、212、74、194、65、71、17、39、 181、196、228 密码套件:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 压缩方法:0 扩展 renegotiation_info, renegotiated_connection:扩展 ec_point_formats,格式: [未压缩,ansiX962_compressed_prime,ansiX962_compressed_char2] * %% 已初始化:[Session-6,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384] ** TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

在握手失败结束时找到“无效”记录器:

更新握手状态:change_cipher_spec 即将到来 握手状态:客户端完成[20] 即将到来的握手状态: 服务器 change_cipher_spec[-1] 即将握手状态:服务器 完成[20] http-nio-8080-exec-3,写入:TLSv1.2 更改密码规范, 长度 = 1 * 完成 verify_data: 124, 94, 237, 141, 218, 48, 210, 88, 98, 142, 112, 197 * 更新握手状态:完成[20] 即将到来的握手状态:服务器 change_cipher_spec[-1] 即将到来的握手状态:服务器 完成[20] http-nio-8080-exec-3,写入:TLSv1.2 握手,长度 = 40 http-nio-8080-exec-3,阅读:TLSv1.2 警报,长度 = 2 http-nio-8080-exec-3,RECV TLSv1.2 ALERT:致命,handshake_failure %% 无效:[Session-6,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384] http-nio-8080-exec-3,调用closeSocket() http-nio-8080-exec-3, 处理异常:javax.net.ssl.SSLHandshakeException:收到 致命警报:handshake_failure 2019-12-07 23:00:43.732 INFO --- [nio-8080-exec-3] .v.w.t.MyServiceHandler : @@@@@@@@@ 其他异常 发生在 MyServiceHandler.execute():com.sun.xml.internal.ws.client.ClientTransportException: HTTP 传输错误:javax.net.ssl.SSLHandshakeException:已接收 致命警报:handshake_failure 和原因 是:javax.net.ssl.SSLHandshakeException:收到致命警报: 握手失败 com.sun.xml.internal.ws.client.ClientTransportException:HTTP 传输错误:javax.net.ssl.SSLHandshakeException:收到致命错误 警报:handshake_failure at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.getOutput(未知 来源)在 com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(未知 来源)在 com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(未知 来源)在 com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(未知 来源)在 com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(未知 来源)在 com.sun.xml.internal.ws.api.pipe.Fiber._doRun(未知 来源)在 com.sun.xml.internal.ws.api.pipe.Fiber.doRun(未知 来源)在 com.sun.xml.internal.ws.api.pipe.Fiber.runSync(未知 来源)

从记录器来看,我认为使用的 SSL 协议版本是 TLS1.2,看起来不错。看起来密码不匹配 - 但不确定我是否忽略了某些东西以及如何修复它。

在进一步检查日志时,发现了这个错误:

无法解析的证书扩展:1 1:ObjectId:2.5.29.31 Criticality=false 无法解析的 CRLDistributionPoints 扩展由于 java.io.IOException:无效的 URI name:ldap://Enroll.visaca.com:389/cn=签证信息传递 外部 CA,c=US,ou=Visa International Service 关联,o=VISA?certificateRevocationList

更新 - 12 月 9 日 - 与我们的中间件支持团队协商,他们表示上述 CRL 异常可能是误报。

因此,在这个假设下,仔细查看日志并与TLS handshake steps wiki 中列出的步骤进行比较。

 upcoming handshake states: client finished[20]
 upcoming handshake states: server change_cipher_spec[-1]
 upcoming handshake states: server finished[20]
 http-nio-8080-exec-15, WRITE: TLSv1.2 Change Cipher Spec, length = 1
 *** Finished verify_data:   27, 249, 167, 252, 151, 220, 110, 252, 113, 134, 248, 228 
 *** update handshake state: finished[20]
 upcoming handshake states: server change_cipher_spec[-1]
 upcoming handshake states: server finished[20]
 http-nio-8080-exec-15, WRITE: TLSv1.2 Handshake, length = 40
 http-nio-8080-exec-15, READ: TLSv1.2 Alert, length = 2
 http-nio-8080-exec-15, RECV TLSv1.2 ALERT:  fatal, handshake_failure
 %% Invalidated:  [Session-6, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
 http-nio-8080-exec-15, called closeSocket() http-nio-8080-exec-15,
 handling exception: javax.net.ssl.SSLHandshakeException: Received
 fatal alert: handshake_failure

'server change_cipher_spec' 步骤是我怀疑出现问题的地方 - 尽管不确定如何进一步调试。感谢任何指针。

【问题讨论】:

这里失效的是SSLSession,而不是密码套件。您正在尝试重新加入过期的会话。您可能需要查看对等日志以了解更多信息。 感谢您的指点。我现在正试图仔细查看 Client Hello 和 ServerHello 之间的日志。 dzone.com/articles/how-analyze-java-ssl-errors 基于 en.wikipedia.org/wiki/… ,我能够跟踪到步骤“ClientKeyExchange”。缺少“CertificateVerify”消息。 在握手过程中发现一个异常“无法解析的 CRLDistributionPoints 扩展”。不确定这是否是原因。我现在已经用这个细节更新了这个问题。 【参考方案1】:

问题终于解决了。

正如预期的那样,“无法解析的证书扩展”被证明是误报。

最后设置信任库和密钥库有助于解决问题。在 SSL 握手期间,客户端身份验证也需要密钥存储。

-Djavax.net.ssl.trustStore=C:\Users\cert\visatomcat.p12 -Djavax.net.ssl.trustStorePassword=pass123 -Djavax.net.ssl.trustStoreType=PKCS12 -Djavax.net.ssl.keyStore =C:\Users\cert\visatomcat.p12 -Djavax.net.ssl.keyStorePassword=pass123

【讨论】:

以上是关于Tomcat [9.0.26] - SSLHandshake 异常的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 9.0.26 高并发场景下DeadLock问题排查与修复

tomcat启动出现乱码

Springboot中tomcat问题

eclipse中tomcat无法正常启动求助

windows tomcat 怎么启动tomcat

使用 Tomcat 7 的 tomcat-maven-plugin - tomcat:deploy 有效,tomcat:undeploy 无效