SSL/TLSを使用してWebサーバーに接続し、その接続を介してさまざまなHTTP要求を送信するJavaプログラムがあります。サーバーはlocalhostであり、自己署名証明書を使用していますが、私のコードはカスタムTrustManagerを使用し、無効な証明書を無視します。
サーバー上の唯一の違いは、jboss 6の実行に使用され、現在jboss 7を実行していることです。これが設定の問題なのか、コードに問題があるのかはわかりませんが、 WebScarabやZAPなどの他のJavaベースのプログラムを使用して接続しようとしています。
いずれにしても、この問題を回避するためにコードにできることはありますか?完全なエラーは次のとおりです。
Received fatal alert: handshake_failure
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.Sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.Sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(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 Sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at Sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at Sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source)
失敗前のデバッグメッセージは次のとおりです。
main, WRITE: TLSv1 Handshake, length = 75
main, WRITE: SSLv2 client hello message, length = 101
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT: fatal, handshake_failure
そこで問題を見つけました。 Javaにバグがある可能性がありますが、クライアントはTLSv1ハンドシェイクを開始しているように見えますが、SSLv2クライアントのhelloメッセージを送信すると、サーバーは接続を拒否します。
これは、TLSのインスタンスを使用してSSLContextを作成した場合でも発生します。
SSLContext sslContext = SSLContext.getInstance("TLS");
解決策は、接続を試行する前にシステムプロパティを設定することです。
System.setProperty("https.protocols", "TLSv1");
おそらく他の解決策もありますが、これは私にとってはうまくいきました。
これは解決されましたか?
私はまったく同じ問題を抱えていました。本質的に、clientHelloの直後にハンドシェイク例外を受け取りました。イベントのチェーンは
最終的に、最初のハンドシェイクフェーズで提供していたものよりも強力な暗号化/復号化アルゴリズムがサーバーに必要であることがわかりました(つまり、クライアントとサーバーは、SSL通信に使用する相互暗号化アルゴリズムに同意できませんでした)。
Unlimited Java JCE(Java Cryptography Extension Policy)をインストールする必要があります。これを使用するためのエクスポートルールがあります。そのため、コードを海外に出荷する場合は影響があります。私の問題。
このリンクでは、更新されたポリシーをインストールする方法について説明します http://suhothayan.blogspot.com/2012/05/how-to-install-Java-cryptography.html
これは、何が起こっているのかを正確に理解するのに役立つ素晴らしいリンクでもありました https://support.f5.com/kb/en-us/solutions/public/15000/200/sol15292.html#id =
これは問題の場合もそうでない場合もありますが、クライアントHelloの直後にハンドシェイクが失敗すると、クライアントとサーバーは何かに同意できないように見えます(多くの場合、相互に通信する必要がある暗号化アルゴリズム)。
提供する情報は、スタックトレースと同様に非常にわずかです。
ここで推測します。
[。
TLSのより高いバージョンを使用するようにクライアントを変更するか、
WebサーバーもSSLv3をサポートするようにします。 Tomcatでこれを行う方法は知っていますが、JBossではできません。
これでうまくいかない場合は、より多くの情報(および完全なスタックトレース)で投稿を更新します。
SSLデバッグ情報を有効にする必要があります-Djavax.net.debug=ssl
このエラーが表示されるのは、JBoss 6がアクセスしたキーストアにJBoss 7インスタンスがアクセスできないためです。
私がお勧めするのは以下です。
自己署名サーバー証明書をトラストストアにインポートする必要があります
keytool -import -alias gridserver -file server.crt -storepass $YOUR_PASSWORD_HERE -keystore server.keystore
Run.confに次のプロパティを追加します
-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=server.keystore
-Djavax.net.debug=ssl # very verbose debug. Turn this off after everything looks good.
-Djavax.net.ssl.keyStorePassword=$YOUR_PASSWORD_HERE
-Djavax.net.ssl.trustStorePassword=$YOUR_PASSWORD_HERE
スタックトレースは、クライアントコードとクライアント「[a] fatal alertを受信しました」からのものです。つまり、クライアントではなくJbossでSSLエラーが発生しました。
したがって、クライアント側のカスタムTrustManagerは、それとは何の関係もありません。私の予想では、新しいJboss 7はクライアント証明書を要求するように設定されており、クライアントは証明書を提示していません。
SSL接続をデバッグするには、opensslを使用してこれを試してください。
openssl s_client -connect jboss.server.com:443
またはそれはSSLV3サーバーですか
openssl s_client -connect jboss.server.com:443 -ssl3
これにより、多くの興味深い情報が出力されます。
これは Java 7バグ に関連していると思います。これ以上詳細がないと確実なのは難しい。
私にとっての解決策は次のとおりでした:System.setProperty("https.protocols", "TLSv1.1,TLSv1.2");