Firefox 浏览器/服务器协商的选定密码与 Tomcat 配置的密码列表不匹配

Pet*_*oss 5 java ssl jsse tomcat7

我有点困惑。我们已将 v7 Tomcat 服务器配置为仅使用 TSLv1.2 与连接的浏览器进行通信,并且我们指定了一组受限制的密码。使用 Firefox 浏览器(v60.3.0esr 64 位)。我们能够建立连接,但奇怪的是在我连接到站点后,我注意到商定的密码不在配置的 tomcat 密码列表中。

我的印象是,在配置 http 连接对象时,服务器作为 hello 连接否定的一部分会将连接限制为可​​用密码列表?我错过了什么?如果缺少 ciphers 参数,则可用密码列表将仅限于在 JVM 上配置的密码(这是我的理解)。因此,我是否还需要将 JVM 中的密码限制为我在 http 连接器元素中指定的同一组?

详细信息:Tomcat(v 7.0.77 java 1.8.0_151)

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true" allowTrace="false"
clientAuth="false" sslProtocols="TLS" sslEnabledProtocols="TLSv1.2"
keystoreFile="/etc/tomcat/tomcat.keystore" keystorePass="XXXX"
ciphers="TLS_RSA_WITH_AES_256_CBC_SHA256,
         TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
         TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
         TLS_RSA_WITH_AES_128_CBC_SHA256, 
         TLS_RSA_WITH_AES_128_CBC_SHA,
         TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
         TLS_RSA_WITH_AES_256_GCM_SHA384,
         TLS_RSA_WITH_AES_128_GCM_SHA256,
         TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
         TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
         TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
         TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384" />
Run Code Online (Sandbox Code Playgroud)

我的 tomcat.config 中没有任何具体定义

    JAVA_HOME="/usr/lib/jvm/jre"
    CATALINA_BASE="/usr/share/tomcat"
    CATALINE_HOME="/usr/share/tomcat"
    JASPER_HOME="/usr/share/tomcat"
    CATALINE_TMPDIR="/var/cache/tomcat/temp"
    TOMCAT_USER="tomcat"
    SECURITY_MANAGER="false"
    SHUTDOWN_WAIT="30"
    SHUTDOWN_VERBOSE="false"
    CATALINA_PID="/var/run/tomcat.pid
Run Code Online (Sandbox Code Playgroud)

建立连接后,我在浏览器窗口中右键单击,选择 Inspect Element 并选择 Network 标记,然后单击客户端请求。然后我选择了安全选项卡(用于请求)并显示:

     Protocol verson: TLSv1.2
     Cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
     Key Exchange group: None
     ...
Run Code Online (Sandbox Code Playgroud)

我确实注意到我们的证书已过期(我最初建立连接时收到安全异常)。

有人可以解释为什么协商密码不是 tomcat 密码列表中的密码之一吗?需要做什么来限制服务器支持的可用密码集?提前致谢。

结果:因此,启用日志记录后,服务器似乎确实在我们的连接密码列表中选择了一个密码。但是,当我检查 fire-fox 浏览安全设置时,浏览器表明它同意的密码是 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256。问题:

  1. 关于协议处理程序的初始化,为什么我有这么多协议不可用?这个 Tomcat 是否正在研究 JVM,出于某种原因,JVM 没有设置这些协议。我们不包括必需的库吗?
  2. 我可以在日志中看到客户端/服务器 hello 消息交换和商定的密码。然而浏览器显示不同的密码,这是如何变化的?有什么东西在拦截这个交换吗?至少可以说很困惑。任何的想法?

Fre*_*ext 0

关于不可用的协议,您是否确认了Java中可用的密码?确认您的 Tomcat 使用的是您期望的 Java,如 Tomcat 的 JAVA_HOME 变量所定义。您可以通过编译一个简单的 Java 程序来获取 Java 中可用的密码套件的列表。(再次强调,请确保它是使用与 Tomcat 匹配的正确 Java 进行编译的。)Java 代码文件和说明可在此处找到,但为了完整起见,我将在下面将其包含在内。

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import javax.net.ssl.SSLServerSocketFactory;

public class Ciphers
{
    public static void main(String[] args)
        throws Exception
    {
        SSLServerSocketFactory ssf = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();

        String[] defaultCiphers = ssf.getDefaultCipherSuites();
        String[] availableCiphers = ssf.getSupportedCipherSuites();

        TreeMap ciphers = new TreeMap();

        for(int i=0; i<availableCiphers.length; ++i )
            ciphers.put(availableCiphers[i], Boolean.FALSE);

        for(int i=0; i<defaultCiphers.length; ++i )
            ciphers.put(defaultCiphers[i], Boolean.TRUE);

        System.out.println("Default\tCipher");
        for(Iterator i = ciphers.entrySet().iterator(); i.hasNext(); ) 
        {
            Map.Entry cipher=(Map.Entry)i.next();

            if(Boolean.TRUE.equals(cipher.getValue()))
                System.out.print('*');
            else
                System.out.print(' ');

            System.out.print('\t');
            System.out.println(cipher.getKey());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在某个临时文件夹中,将此文件另存为 Ciphers.java,然后使用以下命令进行编译:

javac Ciphers.java
Run Code Online (Sandbox Code Playgroud)

然后运行它:

java Ciphers
Run Code Online (Sandbox Code Playgroud)

它应该输出可用密码的列表。请注意,第一行Default Cipher不是语句,而是文本表的列标题(正如您可以在代码中读到的那样)。

一种可能性是您尝试使用的密码不在 Java 实现中,因此对 Tomcat 不可用。

第二种可能性是,由于您使用的证书,某些密码对您不可用。加密不是我的强项,但我相信您需要 RSA 密码的 RSA 证书。同样TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384需要 ECDSA 证书。请参阅此security.stackexchange问题和答案。所以这些密码中有一半可能对你不起作用。

您还可以使用 OpenSSL 的 sslscan 命令来测试哪些密码套件可用。(如果您不指定端口,它将假定为 443。)

sslscan localhost:8443
Run Code Online (Sandbox Code Playgroud)

它将帮助确定您是否已正确设置 Tomcat 连接器。但是,我怀疑它会匹配您的设置,并且不会解决您的客户端连接密码套件问题。(如果进行任何更改,请不要忘记重新启动 Tomcat 服务。我还发现重新启动服务后,在 sslscan 报告完整结果之前有一点延迟。要么等待,要么执行多次以确保确定。我认为 Tomcat 准备 Web 应用程序时超时。)

不幸的是,这个答案只解决了OP的一个子问题。我想看到主要问题的答案 - 我没有答案。希望其他人也能做到...