none
JDBCでSQL Server 2012に接続する際に稀に"SQL Server が不完全な応答を返しました。"と例外が発生します。

    質問

  • OS: Windows Server 2012 R2 Datacenter
    DB: SQL Server 2012 Express
    Java: 1.6.121
    JDBC: 4.0 (jdbc:sqlserver://hostname;DatabaseName=dbname)

    上記環境でコネクションを接続する際に稀に例外が発生しますが、原因が特定できません。
    発生原因または解決方法をご存じの方、ご教授頂けますと幸いです。
    下記は例外発生時のスタックトレースとWindowsシステムログです。

    ■スタックトレース
    com.microsoft.sqlserver.jdbc.SQLServerException: ドライバーが SSL (Secure Sockets Layer) 暗号化による SQL Server への安全な接続を確立できませんでした。エラー: "SQL Server が不完全な応答を返しました。接続が閉じられました。 ClientConnectionId:xxxxxxxx"。
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1667)
        at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1668)
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1323)
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:991)
        at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:827)
        at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1012)
        at java.sql.DriverManager.getConnection(Unknown Source)
        at java.sql.DriverManager.getConnection(Unknown Source)
    Caused by: java.io.IOException: SQL Server が不完全な応答を返しました。接続が閉じられました。 ClientConnectionId:xxxxxxxx
        at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.ensureSSLPayload(IOBuffer.java:651)
        at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.readInternal(IOBuffer.java:708)
        at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.read(IOBuffer.java:700)
        at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.readInternal(IOBuffer.java:895)
        at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.read(IOBuffer.java:883)
        at com.sun.net.ssl.internal.ssl.InputRecord.readFully(Unknown Source)
        at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1618)

    ■Windowsシステムログ
    致命的な警告が生成され、リモート エンドポイントに送信されました。これにより、接続が終了される可能性があります。TLS プロトコルで定義されているこの致命的な警告のコードは 20 です。Windows SChannel エラーの状態は 960 です。
    2016年9月27日 2:05

すべての返信

  • フォーラム オペレーターの星 睦美です。tsujiura さん、投稿ありがとうございます。

    tsujiura さんの質問に書かれているエラーの内容(TLS プロトコルで定義されているこの致命的な警告のコードは 20) を手がかりにして私のほうでも役立つ情報がないか調べてみました。ご参考までに紹介させていただきますね。

    (参考情報)
    ・SSL/TLS Alert Protocol & the Alert Codes:
    https://blogs.msdn.microsoft.com/kaushal/2012/10/05/ssltls-alert-protocol-the-alert-codes/

    警告のコード:20 は"bad_record_mac" で、正常に SSL/TLS ハンドシェイクが処理できないことによるエラーのようですね。

    フォーラムの過去の質問に同じ警告のコード(20) が出力された例がありました。

    ・Active Direcory 証明書サービスを利用した場合の TLS1.0 接続について
    https://social.technet.microsoft.com/Forums/pt-BR/0d226cd6-0b45-4a99-9305-a5266064e978/active-direcory-tls10-?forum=iis7ja

    トラブルシューティングのヒントになりましたら幸いです。

    フォーラム オペレーター 星 睦美 - MSDN Community Support

    2016年9月28日 4:40
  • 情報ありがとうございます。
    未だ解決には至っていませんが、おっしゃる通り、SSL/TLSハンドシェイクでエラーとなっています。

    "-Djavax.net.debug=all"を追加して内容を確認したところ、Finishedメッセージのやり取りの部分でエラーとなっているようです(長くなるので割愛しますが、必要であれば添付します)。

    ここで、ChangeCipherSpec メッセージがクライアントから送信される。そしてクライアントは、未定状態の暗号スペックを、カレントの暗号スペックにコピーする。クライアントはすぐに、新しいアルゴリズム、鍵、そしてシークレットのもとで Finished メッセージを送信する。それに応じ、サーバーは自身の ChangeCipherSpec メッセージを送信し、未定状態の暗号スペックをカレントに移行し、新しい暗号スペックのもとで Finished メッセージを送信する。ここでハンドシェイクが完了し、クライアントとサーバーはアプリケーション層のデータの交換を開始する(下記のフローチャートを参照)。

    ※7.3. ハンドシェイクプロトコル概要より
    https://www.ipa.go.jp/security/rfc/RFC2246-07JA.html

    運用上はエラーとなった際に接続を再試行するようにして回避していますが、継続して調査は行っていますので、
    何か思い当たることがあれば情報提供頂けると助かります。

    2016年9月29日 5:45
  • 最近、WindowsUpdateされませんでしたか?

    以下のサイトを確認ください。

    https://support.microsoft.com/ja-jp/kb/3161639

    新しい暗号スイートを使用した場合にエラーとなっている可能性があります。

    該当のKBをアンインストールされて様子を見られるか

    (他のロールアップに含まれている可能性あり)

    SSL暗号スイートの順序のグループポリシーを構成し、新しい暗号スイートを除いて

    サーバを再起動されて後、様子を見てはいかがでしょうか。

    SQL Serverは資格情報のみ暗号化するようです。その際に暗号スイートを使用するのだと思います。

    もしくは、JDBCの接続元もWindowsUpdateして同様の暗号スイートを持つようになれば問題解決するかも知れません。

    検討違いでしたらすいません。

    2016年10月3日 14:14
  • 問題は解決できましたが。

    2017年11月2日 4:52