如何配置JDK 1.6以对仅TLS服务器进行ssl握手

时间:2016-05-17 09:18:56

标签: java ssl

我在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,但我不确定即使这样也会允许连接根据可用的密码成功。

1 个答案:

答案 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>