SSL连接重置

时间:2011-04-01 00:12:16

标签: java php apache ssl openssl

我正在尝试使用Java连接到HTTPS端点。我尝试的每个方法(下面有更多细节)最终会生成这个堆栈跟踪:

java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:753)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)

我试过了:

  • 连接javax SOAP libs和新URL(“https:// ...”)
  • 使用新网址连接(“https:// ...”)。openConnection()
  • 手动创建SSL连接:

            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
        SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
    
        SSLSocket socket = (SSLSocket) factory.createSocket("...", 443);
    
        Writer out = new OutputStreamWriter(socket.getOutputStream());
        // https requires the full URL in the GET line
        //
        out.write("GET / HTTP/1.0\r\n");
        out.write("\r\n");
        out.flush();
    
        // read response
        BufferedReader in = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));
        int c;
        while ((c = in.read()) != -1) {
            System.out.write(c);
        }
    
        out.close();
        in.close();
        socket.close();
    

更多细节:

  • 我尝试过的每一种方法都与其他SSL服务器有效,这就是这个特定的服务器(我不能自由讨论什么服务器,它是商业伙伴)
  • 我可以使用Web浏览器和带有curl的伪造SOAP请求连接到此服务器;这是特定于Java的。

所以,很明显Java和HTTPS服务器之间在握手应该如何关闭方面存在一些分歧,这可能意味着服务器有一些奇怪的SSL配置。但是,我无法直接访问服务器,并且所有人都在世界的中途,因此由于时区非常不同,沟通有点紧张。

如果我的假设是正确的,那么可能存在哪些可能的SSL问题?什么可能导致这样的事情?我在哪里可以请求控制服务器的人查找问题?当我使用curl执行请求时,我会收回这些服务器配置标头:

Server: Apache/2.2.9 (Debian) mod_jk/1.2.26 PHP/5.2.6-1+lenny10 with Suhosin-Patch mod_ssl/2.2.9 OpenSSL/0.9.8g mod_perl/2.0.4 Perl/v5.10.0
X-Powered-By: PHP/5.2.6-1+lenny10
X-SOAP-Server: NuSOAP/0.7.3 (1.114)

1 个答案:

答案 0 :(得分:37)

这是一个SSL版本的问题。服务器仅支持SSLv3,Java将从v2开始,并尝试向上协商,但并非所有服务器都支持该类型的协商。

强制java只使用SSLv3是我所知道的唯一解决方案。

编辑,我知道有两种方法可以做到这一点:

  • 如果您手动创建套接字,则可以设置启用的协议

    socket.setEnabledProtocols(new String[] { "SSLv3" });
    
  • 如果您使用的是更高级别的库,则可能需要将所有SSL请求设置为仅使用v3,这是通过"https.protocols"系统属性完成的:

    java -Dhttps.protocols=SSLv3