2016-06-28 31 views
1

Apache HTTPサーバー経由でサイトにアクセスしているJavaクライアントおよびブラウザーで断続的なSSLハンドシェイクエラーが発生しました。これはめったに発生しませんが、ビルドを破り、毎日のユーザーエクスペリエンスに影響を与えます。サーバーは、安全な接続を確立するように構成されていますが、クライアントからの証明書は必要としません。Apache HTTPサーバーで断続的なSSLハンドシェイクエラーが発生しました

Javaテストクライアントとサーバーの両方でSSLデバッグ出力を有効にしました(下記参照)。私が観察しているのは、ハンドシェイクの例外が発生するたびに、サーバーはクライアント証明書の要求を送信したようです。私はなぜそれがそうするのか、なぜこれは散発的にしか起こらないのか分かりません。証明書要求を送信すると、ほとんどの場合、エラーはほとんど発生しますが、これが成功した(おそらくは1%の時間、99%が失敗した)要求を取得しました。

クライアントはJava 8(1.8.0_31-b13)を使用し、Apache HTTPサーバーのバージョンは2.2.19です。

SSLProtocol ALL -SSLv2 -SSLv3 
SSLCertificateFile <path-to-pem1> 
SSLCertificateChainFile <path-to-pem2> 
SSLCACertificateFile <path-to-pem3> 
SSLVerifyDepth 10 
SSLVerifyClient none 

の.pemファイルには、世界的に読み取り可能で

1)Apacheの設定の抜粋:

はここでログから抜粋されています。我々は一貫して、クライアント上で何の "*** CertificateRequest" を参照してくださいしない良い例では重度略し

2)クライアントのログ()略し

*** ClientHello, TLSv1.2 
*** 
*** ServerHello, TLSv1 
*** 
*** Certificate chain 
*** 
*** Diffie-Hellman ServerKeyExchange 
*** CertificateRequest 
*** ServerHelloDone 
*** Certificate chain 
*** 
*** ClientKeyExchange, DH 
*** Finished 
*** 
... 
main, WRITE: TLSv1 Handshake, length = 48 
main, waiting for close_notify or alert: state 1 
main, Exception while waiting for close java.net.SocketException: Software caused connection abort: recv failed 
main, handling exception: java.net.SocketException: Software caused connection abort: recv failed 
%% Invalidated: [Session-1, TLS_DHE_RSA_WITH_AES_128_CBC_SHA] 
main, SEND TLSv1 ALERT: fatal, description = unexpected_message 
... 
main, WRITE: TLSv1 Alert, length = 32 
main, Exception sending alert: java.net.SocketException: Software caused connection abort: socket write error 
main, called closeSocket() 

3)サーバーログ()

[info] [client x.x.x.x] Connection to child 1 established (server XXX:443) 
[info] Seeding PRNG with 0 bytes of entropy 
[debug] ssl_engine_kernel.c(1866): OpenSSL: Handshake: start 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: before/accept initialization 
[debug] ssl_engine_io.c(1897): OpenSSL: read 11/11 bytes from BIO#82f6820 [mem: 82c5290] (BIO dump follows) 
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1869): | 0000: XX XX XX XX XX XX XX XX-XX XX XX     ...........  | 
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1897): OpenSSL: read 245/245 bytes from BIO#82f6820 [mem: 82c529b] (BIO dump follows) 
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1869): | 0000: XX XX XX XX XX XX XX XX-XX XX XX XX XX XX XX XX ................ | 
... 
[debug] ssl_engine_io.c(1869): | 00f0: XX XX XX XX XX         .....   | 
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_kernel.c(1987): [client x.x.x.x] SSL virtual host for servername XXX found 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 read client hello A 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write server hello A 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write certificate A 
[debug] ssl_engine_kernel.c(1274): [client x.x.x.x] handing out temporary 1024 bit DH key 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write key exchange A 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write certificate request A 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 flush data 
[debug] ssl_engine_io.c(1897): OpenSSL: read 5/5 bytes from BIO#82f6820 [mem: 82c5290] (BIO dump follows) 
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1869): | 0000: 16 03 01 00 8d         .....   | 
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1897): OpenSSL: read 141/141 bytes from BIO#82f6820 [mem: 82c5295] (BIO dump follows) 
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1869): | 0000: XX XX XX XX XX XX XX XX-XX XX XX XX XX XX XX XX ................ | 
... 
[debug] ssl_engine_io.c(1869): | 0080: XX XX XX XX XX XX XX XX-XX XX XX XX XX   ............. | 
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_kernel.c(1884): OpenSSL: Write: SSLv3 read client certificate B 
[debug] ssl_engine_kernel.c(1903): OpenSSL: Exit: error in SSLv3 read client certificate B 
[debug] ssl_engine_kernel.c(1903): OpenSSL: Exit: error in SSLv3 read client certificate B 
[info] [client x.x.x.x] SSL library error 1 in handshake (server XXX:443) 
[info] SSL Library Error: 336105671 error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate No CAs known to server for verification? 
[info] [client x.x.x.x] Connection closed to child 1 with abortive shutdown (server XXX:443) 

