gpt4 book ai didi

spring-boot - 尝试从 Docker 访问 ES 实例时出现 SSLHandshakeException

转载 作者:太空宇宙 更新时间:2023-11-03 14:26:35 25 4
gpt4 key购买 nike

我正在尝试使用高级 REST 客户端 6.7.2 访问 6.x ES 实例。通过主机名 (https://****.azureedge.net)、用户名和密码向我提供对此 ES 实例的访问权限。

当我的 Spring Boot 应用程序从我的开发环境 (IDE) 运行时,它从同一个 ES 获取数据没有问题,但是当我尝试从 Docker 容器(从我的开发机器或云中的 K8s 集群)运行它时抛出 SSLHandshakeException ).

容器是用基础镜像制作的:FROM debian:stretch-slim & OpenJDK 11.0.2 和 Spring Boot 必要的模块。

我在使用 -Djavax.net.debug=all 进行调试时取得了一些进展。事实证明,在 docker 镜像中运行时,通常的 SSL 握手只发生了几个第一步:

Produced ClientHello handshake message
WRITE: TLS13 handshake, length = 2352
Raw write
Raw read (0000: 15 03 03 00 02 02 28 ......( )
READ: TLSv1.2 alert, length = 2
Received alert message (
"Alert": {
"level" : "fatal",
"description": "handshake_failure"
}
)

接着是 SSLHandshakeException:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at org.elasticsearch.client.RestClient$SyncResponseListener.get(RestClient.java:938)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:227)
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1764)
at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1749)
at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:1708)
at org.elasticsearch.client.SecurityClient.getSslCertificates(SecurityClient.java:508)
....
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source)
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Unknown Source)
at java.base/sun.security.ssl.TransportContext.dispatch(Unknown Source)
at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
at java.base/sun.security.ssl.SSLEngineImpl.decode(Unknown Source)
at java.base/sun.security.ssl.SSLEngineImpl.readRecord(Unknown Source)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source)
at java.base/javax.net.ssl.SSLEngine.unwrap(Unknown Source)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doUnwrap(SSLIOSession.java:271)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:316)
at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:509)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:120)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591)

从本地环境运行时,握手看起来没有中断:

Produced ClientHello handshake message
WRITE: TLS13 handshake, length = 460
Raw write
Raw read
READ: TLSv1.2 handshake, length = 155
Consuming ServerHello
ServerHello
Negotiated protocol version: TLSv1.3
Session initialized: Session(1560119025211|TLS_AES_256_GCM_SHA384)
WRITE: TLS13 change_cipher_spec, length = 1
Raw write
Raw read
READ: TLSv1.2 change_cipher_spec, length = 1
Consuming ChangeCipherSpec message
Raw read
READ: TLSv1.2 application_data, length = 27
...
Raw read
READ: TLSv1.2 application_data, length = 8469
Consuming server Certificate handshake message
... // here is the list of 3 certificates with "SHA256withRSA", "SHA256withRSA", "SHA1withRSA" signature algorithms
Found trusted certificate ⇢ SHA1withRSA
...

在本地运行时,我注意到 CN=Microsoft IT TLS CA 2、OU=Microsoft IT、O=Microsoft Corporation、L=Redmond、ST=Washington、C=US,以及 CN=Baltimore Cyber​​Trust Root, OU=Cyber​​Trust, O=Baltimore, C=IE 作为发行者,也许这很重要,但考虑到 ES 主机地址 (Azure),我想这是意料之中的。

最后我想强调的是,我不需要做任何特别的事情就可以在我的 ma​​cOS Java 11.0.2 开发环境中完成这项工作。

我已经尝试过跟随,但这并没有改变任何东西:

  • 将基础 Docker 镜像从“slim”版本更改为非 slim 版本
  • 使用 OpenJDK 11.0.1 或 11.0.2
  • 将来自主机的证书添加到 JVM 在运行时使用的 TrustStore。 (我在 Docker 容器中检查确实还有一个证书,但考虑到何时发生握手失败,我想这无关紧要)
  • 尝试使用以下命令强制应用程序:“-Dcom.sun.net.ssl.enableECC=false”、“-Djdk.tls.client.protocols=TLSv1.3”、“-Dhttps.protocols=TLSv1.3”、没有帮助

有趣:从带有 BasicAuth 的 Docker 图像中 curl “与”相同的 URL 没有问题(握手完成)& 小查询返回结果。我猜 curl 和 JVM 在 Docker 中使用不同来源的可信 CA,不同的握手算法等。

在此先感谢您的帮助

最佳答案

TLDR:在应用程序中为客户端强制执行 TLSv1.2 使握手从 docker 内部完成

经过多次尝试/失败尝试后,我成功了。以下事情没有任何区别:

  • 使用非“slim”的 debian 基础镜像代替“slim”
  • 使用 OpenJDK 11.0.2 而不是 11.0.1
  • 在构建 docker 镜像时将主机的证书添加到 JVM TrustedStore,以便在容器启动时可用。
  • 强制 com.sun.net.ssl.enableECC=false
  • https.protocols 和/或 jdk.tls.client.protocols 强制执行 TLSv1.3
  • https.protocols 强制执行 TLSv1.2

修复与主机的握手,是通过在 Dockerfile 中使用 -Djdk.tls.client.protocols=TLSv1.2 为客户端强制执行 TLSv1.2,因此应用程序运行在容器内带有此标志。这允许 SSL 握手完成,因为它无论如何都应该工作。由于某种原因,如果不为客户端强制执行较低版本的协议(protocol),有关协议(protocol)版本的实际协商将无法进行。来自本地与 docker 环境的日志没有显示任何差异,但这对 docker 有帮助。

帮助我发现的是:

  • 设置 javax.net.debug=ssl:handshake 或更详细的 javax.net.debug=all 这样我就可以看到握手尝试的详细信息
  • 确认“至少有人”可以通过使用 curl 发送与应用正在尝试的请求相同的请求,从 docker 内部建立出站通信,这是有效的,因为 curl 以某种方式弄清楚了如何继续与主机握手。
  • 纯属幸运

感谢大家的支持和想法

关于spring-boot - 尝试从 Docker 访问 ES 实例时出现 SSLHandshakeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56523042/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com