2013-08-15 16 views
50

SSLを使用してHAProxyサーバーに接続するとランダムに表示される接続エラーが発生します。これらの障害はJDKバージョン1.7.0_21および1.7.0_25では発生しますが、1.7.0_04または1.6.0_38では発生しないことが確認されています。

の例外は、デフォルトのコンテキストでTLSのSSLコンテキストを使用していない場合、これらの障害にのみ起こる

Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated 
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397) 
    at SSLTest2.main(SSLTest2.java:52) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 

です。次のコードは、ループが完了する前に(接続の約2%が失敗)千回と障害が起こるループ内で実行されます、しかし、私はこの方法をSSLコンテキストを作成した場合

SSLContext sslcontext = SSLContext.getInstance("TLS"); 
sslcontext.init(null, null, null); 
SSLSocketFactory factory = sslcontext.getSocketFactory(); 
SSLSocket socket = (SSLSocket)factory.createSocket("myserver", 443); 

//socket.startHandshake(); 
SSLSession session = socket.getSession(); 
session.getPeerCertificates(); 
socket.close(); 

私は、接続されていません私が言及したのJavaのバージョンのいずれかの障害:

SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault(); 

最初の方法は、SSLContextImpl$TLS10Contextを使用して以降ではSSLContextImpl$DefaultSSLContextを使用しています。コードを見ると、例外が発生するような相違はありません。

なぜ私は失敗するのでしょうか、getDefault()コールを使用するメリットとデメリットは何ですか?

注:例外はApache HttpClient(バージョン4)を使用して最初に確認されました。このコードは、HttpClientで見られる問題を再現する最小のサブセットです。

ここ-Djavax.net.debug=sslを追加するとき、私は見誤りです:

main, READ: TLSv1 Alert, length = 2 
main, RECV TLSv1 ALERT: fatal, bad_record_mac 
%% Invalidated: [Session-101, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA] 
main, called closeSocket() 
main, handling exception: javax.net.ssl.SSLException: Received fatal alert: bad_record_mac 
main, IOException in getSession(): javax.net.ssl.SSLException: Received fatal alert: bad_record_mac 

は別の情報Iは、プロキシサーバー上のDiffie-Hellmanのをオフにした場合、エラーが発生しないということです。

+3

-Djavax.net.debug = ssl、ハンドシェイクで再実行し、失敗した実行からの出力を投稿してください。 – EJP

+0

デバッグオプションをオンにして再度実行します。この情報で質問を更新しました。誰にもアイデアはありますか? – user2687486

+0

なぜ4行のコードを1本にするのが好きですか? – EJP

答えて

1

私はが、これはGoogleがreduce the back-and-forth in TLSに導入クライアント側のトリックですTLS false startを使用して、ブラウザに関連しているを推測している、症状から判断する:

不正スタートは、主にブラウザによって制御され、公式のSSL仕様に記載されているデータの2回の往復パスを1回の往復パスに減らすことで動作します。これは、完了したApplicationDataメッセージと最初のApplicationDataメッセージを2つの別個のパッケージに入れず、サーバーからの確認を得た後に送信するのではなく、1つのディスパッチで送信するようクライアントに指示することで行いました。

Googleは現在、高価すぎるサイトを提供するためにSSLをより美味しくする公式の標準としてFalse Startを提案しました。 False Startは、暗号鍵と、エンドユーザとウェブサイトとの間のデータのやりとりを保護するために必要な他の変数をネゴシエートするハンドシェイクを省略することによって、プロトコルの使用に起因するパフォーマンスの低下を軽減することを意図していました。relevant issue raised in Mozilla Firefoxから

:(強調鉱山)が

はこれまでのところ、不正スタートと現在または以前の互換性の問題があることが知られている製品の不完全なリストは、(AFAICT):F5、A10、 Microsoft TMG、Cisco ASA、ServerIron ADX、ESET、NetNanny、JavaのSSLサーバー実装の一部の構成

+0

OPの場合と私の場合の接続は、JAVAで書かれたクライアントとサーバー(プロキシまたはhttp)の間の接続です。ここのブラウザはありません... –

+0

@LorenzoDemattéAah、もちろん、あなたは正しいです。私はそれを逃したとは信じられません。 – JvR

-3

javax.net.ssl.SSLPeerUnverifiedExceptionは..あなたはこのコードをたどるhttpsの他、あなたの接続を設定するために持っている唯一の理由は、HTTPのセキュリティの

  SSLContext ctx = SSLContext.getInstance("TLS"); 
    ctx.init(null, new TrustManager[]{tm}, null); 
    SSLSocketFactory ssf = new SSLSocketFactory(ctx); 
    ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
    ClientConnectionManager ccm = client.getConnectionManager(); 
    SchemeRegistry sr = ccm.getSchemeRegistry(); 
    sr.register(new Scheme("https", ssf, 443)); 
    return new DefaultHttpClient(ccm, client.getParams()); 

使用これを発生します。私はそれがあなたを助けてくれることを願っています

+3

あなたは 'ALLOW_ALL_HOSTNAME_VERIFIER'にセキュリティ脆弱性を導入しています。これは役に立たないことです。 – Bruno

+0

「HTTPセキュリティだけのために発生しません」ということはまったくありません。それはHTTPSとは関係ありません。これはTLSレイヤーで発生します。 – EJP

関連する問題