TL;DR:我们如何配置在Windows上运行的Java 8的Tomcat以支持TLSv1.3和HTTP/2的两种协议?
我们的一个应用程序在Windows上使用Java 8上的Tomcat 9.0运行。使用HTTP/1.1和TLSv1.2,设置对我们来说很好用,但现在我们想同时使用HTTP/2和TLSv1.3。我们能够使HTTP/2或TLSv1.3工作,但不能同时使用两者。
我们能够通过配置Tomcat使用Azul的Zulu Java 8版本来让TLSv1.3工作。使用此配置,Tomcat通过JSSE使用TLS。然而,当我们尝试添加对HTTP/2的支持时,遇到了问题。根据Tomcat文档,
“由于Java 8的TLS实现不支持ALPN(这是HTTP/2 over TLS所需的),因此您必须使用基于OpenSSL的TLS实现来启用HTTP/2支持。”
注意:我们不确定我们正在使用的Zulu版本的Java 8是否缺少ALPN。
当我们切换到基于OpenSSL的TLS时,我们能够使HTTP/2工作,但我们无法弄清如何使TLSv1.3工作。我们安装了OpenSSL和APR二进制文件,但当我们尝试仅配置TLSv1.3(而不是TLSv1.2+TLSv1.3)运行时,我们在Tomcat日志中看到以下错误:
以下是我们尝试过的服务器配置文件server.xml的不同变体。
工作的HTTP/2配置(不包括TLSv1.3):
可工作的TLSv1.3配置(不包括HTTP/2):
不工作的HTTP/2和TLSv1.3配置:
当我们深入研究Tomcat代码时,我们发现:
当我们检查我们的OpenSSL版本(仅为该机器配置的OpenSSL)时,我们看到:
基于此,我们不明白为什么我们的 OpenSSL 配置不支持 TLSv1.3。
“编辑:我们尝试了另一种配置来使用APR(即没有JSSE),但也没有成功。以下是详细信息。
未能工作的HTTP/2和TLSv1.3通过APR配置:”
导致的错误日志(与之前略有不同的堆栈跟踪):
启动时带有APR配置的Tomcat日志
我们的一个应用程序在Windows上使用Java 8上的Tomcat 9.0运行。使用HTTP/1.1和TLSv1.2,设置对我们来说很好用,但现在我们想同时使用HTTP/2和TLSv1.3。我们能够使HTTP/2或TLSv1.3工作,但不能同时使用两者。
我们能够通过配置Tomcat使用Azul的Zulu Java 8版本来让TLSv1.3工作。使用此配置,Tomcat通过JSSE使用TLS。然而,当我们尝试添加对HTTP/2的支持时,遇到了问题。根据Tomcat文档,
“由于Java 8的TLS实现不支持ALPN(这是HTTP/2 over TLS所需的),因此您必须使用基于OpenSSL的TLS实现来启用HTTP/2支持。”
注意:我们不确定我们正在使用的Zulu版本的Java 8是否缺少ALPN。
当我们切换到基于OpenSSL的TLS时,我们能够使HTTP/2工作,但我们无法弄清如何使TLSv1.3工作。我们安装了OpenSSL和APR二进制文件,但当我们尝试仅配置TLSv1.3(而不是TLSv1.2+TLSv1.3)运行时,我们在Tomcat日志中看到以下错误:
org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:935)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:530)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:852)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
at org.apache.catalina.startup.Catalina.load(Catalina.java:656)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:306)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:491)
Caused by: java.lang.IllegalArgumentException: None of the [protocols] specified are supported by the SSL engine : [[TLSv1.3]]
at org.apache.tomcat.util.net.SSLUtilBase.getEnabled(SSLUtilBase.java:91)
at org.apache.tomcat.util.net.SSLUtilBase.<init>(SSLUtilBase.java:55)
at org.apache.tomcat.util.net.openssl.OpenSSLUtil.<init>(OpenSSLUtil.java:41)
at org.apache.tomcat.util.net.openssl.OpenSSLImplementation.getSSLUtil(OpenSSLImplementation.java:36)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:102)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:85)
at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:216)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1043)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:540)
at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:932)
... 13 more
以下是我们尝试过的服务器配置文件server.xml的不同变体。
工作的HTTP/2配置(不包括TLSv1.3):
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig truststoreFile="conf/truststore.jks"
protocols="TLSv1.2+TLSv1.3"
truststorePassword="changeit"
truststoreType="JKS"
certificateVerification="optional">
<Certificate certificateKeystoreFile="conf/keystore.jks" type="RSA"/>
</SSLHostConfig>
</Connector>
可工作的TLSv1.3配置(不包括HTTP/2):
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig truststoreFile="conf/truststore.jks"
protocols="TLSv1.3"
truststorePassword="changeit"
truststoreType="JKS"
certificateVerification="optional">
<Certificate certificateKeystoreFile="conf/keystore.jks" type="RSA"/>
</SSLHostConfig>
</Connector>
不工作的HTTP/2和TLSv1.3配置:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig truststoreFile="conf/truststore.jks"
protocols="TLSv1.3"
truststorePassword="changeit"
truststoreType="JKS"
certificateVerification="optional">
<Certificate certificateKeystoreFile="conf/keystore.jks" type="RSA"/>
</SSLHostConfig>
</Connector>
当我们深入研究Tomcat代码时,我们发现:
if (SSL.version() >= 0x1010100f) {
SSL_PROTOCOL_ALL = (SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2 |
SSL_PROTOCOL_TLSV1_3);
} else {
SSL_PROTOCOL_ALL = (SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2);
}
当我们检查我们的OpenSSL版本(仅为该机器配置的OpenSSL)时,我们看到:
C:\>openssl version
OpenSSL 1.1.1g 21 Apr 2020
基于此,我们不明白为什么我们的 OpenSSL 配置不支持 TLSv1.3。
“编辑:我们尝试了另一种配置来使用APR(即没有JSSE),但也没有成功。以下是详细信息。
未能工作的HTTP/2和TLSv1.3通过APR配置:”
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" scheme="https" secure="true" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig protocols="TLSv1.3">
<Certificate certificateKeyFile="conf/privkey"
certificateFile="conf/ssl.cer"
certificateChainFile="conf/certchain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
导致的错误日志(与之前略有不同的堆栈跟踪):
org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:935)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:530)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:852)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
at org.apache.catalina.startup.Catalina.load(Catalina.java:656)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:306)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:491)
Caused by: java.lang.IllegalArgumentException: None of the [protocols] specified are supported by the SSL engine : [[TLSv1.3]]
at org.apache.tomcat.util.net.SSLUtilBase.getEnabled(SSLUtilBase.java:91)
at org.apache.tomcat.util.net.AprEndpoint.createSSLContext(AprEndpoint.java:405)
at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:376)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1043)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:540)
at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:932)
... 13 more
启动时带有APR配置的Tomcat日志
01-Aug-2020 04:34:59.459 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version: Apache Tomcat/9.0.7
01-Aug-2020 04:34:59.484 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Apr 3 2018 19:53:05 UTC
01-Aug-2020 04:34:59.484 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server number: 9.0.7.0
01-Aug-2020 04:34:59.484 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Windows Server 2016
01-Aug-2020 04:34:59.487 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 10.0
01-Aug-2020 04:34:59.487 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
01-Aug-2020 04:34:59.487 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: C:\Program Files\Java\JDK_Zulu8_262\jre
01-Aug-2020 04:34:59.487 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 1.8.0_262-b19
01-Aug-2020 04:34:59.487 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Azul Systems, Inc.
01-Aug-2020 04:34:59.487 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: C:\Program Files\Apache Software Foundation\Tomcat 9.0
01-Aug-2020 04:34:59.487 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: C:\Program Files\Apache Software Foundation\Tomcat 9.0
01-Aug-2020 04:34:59.488 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=C:\Program Files\Apache Software Foundation\Tomcat 9.0
01-Aug-2020 04:34:59.488 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=C:\Program Files\Apache Software Foundation\Tomcat 9.0
01-Aug-2020 04:34:59.488 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=C:\Program Files\Apache Software Foundation\Tomcat 9.0\temp
01-Aug-2020 04:34:59.488 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
01-Aug-2020 04:34:59.488 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=C:\Program Files\Apache Software Foundation\Tomcat 9.0\conf\logging.properties
01-Aug-2020 04:34:59.488 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: exit
01-Aug-2020 04:34:59.488 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: abort
01-Aug-2020 04:34:59.489 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xms128m
01-Aug-2020 04:34:59.489 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx256m
01-Aug-2020 04:34:59.489 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded APR based Apache Tomcat Native library [1.2.24] using APR version [1.7.0].
01-Aug-2020 04:34:59.489 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
01-Aug-2020 04:34:59.489 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
01-Aug-2020 04:34:59.517 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.1.1g 21 Apr 2020]
01-Aug-2020 04:35:00.410 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
01-Aug-2020 04:35:00.523 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read
01-Aug-2020 04:35:00.536 INFO [main] org.apache.coyote.http11.AbstractHttp11Protocol.configureUpgradeProtocol The ["https-openssl-apr-8443"] connector has been configured to support negotiation to [h2] via ALPN
01-Aug-2020 04:35:00.536 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-openssl-apr-8443"]
01-Aug-2020 04:35:00.633 SEVERE [main] org.apache.catalina.util.LifecycleBase.handleSubClassException Failed to initialize component [Connector[org.apache.coyote.http11.Http11AprProtocol-8443]]
org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:935)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:530)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:852)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
at org.apache.catalina.startup.Catalina.load(Catalina.java:656)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:306)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:491)
Caused by: java.lang.IllegalArgumentException: None of the [protocols] specified are supported by the SSL engine : [[TLSv1.3]]
at org.apache.tomcat.util.net.SSLUtilBase.getEnabled(SSLUtilBase.java:91)
at org.apache.tomcat.util.net.AprEndpoint.createSSLContext(AprEndpoint.java:405)
at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:376)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1043)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:540)
at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:932)
... 13 more
01-Aug-2020 04:35:00.635 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"]
01-Aug-2020 04:35:00.638 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read
01-Aug-2020 04:35:00.638 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 3485 ms
01-Aug-2020 04:35:00.706 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
01-Aug-2020 04:35:00.706 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/9.0.7
libtcnative
静态链接了libapr
和libssl
(OpenSSL)。在启动时,Tomcat应该会提供一系列版本信息。它对于有效的APR和OpenSSL版本有什么说法? - undefined