简体   繁体   English

如何在配置了SSL的tomcat中缓存和更新CRL(证书吊销列表)/ OCSP响应?

[英]How to cache and update CRL (certificate revokation list)/OCSP responses in SSL configured tomcat?

I've been trying to setup SSL/TLS handshake in Tomcat 8. I've successfully done all the configurations but there are some problems I'm facing with CRL/OCSP. 我一直在尝试在Tomcat 8中设置SSL / TLS握手。我已经成功完成了所有配置,但是CRL / OCSP面临一些问题。

I need solution to: this 我需要的解决方案:

I've a couple of questions so kindly have some patience. 我有几个问题,请耐心等待。 Any help would be really appreciated. 任何帮助将非常感激。

  1. Does tomcat 8 allow us to cache the CRL file obtained from the CRL distribution point ? tomcat 8是否允许我们缓存从CRL分发点获得的CRL文件? By cache I mean that if network isn't available and we start the server, I don't want tomcat to allow access to all users by default (which it does) because CRL distribution point wasn't available. 缓存是指如果网络不可用并且我们启动服务器,那么我不希望tomcat默认允许所有用户访问(这样做),因为CRL分发点不可用。 I want it to cache the last available list and use that if CRL can't be downloaded now. 我希望它缓存最后一个可用列表,并在无法立即下载CRL时使用它。 If it can be downloaded then update the existing cache. 如果可以下载,则更新现有缓存。

I've below configuration of connector in server.xml. 我在server.xml中配置了连接器。

 <Connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="8443" maxThreads="2000" clientAuth="want" scheme="https" keepAliveTimeout="-1" connectionTimeout="900000" compression="on" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml,text/css,text/javascript,image/jpg,image/ico,image/png,image/jpeg,image/tiff,image/tif" secure="true" SSLEnabled="true" sslProtocol="TLS" sessionTimeout="30" truststoreFile="D:\\Certs\\server.truststore" truststorePass="123456" keystoreFile="D:\\Certs\\keystore.pkcs12" keystorePass="password" keystoreType="PKCS12" crlFile="http://127.0.0.1:8600/getCRLFile/" maxKeepAliveRequests="200" sslEnabledProtocols= "TLSv1,TLSv1.1,TLSv1.2" maxHttpHeaderSize="65536" maxPostSize="4194304" ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA"/> 

Can I achieve this using any of the tomcat configuration ? 我可以使用任何tomcat配置来实现吗?

  1. I found a way to achieve the above task my manipulating a Java code found here ! 我找到了一种方法来实现上述任务,我的操作找到了Java代码在这里

Problem with this is that I'll have to send the certificates of client while handshaking to this java code and accept/reject the certificate based on reply from this code. 问题是,我必须在握手到此Java代码时发送客户端证书,并基于此代码的回复接受/拒绝证书。 I don't know how to do that. 我不知道该怎么做。 Any help will be of great use. 任何帮助都会很有用。 The second reason is I would prefer to achieve task 1 using tomcat configurations rather than custom code because custom code might miss out on some aspects. 第二个原因是我更喜欢使用tomcat配置而不是自定义代码来完成任务1,因为自定义代码在某些方面可能会遗漏。

  1. Can I dynamically pick an updated CRL from the CRL distribution URL without restarting the tomcat server ? 是否可以在不重新启动tomcat服务器的情况下从CRL分发URL动态选择更新的CRL? The current scenario with above configuration picks the CRL file once when server is turned On and then it uses that copy only even if CRL list available on the URL has changed. 具有上述配置的当前方案在服务器打开时选择一次CRL文件,然后即使URL上可用的CRL列表已更改,它也仅使用该副本。

  2. Can we have multiple CRL end-points configured in the connector ? 我们可以在连接器中配置多个CRL端点吗? Tomcat will check them all and accept/reject a client certificate based on combined list from all the URLs. Tomcat将检查所有这些内容,并根据来自所有URL的组合列表接受/拒绝客户端证书。

    1. If configured, can I cache OCSP responses in a similar way I want to cache CRL lists ? 如果已配置,是否可以以与我要缓存CRL列表类似的方式来缓存OCSP响应?

Thanks in advance. 提前致谢。 Please feel free to ask any details I might have missed. 请随时询问我可能错过的任何详细信息。

Answering my own question. 回答我自己的问题。

I could find a way to cache CRL. 我可以找到一种缓存CRL的方法。 What I did was to make crlFile of connector in server.xml to point to a CRL file on local machine. 我所做的是在server.xml中使连接器的crlFile指向本地计算机上的CRL文件。 I updates this file using a CRON job time to time. 我会不时使用CRON作业来更新此文件。

