Как разрешаются имена серверов сертификатов SSL / Могу ли я добавить альтернативные имена, используя keytool? - PullRequest
71 голосов
/ 09 декабря 2011

Они могут быть сформулированы как отдельные вопросы для ясности, но все они связаны с одной и той же проблемой.

Как разрешаются имена серверов сертификатов SSL?

Почему браузеры, похоже, используютПоле CN сертификата, но механизм Java, похоже, рассматривает только «альтернативные имена субъекта»?

Можно ли добавить альтернативные имена в сертификат SSL с помощью keytool?Если нет, то лучше ли использовать openSSL?

Немного предыстории: Мне нужен главный сервер для связи с несколькими серверами с использованием HTTPS.Очевидно, что мы не хотим покупать SSL-сертификаты для каждого сервера (их может быть много), поэтому я хочу использовать самозаверяющие сертификаты (я использовал keytool для их генерации).После того, как я добавил сертификаты как доверенные в ОС, браузеры (IE и Chrome) с радостью принимают соединение как доверенное.Тем не менее, даже после добавления сертификатов в серверы Java, Java по-прежнему не принимает соединение как доверенное и выдает следующее исключение:

Причина: java.security.cert.CertificateException: Нет альтернативы субъектаимена, присутствующие в sun.security.util.HostnameChecker.matchIP (HostnameChecker.java:142) в sun.security.util.HostnameChecker.match (HostnameChecker.java:75) в com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity (X509T rustManagerImpl.java:264) в com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted (X509TrustManagerImpl.java:250) в com.sun.net.ssl.internal.ssverSlientClien tHandshaker.java:1185) ... еще 14

Я обнаружил, что могу заставить Java доверять сертификату, реализующему мой собственный HostNameVerifier, который я скопировал отсюда: com.sun.jbi.internal.security.https.DefaultHostnameVerifier просто для проверки (кстати, имя хоста, переданное в качестве аргумента HostnameVerifierправильно, поэтому я думаю, что это должно было быть принято).

Я использовал поле сертификата CN в качестве имени хоста (обычно это IP-адрес).

Может кто-нибудь сказать мне, если яделать что-то не так и указать мне в правильном направлении?

1 Ответ

91 голосов
/ 09 декабря 2011

Как должна выполняться проверка имени хоста, определено в RFC 6125 , который является довольно новым и обобщает практику для всех протоколов, и заменяет RFC 2818 , который был специфичен для HTTPS.,(Я даже не уверен, что Java 7 использует RFC 6125, что может быть слишком новым для этого.)

С RFC 2818 (Раздел 3.1) :

Если присутствует расширение subjectAltName типа dNSName, оно ДОЛЖНО использоваться в качестве идентификатора.В противном случае ДОЛЖНО использоваться (наиболее определенное) поле общего имени в поле «Тема» сертификата.Хотя использование общего имени является существующей практикой, оно устарело, и сертификационным органам рекомендуется вместо этого использовать dNSName.

[...]

В некоторых случаях указывается URIкак IP-адрес, а не имя хоста.В этом случае iPAddress subjectAltName должно присутствовать в сертификате и должно точно соответствовать IP-адресу в URI.

По сути, конкретная проблема возникает из-за того, что вы используете IP-адресав вашем CN, а не имя хоста.Некоторые браузеры могут работать, потому что не все инструменты строго следуют этой спецификации, в частности потому, что «наиболее специфичный» в RFC 2818 не определен четко (см. Обсуждения в RFC 6215).

Если вы используете keytool, с Java 7, keytool имеет возможность включить альтернативное имя субъекта (см. Таблицу в документации для -ext): вы можете использовать -ext san=dns:www.example.com или -ext san=ip:10.0.0.1.

РЕДАКТИРОВАТЬ:

Вы можете запросить SAN в OpenSSL, изменив openssl.cnf (он выберет копию в текущем каталоге, если вы не хотите редактировать глобальныйКонфигурация, насколько я помню, или вы можете выбрать явное местоположение, используя переменную окружения OPENSSL_CONF.

Установите следующие параметры (сначала найдите соответствующие разделы в скобках):

[req]
req_extensions = v3_req

[ v3_req ]
subjectAltName=IP:10.0.0.1
# or subjectAltName=DNS:www.example.com

Есть также хороший прием для использования переменной окружения (вместо того, чтобы фиксировать ее в файле конфигурации): http://www.crsr.net/Notes/SSL.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...