【问题标题】:SSL Connection ResetSSL 连接重置
【发布时间】:2011-07-27 08:16:26
【问题描述】:

我正在尝试连接到 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 库和新 URL("https://...")
  • 正在连接新的 URL("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)

【问题讨论】:

  • 该异常跟踪没有显示代码中出现问题的位置。可能 SSL 连接已成功建立,问题出在您的 HTTP 上。
  • 它在我的代码中出现的位置因我使用的方法而异。它总是发生在 out.flush() 或开始读取连接时。不过,我包含的部分始终相同 - 问题出在握手中。
  • 更新:可能是 SSL 版本问题。我发现服务器只支持 SSLv3,Java 将从 v2 开始,并尝试向上协商,但并非所有服务器都支持这种类型的协商。当我确定这是问题所在时,我会再次发布。
  • @Nathan:您应该用解决方案回答您自己的问题,然后接受您的回答。你不会得到任何分数,但它会作为一个已回答的问题显示给其他有同样问题的人,并且可能会帮助其他人。
  • 是的,我回答了,但 48 小时内我无法接受自己的回答。我会在允许的情况下这样做。谢谢!

标签: java php apache ssl openssl


【解决方案1】:

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

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

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

  • 如果是手动创建socket,可以设置启用的协议

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

    java -Dhttps.protocols=SSLv3
    

【讨论】:

  • 干得好!现在回答所有剩余的开放 SSL 问题 :)
  • 另外,JDK 7 默认为 TLSv1,JDK 8 默认为 TLSv1.2。来源:blogs.oracle.com/java-platform-group/entry/…
  • 您可能需要添加所有这些来处理其他情况:TLSv1.2,TLSv1.1,TLSv1,SSLv3
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 2016-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多