我在JDK 1.6上运行客户端时看到handshake_failure。如何配置JDK 1.6以允许客户端连接?
我怀疑问题是SSLv2客户端问候或不支持的密码,但不是100%确定。
客户端调试输出:
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Client, setSoTimeout(61000) called
%% No cached client session
*** ClientHello, TLSv1
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
***
Client, WRITE: TLSv1 Handshake, length = 75
Client, WRITE: SSLv2 client hello message, length = 101
Client, received EOFException: error
Client, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Client
, SEND TLSv1 ALERT:
fatal,
description = handshake_failure
我理解另一种方法(不理想)是在远程服务器上允许SSLv2Hello伪协议。我羞愧地把头埋了下来要求提供商允许SSLv2Hello,但我不确定即使这样也会允许连接根据可用的密码成功。
答案 0 :(得分:2)
由于安全问题(CVE-2014-3566或Poodle等等),SSLv2和SSLv3已被弃用,因此强迫服务器接受它不是一个好主意。
也无需将客户端的JVM升级到6(只要服务器接受TLSv1),您只需禁用上述协议即可创建自定义套接字工厂(扩展默认{{1} }),然后删除它并在创建套接字时设置启用的协议
SSLSocketFactory
使用Apache HttpComponents 4.4.1(仅接受Java 6安全协议)的示例
private Socket removeSSLv2v3(Socket socket) {
if (!(socket instanceof SSLSocket)) {
return socket;
}
SSLSocket sslSocket = (SSLSocket) socket;
String[] protocols = sslSocket.getEnabledProtocols();
Set<String> set = new HashSet<String>();
for (String s : protocols) {
if (s.equals("SSLv3") || s.equals("SSLv2Hello")) {
continue;
}
set.add(s);
}
sslSocket.setEnabledProtocols(set.toArray(new String[0]));
return sslSocket;
}
或者您可以在执行客户端时通过命令行中的属性设置启用的协议(对于Java 6,它仅接受TLSv1)
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContextBuilder.build(), new String[] { "TLSv1" }, null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
或
java -Dhttps.protocols="TLSv1" <MyClient>