java.security.cert.CertificateException при подключении к серверу с несколькими сертификатами

Я пытаюсь создать SSL-соединение с веб-сайтом (https://www.otten-markenshop.de/), и с помощью браузера или curl это работает, но ни wget, ни Java не удается подключиться. Меня больше всего интересует, почему код Java дает сбой. Вот подробности ошибки:

Использование WGET:

wget https://www.otten-markenshop.de/

приводит к

Resolving www.otten-markenshop.de... 217.24.213.167
Connecting to www.otten-markenshop.de|217.24.213.167|:443... connected.
ERROR: certificate common name “www.plentymarkets.eu” doesn’t match requested 
host name “www.otten-markenshop.de”.

Использование Java:

public static void main(String[] args) throws IOException
{
    URL url = new URL("https://www.otten-markenshop.de");
    URLConnection connection = url.openConnection();
    connection.getInputStream();
}

приводит к:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: 
java.security.cert.CertificateException: No subject alternative DNS 
name matching www.otten-markenshop.de found.

Что еще я заметил, так это то, что сертификат, который я получаю в браузере, отличается от сертификата, который я получаю при запуске программы Java:

в браузере:

Common Name (CN): 
    www.otten-markenshop.de
Subject Alternative Name: 
    DNS Name=www.otten-markenshop.de 
    DNS Name=otten-markenshop.de

в Яве:

Common Name (CN): 
    www.plentymarkets.eu
Subject Alternative Name: 

И сертификат, который я получаю в Java, такой же, как и в браузере, если я пытаюсь получить доступ к хосту по IP-адресу: https://217.24.213.167 Таким образом, получается, что на сервере установлено несколько сертификатов, и он использует виртуальные хосты для определения того, какой сертификат следует использовать. Но по какой-то причине это определение не работает, когда клиент Java или wget.

Любые идеи, почему это происходит?

P.S. У меня нет доступа к целевому серверу, чтобы посмотреть, как он настроен.

П.П.С. Мне больше интересно понять, почему простой Java-код не работает, а не заставить его работать, например, отключив проверку SSL. В конце концов, я могу без проблем подключиться к указанному URL-адресу через HTTP.


person Ivan    schedule 05.06.2014    source источник


Ответы (1)


Наличие нескольких сертификатов на одном и том же IP-адресе и порте зависит от указания имени сервера.

Ваш сервер поддерживает его, но ваш клиент также должен его поддерживать.

Поддержка SNI на стороне клиента появилась только в Java 7 (см. примечания к выпуску)(*). Я предполагаю, что вы используете Java 6 или ниже, иначе ваш простой пример с URLConnection должен работать из коробки, как этот.

(Вам также могут потребоваться дополнительные настройки, если вы используете другую клиентскую библиотеку, например HTTP-клиент Apache, в зависимости от версии.)

(*) И это было представлено на стороне сервера в Java 8, но это не ваша проблема здесь.

person Bruno    schedule 05.06.2014
comment
Большое спасибо, действительно, я запустил образец с Java 6. В производственной среде я использую Java 7, но с отключенной поддержкой SNI из-за других проблем с SSL (чтобы игнорировать предупреждение unrecognized_name, которое стало исключительным условием в Java 7). Теперь я вижу цену отключения SNI. - person Ivan; 05.06.2014