1. ホーム
  2. java

[解決済み】SSL接続のリセット

2022-02-02 07:37:22

質問

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サーバーではうまくいきましたが、この特定のサーバーではうまくいきません(どのサーバーかは自由に話すことができません、ビジネスパートナーです)。
  • このサーバーには、ウェブブラウザーでも、curlでSOAPリクエストを偽装しても接続できます。

つまり、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バージョンの問題です。サーバはSSLv3しかサポートしておらず、Javaはv2で開始し、上方へのネゴシエーションを試みますが、すべてのサーバがそのタイプのネゴシエーションをサポートしているわけではありません。

javaがSSLv3のみを使用するように強制することが、私が知っている唯一の解決策です。

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

  • ソケットを手動で作成する場合は、有効なプロトコル

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

    java -Dhttps.protocols=SSLv3