2016-04-19 7 views
0

私は単一のサーバー1.1.1.1をいくつかのホストA.comとB.comに提供しています。 各ドメインにはそれぞれ独自の証明書があります。 urlでIPを使用するときのSNIを取得する方法

私はホストベースのURLを使用しています:

URL url = new URL("https://B.com/23o8PS"); 
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
conn.connect(); 
Certificate[] certificates = ((HttpsURLConnection) conn).getServerCertificates(); 
System.out.println(certificates.length + " " + certificates[0].toString()); 

私が正常にB.comの証明書を取得することができます。しかし、私は以下のように(ホストを示すために、Hostフィールドを追加することによって)IPベースのURLを使用する場合:

それは、サーバからデフォルトの証明書として返されるかのように、私はちょうどA.comの証明書を持って
URL url = new URL("https://1.1.1.1/23o8PS"); 
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
conn.setRequestProperty("Host", "B.com"); 
conn.connect(); 
Certificate[] certificates = ((HttpsURLConnection) conn).getServerCertificates(); 
System.out.println(certificates[0].toString()); 

。 HttpURLConnectionのHOST HEADERフィールドに従ってSNIを設定できないようです。

私はこの状況にどのように対処できますか?

+0

URLにホスト名を使用します。 AFAIKでは、HTTPヘッダーが送信される前にSNIネゴシエーション全体が発生します。 – CommonsWare

+0

@CommonsWare私はヘッダーが送信される前にそれが起こることを知っていますが、SNIは私がURLから来たと思ったサーバとネゴシエートする前にホスト情報を取得しなければなりません。ですから、ヘッダーフィールドの優先順位が高いので、URLの代わりにヘッダーフィールドからホストを取得できるかどうかは疑問です。そして、それはうまくいかないようです。だから私はIPベースのリクエストでそれを行う方法はありませんか? – Ryan

+1

@ Ryan:HttpUrlConnectionの抽象度レベルでこれを処理できるかどうかは疑問です。ソケットのレベルで行うことができます。http://developer.android.com/reference/android/net/SSLCertificateSocketFactory.html#setHostname(java.net.Socket、java.lang.String)を参照してください。 –

答えて

0

Server Name Identification (SNI)は、TLSハンドシェイクの一部です。これは最初から受け継がれ、使用されているサーバー証明書を判別するために使用されます。 HTTPリクエストが送信される前にハンドシェークが発生します。そうでなければ、HTTPリクエストは暗号化されずに送信されます。 RFC 4366パー

3.1。サーバー名の表示

TLSは、クライアントがサーバーに連絡しているサーバーの名前を伝えるためのメカニズムを提供しません。単一の基礎となるネットワークアドレスで複数の「仮想」サーバーをホストするサーバーへの安全な接続を容易にするために、クライアントがこの情報を提供することが望ましい場合があります。

...

は現在、サポートされている唯一のサーバー名がDNSホスト名あります。しかし、これはTLSがDNSに依存することを意味するものではなく、将来(この文書を更新するRFCによって)追加される可能性があります。 TLSは、提供されたサーバ名を不透明なデータとして扱い、その名前と型をアプリケーションに渡すことができる(MAY)。

"HostName"には、クライアントが認識しているサーバーの完全修飾DNSホスト名が含まれます。ホスト名は、UTF-8エンコーディング[UTF8]を使用してバイト文字列として表され、末尾のドットは使用されません。

...

リテラルIPv4アドレスとIPv6アドレスを "ホスト名" には許可されていません。

SNIでIPアドレスを使用することはできません。

SNIの目的はすべて、単一のIPアドレスで複数の仮想ホストをサポートすることです。

はまた、私が欲しいものthe Java JSSE documentation.

0

を参照して代わりにDNSの要求のためのIPを指定することです。

私はこの問題を解決するために別の方法を試しました。

私はのSSLSocketFactoryをカスタマイズしたが、のcreateSocket方法をオーバーライドし、のSSLSocketのためのIPアドレスを指定しました。これは複数のドメインを持つ単一IPアドレスの下でも動作します。

関連する問題