Debian 9 Tomcat 9 让我们加密 SSL 配置
Debian 9 Tomcat 9 Let's Encrypt SSL config
这让我抓狂。
我已经创建了指向 PEM 文件的符号链接。我使 tomcat 用户可读 PEM 文件。我将 server.xml 设置为使用 SSL。并且连接器无法启动。
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200"
scheme="https"
secure="true"
SSLEnabled="true"
clientAuth="false"
sslProtocol="TLS"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
defaultSSLHostConfigName="mydomain.com"
>
<SSLHostConfig hostName="mydomain.com" protocols="+TLSv1,+TLSv1.1,+TLSv1.2">
<Certificate
certificateKeyFile="conf/privkey.pem"
certificateFile="conf/cert.pem"
certificateChainFile="conf/chain.pem"
type="UNDEFINED"
/>
</SSLHostConfig>
</Connector>
我确实尝试将类型更改为 RSA,但无济于事。我在日志中看到的是:
02-Jan-2021 17:40:54.398 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-openssl-nio-8443"]
02-Jan-2021 17:40:54.466 SEVERE [main] org.apache.catalina.util.LifecycleBase.handleSubClassException Failed to initialize component [Connector[HTTP/1.1-8443]]
org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1013)
... some lines removed
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)
Caused by: java.lang.IllegalArgumentException
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:99)
... some lines are removed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1010)
... 13 more
Caused by: java.io.IOException
at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:302)
at org.apache.tomcat.util.net.openssl.OpenSSLUtil.getKeyManagers(OpenSSLUtil.java:98)
at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:247)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:97)
... 20 more
我检查了 SSLUtilBase.java 代码 (tomcat 9.0.33):
if (certificate.getCertificateFile() == null) {
throw new IOException(sm.getString("jsse.noCertFile"));
}
我确实尝试复制文件而不是使用符号链接。徒劳无功。从证书文件中删除了注释。徒劳无功。似乎 tomcat 找不到我在 server.xml.
中指定的文件
我错过了什么?
我对 Ubuntu 20.04 和 Tomcat 9.0.52 也有同样的问题。
Tomcat - server.xml - certificateKeyFile
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
我也尝试了您上面描述的所有方法,但我也无法使带有 certificateKeyFile 的 Tomcat 连接器正常工作。
请注意,在 RedHat Linux 7/8 上它工作正常!!!我在 Ubuntu 20.04.
中才遇到这个问题
好消息是,如果您使用密钥库而不是 certificateKeyFile,它在 Ubuntu 20.04 中工作正常。
您需要以运行 tomcat 的用户身份创建密钥库,在我的例子中是名为“tomcat”的用户,然后使用密钥库创建 CSR,颁发证书,然后将证书导入密钥库。
--创建密钥库文件夹并授予适当的权限:
su - root
mkdir /rhdata/sslcert
chown -R tomcat:tomcat /rhdata/sslcert
su - tomcat
cd /rhdata/sslcert
--创建PKCS12密钥库(必须做上一步):
su - tomcat
/usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keystore /rhdata/sslcert/.keystore
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -validity 3600 -keysize 2048 -keystore /rhdata/sslcert/.keystore
Enter keystore password: key$tom@2021
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool --list --keystore /rhdata/sslcert/.keystore -storepass 'key$tom@2021'
--创建CSR:
su - tomcat
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -certreq -keyalg RSA -alias tomcat -file /rhdata/sslcert/keytool_cert/certreq.csr -keystore /rhdata/sslcert/.keystore -storepass 'key$tom@2021'
--使用 CSR
从证书颁发机构创建新证书
--将新证书导入密钥库:
su - tomcat
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -import -alias tomcat -keystore /rhdata/sslcert/.keystore -storepass 'key$tom@2021' -file /rhdata/sslcert/keytool_cert/certnew.p7b
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -import -alias tomcat -keystore /rhdata/sslcert/.keystore -storepass 'key$tom@2021' -file /rhdata/sslcert/keytool_cert/certnew.cer
--这是新的 Tomcat 连接器:
Tomcat - server.xml - keystore
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="/rhdata/sslcert/.keystore" keystorePass="key$tom@2021"
clientAuth="false" sslProtocol="TLS"/>
--验证新的Tomcatserver.xml文件
su - tomcat
cd /usr/local/tomcat9/conf
/usr/local/tomcat9/bin/configtest.sh
--那么,stop/start Tomcat.
su - root
systemctl stop tomcat.service
systemctl start tomcat.service
systemctl status tomcat.service
vi /usr/local/tomcat9/logs/catalina.out <-- shall not have any errors!!!
每当您在连接器上使用 deprecated properties 之一时,Tomcat 会创建一个 <SSLHostConfig>
元素,其中包含 hostName="_default_"
和一个 <Connector>
元素。该错误是由于此特定元素上缺少 certificateFile
引起的。
从 <Connector>
元素中删除已弃用的属性(clientAuth
、sslProtocol
),一切都应该有效。
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
defaultSSLHostConfigName="mydomain.com">
<SSLHostConfig hostName="mydomain.com" protocols="TLSv1+TLSv1.1+TLSv1.2">
<Certificate
certificateKeyFile="conf/privkey.pem"
certificateFile="conf/cert.pem"
certificateChainFile="conf/chain.pem"
type="UNDEFINED"
/>
</SSLHostConfig>
</Connector>
备注:sslProtocol
属性是 JSSE 的特性,应始终保留默认值 (TLS
)。
这让我抓狂。
我已经创建了指向 PEM 文件的符号链接。我使 tomcat 用户可读 PEM 文件。我将 server.xml 设置为使用 SSL。并且连接器无法启动。
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200"
scheme="https"
secure="true"
SSLEnabled="true"
clientAuth="false"
sslProtocol="TLS"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
defaultSSLHostConfigName="mydomain.com"
>
<SSLHostConfig hostName="mydomain.com" protocols="+TLSv1,+TLSv1.1,+TLSv1.2">
<Certificate
certificateKeyFile="conf/privkey.pem"
certificateFile="conf/cert.pem"
certificateChainFile="conf/chain.pem"
type="UNDEFINED"
/>
</SSLHostConfig>
</Connector>
我确实尝试将类型更改为 RSA,但无济于事。我在日志中看到的是:
02-Jan-2021 17:40:54.398 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-openssl-nio-8443"]
02-Jan-2021 17:40:54.466 SEVERE [main] org.apache.catalina.util.LifecycleBase.handleSubClassException Failed to initialize component [Connector[HTTP/1.1-8443]]
org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1013)
... some lines removed
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)
Caused by: java.lang.IllegalArgumentException
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:99)
... some lines are removed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1010)
... 13 more
Caused by: java.io.IOException
at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:302)
at org.apache.tomcat.util.net.openssl.OpenSSLUtil.getKeyManagers(OpenSSLUtil.java:98)
at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:247)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:97)
... 20 more
我检查了 SSLUtilBase.java 代码 (tomcat 9.0.33):
if (certificate.getCertificateFile() == null) {
throw new IOException(sm.getString("jsse.noCertFile"));
}
我确实尝试复制文件而不是使用符号链接。徒劳无功。从证书文件中删除了注释。徒劳无功。似乎 tomcat 找不到我在 server.xml.
中指定的文件我错过了什么?
我对 Ubuntu 20.04 和 Tomcat 9.0.52 也有同样的问题。
Tomcat - server.xml - certificateKeyFile
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
我也尝试了您上面描述的所有方法,但我也无法使带有 certificateKeyFile 的 Tomcat 连接器正常工作。
请注意,在 RedHat Linux 7/8 上它工作正常!!!我在 Ubuntu 20.04.
中才遇到这个问题好消息是,如果您使用密钥库而不是 certificateKeyFile,它在 Ubuntu 20.04 中工作正常。
您需要以运行 tomcat 的用户身份创建密钥库,在我的例子中是名为“tomcat”的用户,然后使用密钥库创建 CSR,颁发证书,然后将证书导入密钥库。
--创建密钥库文件夹并授予适当的权限:
su - root
mkdir /rhdata/sslcert
chown -R tomcat:tomcat /rhdata/sslcert
su - tomcat
cd /rhdata/sslcert
--创建PKCS12密钥库(必须做上一步):
su - tomcat
/usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keystore /rhdata/sslcert/.keystore
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -validity 3600 -keysize 2048 -keystore /rhdata/sslcert/.keystore
Enter keystore password: key$tom@2021
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool --list --keystore /rhdata/sslcert/.keystore -storepass 'key$tom@2021'
--创建CSR:
su - tomcat
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -certreq -keyalg RSA -alias tomcat -file /rhdata/sslcert/keytool_cert/certreq.csr -keystore /rhdata/sslcert/.keystore -storepass 'key$tom@2021'
--使用 CSR
从证书颁发机构创建新证书--将新证书导入密钥库:
su - tomcat
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -import -alias tomcat -keystore /rhdata/sslcert/.keystore -storepass 'key$tom@2021' -file /rhdata/sslcert/keytool_cert/certnew.p7b
$ /usr/lib/jvm/java-11-openjdk-amd64/bin/keytool -import -alias tomcat -keystore /rhdata/sslcert/.keystore -storepass 'key$tom@2021' -file /rhdata/sslcert/keytool_cert/certnew.cer
--这是新的 Tomcat 连接器:
Tomcat - server.xml - keystore
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="/rhdata/sslcert/.keystore" keystorePass="key$tom@2021"
clientAuth="false" sslProtocol="TLS"/>
--验证新的Tomcatserver.xml文件
su - tomcat
cd /usr/local/tomcat9/conf
/usr/local/tomcat9/bin/configtest.sh
--那么,stop/start Tomcat.
su - root
systemctl stop tomcat.service
systemctl start tomcat.service
systemctl status tomcat.service
vi /usr/local/tomcat9/logs/catalina.out <-- shall not have any errors!!!
每当您在连接器上使用 deprecated properties 之一时,Tomcat 会创建一个 <SSLHostConfig>
元素,其中包含 hostName="_default_"
和一个 <Connector>
元素。该错误是由于此特定元素上缺少 certificateFile
引起的。
从 <Connector>
元素中删除已弃用的属性(clientAuth
、sslProtocol
),一切都应该有效。
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
defaultSSLHostConfigName="mydomain.com">
<SSLHostConfig hostName="mydomain.com" protocols="TLSv1+TLSv1.1+TLSv1.2">
<Certificate
certificateKeyFile="conf/privkey.pem"
certificateFile="conf/cert.pem"
certificateChainFile="conf/chain.pem"
type="UNDEFINED"
/>
</SSLHostConfig>
</Connector>
备注:sslProtocol
属性是 JSSE 的特性,应始终保留默认值 (TLS
)。