web-dev-qa-db-ja.com

SSL接続のリセット

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:// ...")で接続する
  • 新しい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ブラウザーと偽装したSOAP curlを使用したリクエストの両方を使用して接続できます。これは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)
18
roguenet

SSLバージョンの問題です。サーバーはSSLv3のみをサポートし、Javaはv2から始まり、上方へのネゴシエーションを試みますが、すべてのサーバーがそのタイプのネゴシエーションをサポートしているわけではありません。

Java SSLv3のみを使用することは、私が知っている唯一の解決策です。

編集、これを行うには私が知っている2つの方法があります。

  • ソケットを手動で作成している場合は、有効なプロトコルを設定できます

    socket.setEnabledProtocols(new String[] { "SSLv3" });
    
  • より高いレベルのライブラリを使用している場合は、v [3]のみを使用するようにすべてのSSLリクエストを設定する必要があります。これは、"https.protocols"システムプロパティ:

    Java -Dhttps.protocols=SSLv3
    
39
roguenet