Подтвердить что ты не робот

Почему андроид получает неправильный сертификат 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 https://198.245.xx.xxx

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

Ответ 3

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

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

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