Java - 如何使用 JVM 配置仅为某些协议禁用 TLS 密码?

2022-09-02 10:43:06

我见过很多使用jdk.tls.disabledAlgorithms在java中禁用TLS密码的示例,例如:

 jdk.tls.disabledAlgorithms=MD2, RSA keySize < 1024, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256

但是,如何使用jdk.tls.disabledAlgorithms或类似配置仅禁用某些协议的密码?

例如,如何仅禁用 ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256TLSv1.1

它似乎不支持这样做的方式,就像这样:opensssl

TLSv1.1:!TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256

它不会导致任何错误,但仍允许使用密码。

编辑:请注意,我只对基于JVM配置的答案真正感兴趣,因为我不控制许多这些服务器上的代码,只控制JVM和JVM配置。有些甚至是第三方服务器,所以更多的是运维级别的东西。

编辑2:请注意,您可以运行Java应用程序并提供参数来更改使用的协议和密码,例如 会这样做 - 但它不会让你按协议过滤密码,只有密码,或者协议,从我所看到的。该文件将包含一个属性条目,如java -server -Djava.security.properties=./my/custom/java.security -jar myapp.jarjdk.tls.disabledAlgorithms


答案 1

发布我的评论作为答案,因为为什么不呢。

其他答案,以及我在网上找到的每个文档,似乎都同意你所要求的东西在Java中是不可能的,至少现在还不是。您可以全局启用/禁用协议,也可以全局启用/禁用密码类型,但不能基于另一个密码类型执行一个。

但是,由于您处于DevOps端,因此可能使用非Java解决方案。您可以运行应用程序的单独实例,每个实例仅启用了TLSv1.1,仅启用TLSv1.2等,并对每个实例应用所需的密码过滤器;然后让nginx(或您使用的任何东西)根据检测到的协议将流量重定向到适当的实例。

因此,在 NODE1 上有一个实例::

jdk.tls.client.protocols=TLSv1.1
jdk.tls.disabledAlgorithms=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256

节点 2 上的另一个实例具有:

jdk.tls.client.protocols=TLSv1.2
jdk.tls.disabledAlgorithms=...

和一些nginx规则(使用或你认为合适的):returnrewrite

server {
    [...]
    if ( $ssl_protocol = TLSv1.1 ) {
        return 302 $scheme://NODE1.yourhost.com$request_uri;
    }
    if ( $ssl_protocol = TLSv1.2 ) {
        rewrite ^ $scheme://NODE2.yourhost.com$request_uri;
    }

我只是一个Java开发人员,我对nginx的经验非常有限,所以你可能需要稍微调整一下配置。只是想帮忙。


答案 2

JSSE文档说,该属性可以在给定的SSL上下文中存储受支持协议的逗号分隔列表,但是当前JSSE实现使用此属性,但其他供应商或未来版本可以忽略此属性,因此YMMV也是如此。https.protocols

从程序上看,你可以像这样实现它:

SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
socket.setEnabledCipherSuites(new String[] {
    CipherSuite.TLS_RSA_WITH_RC4_128_MD5.javaName,
    CipherSuite.TLS_RSA_WITH_RC4_128_SHA.javaName,
});

//allow TLS1.2 only
socket.setEnabledProtocols(new String[] {
    TlsVersion.TLS_1_2.javaName,
});

推荐