web-dev-qa-db-ja.com

Androidが間違ったSSL証明書を取得するのはなぜですか?(2つのドメイン、1つのサーバー)

foo.netbar.comの2つのドメインがあります。どちらもSSL証明書を持っており、すべてのデスクトップブラウザとモバイルブラウザでうまく機能します。これらは、nginxで構成された同じサーバーでホストされます。

ただし、ネイティブAndroidアプリ内からドメインにリクエストを送信すると、どういうわけか間違ったドメインから証明書を取得します!これにより、IO例外:

request = new HttpPost("https://foo.net/api/v1/baz");
request.setHeader("Authorization", "user:pass");
response = httpClient.execute(request);

.。

javax.net.ssl.SSLException: hostname in certificate didn't match: <foo.net> != <bar.com> OR <bar.com> OR <www.bar.com>

サーバーが正しく構成されていることを他のすべての測定値が示しているように見える場合、Android/Javaがbar.comからの証明書を使用しようとする原因は何ですか? nginxアクセスまたはエラーログには何も表示されません。私のAndroidプロジェクトのどこにもbar.comについての言及はありません。

編集:理由はわかりませんが、サーバーがサーバーIP bar.comhttps://198.245.xx.xxxの証明書を使用しているようです

17
hughes

この問題の原因として最も可能性が高いのは、サーバーが Server Name Indication を使用して送信する証明書を選択することです。クライアントがSNIをサポートしていない場合、サーバーはSSL/TLSハンドシェイク中に(HTTPトラフィックが送信される前に)送信する証明書を選択できません。 SNIは、同じIPアドレスとポートで複数の証明書を使用する場合に必要ですが、すべてのクライアントがSNIをサポートしているわけではありません(WindowsXPのすべてのバージョンと多数のモバイルブラウザーでIE )。

また、Apache HTTPクライアントライブラリを目に見えて使用しています(HttpsURLConnectionではありません。 いくつかのAndroidバージョン でSNIサポートがあります。 Apache HTTPクライアントライブラリのSNI ごく最近 、そして確かにAndroidスタックには入っていません。

この記事で説明されている回避策 は便利です(ただし、Android 4.2+)でのみ機能するようです)。

別の2つのオプションは次のとおりです。

  • サーバーを制御している場合、(SNIを必要としないように)ホストごとに異なるIPアドレスを使用する、または
  • 別のHTTPクライアントライブラリ(例:HttpsURLConnection)を使用する。
29
Bruno

トリックのようなApacheのソリューション:SSL証明書は/ etc/Apache2/sites-enabledからの仮想ホスト名に基づいてロードされます。したがって、そのチェックをだますには、問題のある証明書が最初にロードされていることを確認してください(vhostは名前でロードされていることに注意してください)。

4
Sorin Trimbitas

Foo.netの証明書が正しく構成されておらず、bar.comと同じホスト名を使用しているようです。

念のため、foo.netで https://www.digicert.com/help/ などのオンライン証明書検証ツールを実行してみてください。

Foo.netの証明書を正しいホスト名で再生成するか、ngixを再構成してnginxが正しいホストに正しい証明書を提供するようにする必要があると思います。

0
flolom