【问题标题】:Java 8 , JCE Unlimited Strength Policy and SSL Handshake over TLSJava 8、JCE 无限强度策略和基于 TLS 的 SSL 握手
【发布时间】:2015-06-16 09:41:57
【问题描述】:

使用Java 8,服务器仅支持TLSv1,无法从cent OS 建立安全套接字连接

版本

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

来源

import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created by jigar.joshi on 6/10/15.
 */
public class SSLTester {
    public static void main(String[] args) throws Exception {
        SSLSocketFactory f =
                (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket socket = (SSLSocket) f.createSocket("efm.sandbox.vovici.com", 443 );
        try {
            printSocketInfo(socket);
            socket.startHandshake();    
            System.out.println("----------------------------------SUCCESS----------------------------------");

            BufferedReader r = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));
            String m = null;
            while ((m = r.readLine()) != null) {
                System.out.println(m);

            }
            r.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println(e.toString());
        }
    }

    private static void printSocketInfo(SSLSocket s) {
        System.out.println("Socket class: " + s.getClass());
        System.out.println("    Remote address = "
                + s.getInetAddress().toString());
        System.out.println("    Remote port = " + s.getPort());
        System.out.println("    Local socket address = "
                + s.getLocalSocketAddress().toString());
        System.out.println("    Local address = "
                + s.getLocalAddress().toString());
        System.out.println("    Local port = " + s.getLocalPort());
        System.out.println("    Need client authentication = "
                + s.getNeedClientAuth());
        SSLSession ss = s.getSession();
        System.out.println("    Cipher suite = " + ss.getCipherSuite());
        System.out.println("    Protocol = " + ss.getProtocol());
    }

}

使用相同版本的JVM,在OSX上握手成功,在centOS上失败,失败原因是它只尝试使用TLSv1.2(JVM 8中默认)并且不尝试较低的协议

调试说明:

-Ddeployment.security.TLSv1.0=true 

-Ddeployment.security.TLSv1=true 

-Ddeployment.security.TLSv1.1=false 

-Ddeployment.security.TLSv1.2=false 

-Djavax.net.debug=ssl:handshake:verbose 

问题:

  • 为什么在 OSX 上可以选择 TLSv1 而在 CentOS 上却不能?

  • 我如何告诉 JVM 以特定顺序使用协议,或者如果它考虑版本顺序,那么我如何告诉它也尝试使用 v1

编辑:

我在 JRE 中安装了无限强度的 JCE 策略,这导致了这种情况,没有它就可以工作,所以 OSX 和 CentOS 的差异消失了,我怎样才能让它工作?

编辑:

输出

Socket class: class sun.security.ssl.SSLSocketImpl
    Remote address = efm.sandbox.vovici.com/206.132.29.15
    Remote port = 443
    Local socket address = /10.10.152.143:50376
    Local address = /10.10.152.143
    Local port = 50376
    Need client authentication = false
    Cipher suite = SSL_NULL_WITH_NULL_NULL
    Protocol = NONE
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1529)
    at sun.security.ssl.SSLSocketImpl.checkWrite(SSLSocketImpl.java:1541)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
    at SSLTester.main(SSLTester.java:24)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:980)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
    at sun.security.ssl.SSLSocketImpl.getSession(SSLSocketImpl.java:2225)
    at SSLTester.printSocketInfo(SSLTester.java:56)
    at SSLTester.main(SSLTester.java:23)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.InputRecord.read(InputRecord.java:505)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:961)
    ... 5 more
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake

【问题讨论】:

  • 究竟是什么异常?为什么要手动拨打startHandshake()? SSLSocket 透明地执行握手,此外,printSocketInfo 中的getSession() 已经发起了握手。
  • 感谢@apangin,添加输出,我认为这里可以明确地忽略握手

标签: java ssl jvm centos java-8


【解决方案1】:

尝试将协议限制为仅TLSv1,使用:

-Djdk.tls.client.protocols=TLSv1

查看此页面了解更多详情:https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#descPhase2

希望这会有所帮助,

尤里

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-31
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多