Java 8 使用Zulu jdk 11从Alpine Linux映像调用GRPC服务时出现SSL连接问题

Java 8 使用Zulu jdk 11从Alpine Linux映像调用GRPC服务时出现SSL连接问题,java-8,netty,java-11,sslhandshakeexception,azul-zulu,Java 8,Netty,Java 11,Sslhandshakeexception,Azul Zulu,我有一个spring boot应用程序,它使用Netty调用GRPC服务。当我在本地机器上运行代码时(MacOS和zulu jdk没有JCE),我能够连接到GRPC服务 注意:我们使用的是Oracle JDK 1.8编译的GRPC客户端jar 当我构建一个docker映像(带zulu jdk的Alpine Linux,不带JCE)时,我得到以下错误 javax.net.ssl|ERROR|37|C7-services-1|2019-09-26 21:18:10.622 GMT|Trans

我有一个spring boot应用程序,它使用Netty调用GRPC服务。当我在本地机器上运行代码时(MacOS和zulu jdk没有JCE),我能够连接到GRPC服务

注意:我们使用的是Oracle JDK 1.8编译的GRPC客户端jar

当我构建一个docker映像(带zulu jdk的Alpine Linux,不带JCE)时,我得到以下错误

    javax.net.ssl|ERROR|37|C7-services-1|2019-09-26 21:18:10.622 GMT|TransportContext.java:312|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking (
"throwable" : {
  javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
    at java.base/sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:169)
    at java.base/sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:98)
    at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:216)
    at java.base/sun.security.ssl.SSLEngineImpl.beginHandshake(SSLEngineImpl.java:103)
    at io.netty.handler.ssl.JdkSslEngine.beginHandshake(JdkSslEngine.java:155)
    at io.netty.handler.ssl.SslHandler.handshake(SslHandler.java:1967)
    at io.netty.handler.ssl.SslHandler.startHandshakeProcessing(SslHandler.java:1886)
    at io.netty.handler.ssl.SslHandler.channelActive(SslHandler.java:2021)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:225)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:211)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:204)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1396)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:225)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:211)
    at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:906)
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:311)
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:341)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:670)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:617)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:534)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at java.base/java.lang.Thread.run(Thread.java:834)}

)
在图像中我看到的很少

*   TLS_AES_128_GCM_SHA256
*   TLS_AES_256_GCM_SHA384
*   TLS_DHE_DSS_WITH_AES_128_CBC_SHA
*   TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
*   TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
*   TLS_DHE_DSS_WITH_AES_256_CBC_SHA
*   TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
*   TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
*   TLS_DHE_RSA_WITH_AES_128_CBC_SHA
*   TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
*   TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
*   TLS_DHE_RSA_WITH_AES_256_CBC_SHA
*   TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
*   TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
*   TLS_EMPTY_RENEGOTIATION_INFO_SCSV
*   TLS_RSA_WITH_AES_128_CBC_SHA
*   TLS_RSA_WITH_AES_128_CBC_SHA256
*   TLS_RSA_WITH_AES_128_GCM_SHA256
*   TLS_RSA_WITH_AES_256_CBC_SHA
*   TLS_RSA_WITH_AES_256_CBC_SHA256
*   TLS_RSA_WITH_AES_256_GCM_SHA384
注意:顺便说一句,在我的本地电脑上,它选择了TLS\u ECDH\u ECDSA\u和\u AES\u 128\u GCM\u SHA256

我将java版本降级为OracleJDK1.8,并使用JDK1.8构建映像。现在我可以通过SSL握手解决这个问题,因为我可以看到映像中现在可用的所有密码。然而,我最终遇到了一个非常棘手的问题

