Почему андроид получает неправильный сертификат ssl? (Два домена, один сервер)

У меня есть два домена: foo.net и bar.com . У них обоих есть 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 или в журнале ошибок. В моем проекте андроида нет упоминания о bar.com .

Изменить: я не уверен, почему, но похоже, что сервер использует сертификат для bar.com для IP- bar.com сервера https://198.245.xx.xxx

Solutions Collecting From Web of "Почему андроид получает неправильный сертификат ssl? (Два домена, один сервер)"

Наиболее вероятной причиной этой проблемы является то, что сервер использует указание имени сервера, чтобы выбрать, какой сертификат отправить. Если клиент не поддерживает SNI, сервер не может выбрать, какой сертификат отправлять по протоколу SSL / TLS (до отправки любого HTTP-трафика). SNI требуется, если вы хотите использовать несколько сертификатов на одном IP-адресе и порту, но не все клиенты поддерживают его (как известно, IE на любой версии Windows XP и ряд мобильных браузеров).

Вы также видимо используете библиотеку Apache HTTP Client (а не HttpsURLConnection , для которой может быть поддержка SNI с некоторыми версиями Android . Поддержка SNI в клиентской библиотеке Apache HTTP довольно недавно и, конечно же, не попала в Android стек.

Возможно, обходной путь, описанный в этой статье, полезен (хотя, похоже, он работает только для Android 4.2+).

Еще два варианта:

  • Использовать отдельный IP-адрес для каждого хоста (чтобы не требовалось SNI), если вы контролируете сервер, или
  • Для использования другой клиентской библиотеки HTTP (например, HttpsURLConnection ).

Похоже, что сертификат foo.net неверно сконфигурирован и использует то же имя хоста, что и bar.com

Попробуйте запустить инструмент проверки онлайн-сертификата, например https://www.digicert.com/help/ на foo.net, чтобы быть уверенным.

Я думаю, что вам нужно восстановить сертификат foo.net с правильным именем хоста или перенастроить ngix, чтобы убедиться, что nginx обслуживает правильный сертификат для правильного хоста.

Решение для Apache, больше похоже на трюк: SSL-сертификаты загружаются на основе имени vhost из / etc / apache2 / sites-enabled. Итак, чтобы обмануть эту проверку, убедитесь, что проблемный сертификат загружен первым (помните, что vhosts загружаются по имени).