とこのようなサーバー上での出力

[debug] ssl_engine_kernel.c(1987): [client x.x.x.x] SSL virtual host for servername XXX found 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 read client hello A 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write server hello A 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write certificate A 
[debug] ssl_engine_kernel.c(1274): [client x.x.x.x] handing out temporary 1024 bit DH key 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write key exchange A 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write server done A 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 flush data 
[debug] ssl_engine_io.c(1897): OpenSSL: read 5/5 bytes from BIO#82d82d8 [mem: 82c8790] (BIO dump follows) 
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1869): | 0000: 16 03 01 00 86         .....   | 
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1897): OpenSSL: read 134/134 bytes from BIO#82d82d8 [mem: 82c8795] (BIO dump follows) 
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_io.c(1869): | 0000: XX XX XX XX XX XX XX XX-XX XX XX XX XX XX XX XX ................ | 
... 
[debug] ssl_engine_io.c(1869): | 0080: XX XX XX XX XX XX        ......   | 
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+ 
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 read client key exchange A 

Javaクライアントコードの概要:

URL url = new URL("https://..."); 
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 
connection.setRequestProperty("Authorization", "Basic " + DatatypeConverter.printBase64Binary((user + ":" + pass).getBytes(Charset.forName("UTF-8")))); 
connection.setReadTimeout(60*1000); 
connection.setUseCaches(false); 
connection.connect(); 

java -Djavax.net.ssl.trustStore=... -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStorePassword=... -Djavax.net.debug=all ... 

質問とファイル名を指定して実行:サーバーがクライアントに ouputを "*** CertificateRequest" を引き起こして、証明書要求を送信させ何

  1. 設定 "SSLVerifyClient none"は証明書要求を妨げていませんか?
  2. 次に見たいものはありますか?

