为什么Spring Boot应用程序和Consul之间的SSL连接在几分钟后就失效了?

问题描述 投票:6回答:1

我正在使用新版本的Ubuntu、Consul和Spring Boot升级环境。乍一看,一切似乎都很正常。应用程序连接到Consul,请求其配置并启动。然而,几分钟后,有些东西坏了,大约每隔2秒就会重复出现这条消息。

com.ecwid.consul.transport.TransportException: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
    at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:77)
    at com.ecwid.consul.transport.AbstractHttpTransport.makeGetRequest(AbstractHttpTransport.java:34)
    at com.ecwid.consul.v1.ConsulRawClient.makeGetRequest(ConsulRawClient.java:128)
    at com.ecwid.consul.v1.catalog.CatalogConsulClient.getCatalogServices(CatalogConsulClient.java:120)
    at com.ecwid.consul.v1.ConsulClient.getCatalogServices(ConsulClient.java:372)
    at org.springframework.cloud.consul.discovery.ConsulCatalogWatch.catalogServicesWatch(ConsulCatalogWatch.java:129)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
    at java.base/sun.security.ssl.SSLSocketImpl.handleEOF(SSLSocketImpl.java:1313)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1055)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:395)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)

我发现每隔两秒就会出现一条信息 是由于应用程序的健康检查造成的。一旦第一次出现错误,以后每次健康检查都会继续出现。通过关闭健康检查并重新启动来确认这一点。这就导致了错误的发生,当达到Consul-data的TTL时,正好发生一次。

我对这个问题的理解到此为止。我试着去追踪它的几个原因,但都没有找到解决办法。

  • 检查证书 - 所使用的证书由Vault生成,由中间证书签署,由自签的根证书签署。然后将这些证书与密钥一起放在pkcs12捆绑包中,并提供给应用程序。这适用于所有的TLS连接,也适用于CLI工具和以下情况 curl. 这似乎是一个死胡同。
  • 网络连接 - 由于连接被重置,我试着看是由于防火墙或安全组的问题。然而,相关端口(8501)对TCP和UDP流量都是开放的,所有手动测试与 nc 显示端口可以到达。
  • IPv6错误 - 在某个地方,我发现了一个帖子,说这可能是由于IPv6的一个错误。我试着把机器上的IPv6关闭,重启一切,然后再试。没有成功,还是同样的错误。
  • Consul的版本 - 我试着在我们的旧环境中运行应用程序,其中Consul 1.2.3正在运行,那里的错误没有出现。我仍在尝试找出是否有一个特定的Consul版本开始出现这个问题,但还没有找到。
  • TLS错误 - 在Consul 1.2.3和1.7.2之间,Consul的TLS支持和底层的Go TLS实现都有一些变化。在Consul 1.4.0的测试中发现了这个问题,它提供了一个稍微不同的TLS错误。互联网上的一些建议是,Go和OpenJDK之间存在冲突的实现。我试着强迫Java应用程序使用TLS 1.2,但同样没有成功。
  • 握手调试 - 根据评论中的提示,我使用了 -Djavax.net.debug=ssl:handshake 以了解握手过程中发生了什么。在最初的几分钟里,产生的额外输出在我看来是正常的握手。一旦出现问题,握手的输出就在 "产生的客户端Hello消息 "之后停止,并显示 "远程主机终止了握手"。我还没能对这个连接的另一边进行同样的操作。Consul是一个Golang应用程序。如果有谁知道如何为Golang应用程序获取同样的调试信息,请告知。

我希望有人知道如何找到这个问题的原因,或者更好的是,有一个解决方案。

java spring-boot tls1.2 consul spring-cloud-consul
1个回答
4
投票

经过一些更多的挖掘和尝试其他版本的东西。我发现,使用GraalVM会产生一个不同的,但稍微更有描述性的错误。当试图连接到Consul-应用程序时,它立即用这个消息终止。

Caused by: javax.net.ssl.SSLHandshakeException: extension (5) should not be presented in certificate_request
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:307)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:254)
    at java.base/sun.security.ssl.SSLExtensions.<init>(SSLExtensions.java:90)
    at java.base/sun.security.ssl.CertificateRequest$T13CertificateRequestMessage.<init>(CertificateRequest.java:818)
    at java.base/sun.security.ssl.CertificateRequest$T13CertificateRequestConsumer.consume(CertificateRequest.java:922)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:177)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1151)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1062)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:71)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:220)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:164)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:139)
    at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:61)

这让我在Golang GitHub页面上找到了一个问题。https:/github.comgolanggoissues35722。. 它详细介绍了来自不同人的类似问题,但不断有稍微不同的细节。在那个帖子中,提到了Go和Java之间TLS 1.3实现的差异。OpenJDK的维护者也提到了这个问题。https:/bugs.openjdk.java.netbrowseJDK-8236039.

它已经被修复和关闭,但还没有在我的任何常规二进制发行版中使用。我将尝试检查该版本是否真的修复了这个问题。不过,有一个变通的办法,就是在Java中禁用TLS1.2。你可以通过添加 -Djdk.tls.client.protocols=TLSv1.2 到启动参数。

© www.soinside.com 2019 - 2024. All rights reserved.