如何解决由于 TLS 版本不兼容导致的问题

在实际开发或实施的过程中,你很可能会遇到 TLS 版本不兼容的问题,我们以 Java 为例,你会收到如下报错

The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12]。

如果你是一名新手,又是看到 TLS 这种底层的东西,一定让你感觉到束手无策,拼命的再网上找各种解决方案,而网上基于这个问题的帖子,大多是拷贝来拷贝去,只言片语,也没说清楚了啥,说以你看了,也并不一定敢上手去尝试。

我也是命好,最近遇到这个事儿,顺手记录下来分享给大家。

遇到这个问题大家不用慌,首先这是一个非常简单的问题,本质就是:

在进行网络调用的过程中,客户端和服务端采用的 TLS 版本不一致,导致握手失败。通俗说就是语言不通,无法交流,系统把这个错误报给了你。

比如下图两台服务器:

Jenkins 从 CSM 服务器上下载代码进行构建。Jenkins 使用的是 JDK17,SCM 使用的事 VisualSVN3.9 或以下。

那么我们可以分别看一下这两个软件对 TLS 版本的支持:

JDK17 是支持 TLS1.0 ~ TLS1.3 的。

但是,官方强调了,从 JDK 6 到 JDK 7,默认使用的 TLS 版本是 TLS 1.0。JDK 8 开始,默认使用的 TLS 版本是 TLS 1.2。JDK 11 开始,支持 TLS 1.3。JDK 17 默认使用的 TLS 版本是 TLS 1.3。

VisualSVN3.9 默认支持 TLS1.0 和 TlS1.1 以下。所以看下图:

这两家是无法现实握手的,就是不兼容,系统会报出本文最开始的错误。很简单!

那么问题原因找到了,我们来解决它。解决思路就是让两边的协议有交集。比如都要支持 TLS1.0 或 TLS1.2.

但是要注意:JDK 的 TLS 1.0 和 TLS 1.1 实现存在安全漏洞,建议不要使用。

我们让两边同时支持 TLS1.0 版本,因为是内网系统,问题不大。

从上面的表格中,我们可以看到,JDK17 是支持 1.0 的,为什么不能用,是因为在他的安全配置中,已经把 1.0 给禁用了,我们可以把 1.0 放开,实现我们的需求。

这个配置文件的位置是:$JAVA_HOME/conf/security/java.security
找到里面的一行配置:jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \ DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL 说明:JDK中的jdk.tls.disabledAlgorithms参数用于禁用不安全或不需要的TLS密码算法,以提高系统的安全性。通过配置这个参数,可以指定JDK不支持的密码算法或协议,以降低它们的优先级,减少被攻击的风险。
我们把TLSv1,TLSv1.1这两个删除掉,变成如下:jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \ DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL

通过以上这些修改,我们就可以让 JDK17 支持 TLS1.0 和 TLS1.1 了。

我们可以通过以下代码来验证:

System.out.println(SSLContext.getDefault().getSupportedSSLParameters().getProtocols());

我们也可以在运行应用时禁用:

// 不禁用就是可以用java -Djdk.tls.disabledAlgorithms="SSLv3, RC4" myApp

通过以上这么一讲,你那么一改,这个问题就解决了。

那么,为什么不去升级 TLS 版本到较安全的呢,话是这么说,关键是你得两头说的都算,否则只能去兼容。

添加JVM参数:-Dhttps.protocols=TLSv1

扫码领红包

微信赞赏支付宝扫码领红包

发表回复

后才能评论