Caused by: java.lang.IllegalStateException: Could not find TLS ALPN provider; no working netty-tcnative, Conscrypt, or Jetty NPN/ALPN available
    at io.grpc.netty.GrpcSslContexts.defaultSslProvider(GrpcSslContexts.java:258) ~[grpc-netty-1.16.1.jar:1.16.1]
    at io.grpc.netty.GrpcSslContexts.configure(GrpcSslContexts.java:171) ~[grpc-netty-1.16.1.jar:1.16.1]
    at io.grpc.netty.GrpcSslContexts.forClient(GrpcSslContexts.java:120) ~[grpc-netty-1.16.1.jar:1.16.1]
    at com.samsclub.list.core.client.C7ProductCatalogProvider.createChannel(C7ProductCatalogProvider.java:104) ~[sams-list-core-0.0.10-SNAPSHOT.jar:0.0.10-SNAPSHOT]
    at com.samsclub.list.core.client.C7ProductCatalogProvider.init(C7ProductCatalogProvider.java:59) ~[sams-list-core-0.0.10-SNAPSHOT.jar:0.0.10-SNAPSHOT]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_212]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_212]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_212]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_212]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMet
看到这个了吗

我真的很想上祖鲁11号,想打电话给这个GRPC服务。我们应该用JDK11编译GRPC客户机jar吗

我的Docker Alpine图像配置

/app # cat /etc/os-release 
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.10.0
PRETTY_NAME="Alpine Linux v3.10"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
/app # java -version
openjdk version "11.0.4" 2019-07-16 LTS
OpenJDK Runtime Environment Zulu11.33+15-CA (build 11.0.4+11-LTS)
OpenJDK 64-Bit Server VM Zulu11.33+15-CA (build 11.0.4+11-LTS, mixed mode)

你说没有JCE的祖鲁jdk是什么意思

zulu jdk提供了所有必需的加密库和提供程序。如果手动排除某些提供程序或库,则会丢失相应的功能


例如,SunEC crypto provider负责ECDSA和ECDH算法的实现。将SunEC从提供程序列表中排除或禁用/删除jdk.crypto.ec模块,您将错过所有TLS_ECDH_ECDSA_*TLS_ECDHE_ECDSA_*cipher套件。这可能是TLS握手失败的原因。

使用Zulu 11 jdk清理alpine docker映像显示以下内容:

$ docker run alpn_zulu more /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.10.2
PRETTY_NAME="Alpine Linux v3.10"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
$ docker run alpn_zulu java -version
openjdk version "11.0.4" 2019-07-16 LTS
OpenJDK Runtime Environment Zulu11.33+15-CA (build 11.0.4+11-LTS)
OpenJDK 64-Bit Server VM Zulu11.33+15-CA (build 11.0.4+11-LTS, mixed mode)
$ docker run alpn_zulu jrunscript -e "java.util.Arrays.asList(javax.net.ssl.SSLServerSocketFactory.getDefault().getSupportedCipherSuites()).stream().forEach(println)"
Warning: Nashorn engine is planned to be removed from a future JDK release
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
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_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_EMPTY_RENEGOTIATION_INFO_SCSV

JCE(Java加密扩展)默认情况下不会随任何jdk下载一起提供。你需要单独下载。我没有手动删除任何内容。B我们将删除模块的位置“jdk.crypto.ec module”更新了我的问题,使linux和java配置从docker映像中删除。您是否可以运行“jrunscript-e”java.util.Arrays.asList(javax.net.ssl.SSLServerSocketFactory.getDefault().getSupportedCipherSuites()).stream().forEach(println)”和“jrunscript-e”java.util.Arrays.asList(javax.net.ssl.SSLServerSocketFactory.getDefault().getSupportedCipherSuite()).stream().forEach(println)“”命令在alpine映像和本地计算机上(使用zulu11)并进行比较。如果不同,则在java.security文件中有不同的安全配置
$ docker run alpn_zulu more /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.10.2
PRETTY_NAME="Alpine Linux v3.10"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
$ docker run alpn_zulu java -version
openjdk version "11.0.4" 2019-07-16 LTS
OpenJDK Runtime Environment Zulu11.33+15-CA (build 11.0.4+11-LTS)
OpenJDK 64-Bit Server VM Zulu11.33+15-CA (build 11.0.4+11-LTS, mixed mode)
$ docker run alpn_zulu jrunscript -e "java.util.Arrays.asList(javax.net.ssl.SSLServerSocketFactory.getDefault().getSupportedCipherSuites()).stream().forEach(println)"
Warning: Nashorn engine is planned to be removed from a future JDK release
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
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_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_EMPTY_RENEGOTIATION_INFO_SCSV