【问题标题】:Debian 9 Tomcat 9 Let's Encrypt SSL configDebian 9 Tomcat 9 让我们加密 SSL 配置
【发布时间】:2021-01-02 17:57:03
【问题描述】:

现在让我发疯了。

我已经创建了指向 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"));
            }

我确实尝试复制文件而不是使用符号链接。徒劳无功。从证书文件中删除了 cmets。徒劳无功。 tomcat 好像找不到我在 server.xml 中指定的文件。

我错过了什么?

【问题讨论】:

  • 可能使用已弃用的clientAuth="false" 属性(参见documentation)会导致自动创建&lt;SSLHostConfig hostName="_default_"&gt; 元素。错误指的是这个元素,而不是你配置的那个。
  • @PiotrP.Karwasz 确实,我已经删除了它(以及接下来的两行)以及“type=UNDEFINED”,现在它可以工作了。

标签: ssl tomcat pem


【解决方案1】:

每当您在连接器上使用deprecated properties 之一时,Tomcat 都会创建一个&lt;SSLHostConfig&gt; 元素,其中包含hostName="_default_"&lt;Connector&gt; 元素。该错误是由于此特定元素上缺少 certificateFile 引起的。

&lt;Connector&gt; 元素中删除不推荐使用的属性(clientAuthsslProtocol),一切正常。

    <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)。

【讨论】:

    【解决方案2】:

    我在 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 中遇到过这个问题。

    好消息是,如果您使用密钥库而不是证书密钥文件,它在 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"/>
    

    --验证新的Tomcat server.xml文件

    su - tomcat
    cd /usr/local/tomcat9/conf
    /usr/local/tomcat9/bin/configtest.sh
    

    --然后,停止/启动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!!!
    

    【讨论】:

    • OP 使用certbot 生成的 PEM 文件来配置 SSL,即使在更新证书时也可以开箱即用。您建议切换回使用密钥库,每次更新证书时都需要进行干预:请参阅this answer 以使其自动化。
    • 在我的情况下,我的证书是由 Digicert 颁发的,并且证书已经以 PKCS12 PEM 格式颁发。这个问题只发生在 Ubuntu 20.04 和 Tomcat 9/10 最新版本中,但在 RedHat Linux 7/8 最新更新和 Tomcat 9/10 最新版本上它工作正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-17
    • 2020-04-05
    相关资源
    最近更新 更多