アップデート:Java 6が使用されているときにJavaクライアントがエラーを表示しないことに気付きました。この問題は、Java 7および8、Chrome、Internet Explorer、Firefoxで発生します。これは、TLSv1.1またはTLSv1.2に関する問題を指しているようです(https://serverfault.com/questions/513961/how-to-disable-tls-1-1-1-2-in-apache「OpenSSL v1.0.1にはTLSv1.2に関するいくつかの既知の問題があります」を参照)。私は少なくとも、JavaクライアントでTLSv1.1/2を無効にすると問題が解消するかどうかを確認しようとします。

答えて

0

何が原因でサーバーが証明書要求を送信し、クライアントで出力が「*** CertificateRequest」になるのですか?

サーバーでのSSL_CTX_set_client_CA_listの呼び出し。それは識別名のリストです。 SSL_CTX_set_client_CA_list man pageも参照してください。

サーバーは、CAに信頼を確立するためにSSL_CTX_load_verify_locationsに電話する必要があります。 SSL_CTX_load_verify_locations man pageも参照してください。


設定「でSSLVerifyClientのいずれもが、」証明書要求を阻止しないではありませんか。

おそらく。 SSL_CTX_set_verify man pageから、SSL_VERIFY_PEER、おそらくSSL_VERIFY_FAIL_IF_NO_PEER_CERTが必要です。次を見てどのように


任意の提案ですか?

関連するJavaコードを表示する必要があります。

サーバーとクライアントが使用するOpenSSLのバージョンを記述する必要があります。

+0

これは、CertificateRequestでクライアントに送信されます。それ以外の理由で送信する必要はありません。 – EJP

+0

@EJP - ああ、そうです。申し訳ありません。 – jww

+0

Javaサンプルコードが追加されました。そこにはOpenSSLが使用されていません。私は実際のマシンにアクセスすることはできません。 sysadminは、 "OpenSSL 1.0.1h 5月2014年6月5日<3rdpartycompanyname> extensions 3.0.16.0"がインストールされていることを伝えます。私は、Apacheが共有ライブラリを使用していると仮定します。 – JanDasWiesel

0

クライアントが証明書要求を送信すると、出力が「*** CertificateRequest」になるのはなぜですか?

SSLVerifyClientは、「オプション」以上に設定されています。おそらく.htaccessファイルに設定されている可能性があります。そのため、設定ファイルで見つけることができません。これは、グローバルに設定された `SSLVerifyClient none 'をオーバーライドします。

+0

sysadminは、.htaccessファイルがないことを伝えます。ただし、SSLVerifyClient noneは、セクションでのみ設定されています。 httpd.confに移動(グローバルに) - 有望に見えますが、明日はもっと分かります。まだ問題が散発的にしか起こらないのはなぜか私には困惑しています。 – JanDasWiesel

+0

「none」より上位に設定されています。そうしないと、CertificateRequestは送信されません。これについて疑う余地はありません。 – EJP

+0

あなたの助けが大変ありがとうございます!私のコントロール外の状況のた​​め、進歩は辛抱強く遅いです。 configが実行時に表示されるようにmod_infoの設定を尋ねました。予期しないSSLVerifyClient設定が表示されることがあります。私は、新しいJVMを起動し、同じURLに何度も何度もアクセスすることで、散発的な証明書リクエストを生成しています。これらのコールの一部が証明書要求を示し、失敗します。なぜこれが散発的にしか起こらないのか?証明書要求がサーバーのSSL状態の一部であると理解している限り、なぜ同じ要求に違反するのでしょうか? – JanDasWiesel

0

長時間の退屈なデバッグと分析の結果、私は結果を報告したいと思います。この問題は、クライアントが送信したTLSハンドシェイクメッセージの最初のClientHelloに関連しています。

Java 7およびJava 8クライアント(およびおそらくすべての最新のブラウザー)は、「サーバー名表示(SNI)」拡張機能を使用します。問題は、この拡張機能を使用する場合にのみ発生します。 Java 6クライアントはそれを送信せず、問題は発生しませんでした。この問題はTLSv1とTLSv1.2で発生しました。私たちはTLSv1.1リクエストを見たことがないので、私はコメントできません。

Java 7および8クライアントで問題を防ぐために、-Djsse.enableSNIExtension=falseを設定すると、クライアントがSNI拡張機能を送信するのを停止することができます。

httpd.confの設定(およびインクルードされたファイル)を変更して、サーバが正常に動作するかどうかを調べます。私たちが成功した場合、つまりこれについてサーバー側の回避策がある場合は、情報を投稿することがあります。上記のJavaスイッチは、少なくとも夜間のビルドには十分なクライアント側の回避策です。

+0

私はこの正確な問題は、jre 8のtomcat 8.5で発生しています。残念ながら、SNIを無効にしても問題は解決しません(少なくとも私の場合)。 – spy

関連する問題