Starting with Tomcat v8.5.24, a new API has been added to refresh the whole SSL config without restarting Tomcat server. 从Tomcat v8.5.24开始,已添加新的API以刷新整个SSL配置,而无需重新启动Tomcat服务器。 I called those APIs time to time too to pick the updated CRL file from the local machine. 我也不时调用这些API,以从本地计算机中选择更新的CRL文件。

They introduced 2 methods named: 他们介绍了两种名为:

  1. reloadSslHostConfig(String hostName) - to reload a specific host reloadSslHostConfig(String hostName)-重新加载特定的主机
  2. reloadSslHostConfigs() - reload all reloadSslHostConfigs()-重新加载全部

They can be called in various ways: 可以通过多种方式调用它们:

  1. Using jmx 使用jmx
  2. Using manager service 使用经理服务
  3. By making custom protocol - I found this way during my research 通过制定自定义协议-我在研究期间发现了这种方式

Details of way 1 and way 2 are easily available online. 方法1和方法2的详细信息可轻松在线获得。

Details of how to go about using way 3: 如何使用方式3的详细信息:

  1. Make a class extending the protocol of your choice for eg. 制作一个类,扩展您选择的协议,例如。 Http11NioProtocol Http11NioProtocol
  2. Override the required methods and just call super in them to keep default behavior 覆盖所需的方法,仅在其中调用super即可保持默认行为
  3. Make a thread in this class to call reloadSslHostConfigs method time to time 在此类中创建线程以不时调用reloadSslHostConfigs方法
  4. Package this class in a jar and put that jar in tomcat's lib folder 将此类包装在jar中,然后将该jar放入tomcat的lib文件夹
  5. Edit protocol in connector in server.xml to use this custom defined protocol 在server.xml的连接器中编辑协议以使用此自定义协议

Find sample code below: 在下面找到示例代码:

Main protocol class: 主协议类:

    package com.myown.connector;

    import java.io.File;
    import java.io.InputStream;
    import java.lang.reflect.Field;
    import java.net.URL;
    import java.net.URLConnection;
    import java.nio.file.StandardCopyOption;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ConcurrentMap;

    import javax.management.MalformedObjectNameException;
    import javax.management.ObjectName;
    import javax.net.ssl.SSLSessionContext;

    import org.apache.coyote.http11.Http11NioProtocol;
    import org.apache.juli.logging.Log;
    import org.apache.juli.logging.LogFactory;
    import org.apache.tomcat.util.modeler.Registry;
    import org.apache.tomcat.util.net.AbstractEndpoint;
    import org.apache.tomcat.util.net.AbstractJsseEndpoint;
    import org.apache.tomcat.util.net.GetSslConfig;
    import org.apache.tomcat.util.net.SSLContext;
    import org.apache.tomcat.util.net.SSLHostConfig;
    import org.apache.tomcat.util.net.SSLHostConfigCertificate;
    import org.apache.tomcat.util.net.SSLImplementation;
    import org.apache.tomcat.util.net.SSLUtil;

    public class ReloadProtocol extends Http11NioProtocol {

        private static final Log log = LogFactory.getLog(Http12ProtocolSSL.class);

        public ReloadProtocol() {
            super();
            RefreshSslConfigThread refresher = new 
                  RefreshSslConfigThread(this.getEndpoint(), this);
            refresher.start();
        }

        @Override
        public void setKeystorePass(String s) {
            super.setKeystorePass(s);
        }

        @Override
        public void setKeyPass(String s) {
            super.setKeyPass(s);
        }

        @Override
        public void setTruststorePass(String p) {
            super.setTruststorePass(p);
        }

        class RefreshSslConfigThread extends Thread {

            AbstractJsseEndpoint<?> abstractJsseEndpoint = null;
            Http11NioProtocol protocol = null;

            public RefreshSslConfigThread(AbstractJsseEndpoint<?> abstractJsseEndpoint, Http11NioProtocol protocol) {
                this.abstractJsseEndpoint = abstractJsseEndpoint;
                this.protocol = protocol;
            }

            public void run() {
                int timeBetweenRefreshesInt = 1000000; // time in milli-seconds
                while (true) {
                    try {
                            abstractJsseEndpoint.reloadSslHostConfigs();
                            System.out.println("Config Updated");
                    } catch (Exception e) {
                        System.out.println("Problem while reloading.");
                    }
                    try {
                        Thread.sleep(timeBetweenRefreshesInt);
                    } catch (InterruptedException e) {
                        System.out.println("Error while sleeping");
                    }
                }
            }
       }
}

Connector in server.xml should mention this as the protocol: server.xml中的连接器应将此作为协议提及:

<Connector protocol="com.myown.connector.ReloadProtocol"
 ..........

Hope this helps someone. 希望这对某人有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM