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

Получение SSLHandshakeException: handshake_failure, несмотря на то, что мой клиент игнорирует все сертификаты

У меня есть Java-программа, которая подключается к веб-серверу с использованием SSL/TLS и отправляет различные HTTP-запросы по этому соединению. Сервер является localhost и использует самозаверяющий сертификат, но мой код использует пользовательские TrustManager и игнорирует недопустимые сертификаты. Он отлично работал до сих пор.

Единственное отличие на сервере заключается в том, что он использовался для запуска jboss 6 и теперь запускается jboss 7. Я не уверен, что это проблема конфигурации или проблема с моим кодом, но я получаю те же ошибки, если я пытаюсь подключиться с помощью других Java-программ, таких как WebScarab или ZAP.

В любом случае, есть ли что-нибудь, что я могу сделать для моего кода, чтобы обойти эту проблему? Вот полная ошибка:

Received fatal alert: handshake_failure
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source)

Вот отладочные сообщения перед сбоем:

main, WRITE: TLSv1 Handshake, length = 75
main, WRITE: SSLv2 client hello message, length = 101
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT: fatal, handshake_failure
4b9b3361

Ответ 1

Итак, я нашел проблему. На Java может быть ошибка, но клиент, похоже, инициирует TLSv1 Handshake, но затем отправляет приветственное сообщение клиента SSLv2, после чего сервер отклоняет соединение.

Это происходит, даже если вы создаете свой SSLContext с экземпляром TLS:

SSLContext sslContext = SSLContext.getInstance("TLS");

Решение состоит в том, чтобы установить системное свойство до того, как будут сделаны попытки подключения:

System.setProperty("https.protocols", "TLSv1");

Есть, вероятно, другие решения, но это работало для меня.

Ответ 2

Информация, которую вы предоставляете, очень мало, а также трассировка стека.
Я сделаю это предположение. Я подозреваю, что на новом сервере протокол TLSv1, в то время как ваши клиенты пытаются подключиться к SSLv3 (или меньше), и в результате квитирование не выполняется.

Измените клиентов на использование более высокой версии TLS или
Сделайте свой веб-сервер также поддержкой SSLv3. Я знаю, как это сделать в Tomcat, но не в JBoss.

Если это не работает, обновите сообщение с дополнительной информацией (и полной трассировкой стека).
Вы должны включить ssl debug info -Djavax.net.debug=ssl

Ответ 3

Было ли это разрешено?

У меня была одна и та же проблема, по сути, я получал исключение рукопожатия сразу после clientHello. Итак, цепочка событий была

  • Я бы представил свой сертификат на сервер
  • Сервер будет немедленно реагировать на отказ от рукопожатия. (Я бы даже не получил сервер Hello).

В конце концов я обнаружил, что серверу требуется более сильный алгоритм шифрования/дешифрования, чем тот, который я поставлял на начальной стадии установления связи (то есть клиент и сервер не могли договориться о взаимном алгоритме шифрования для использования для связи ssl).

Мне нужно установить Unlimited Java JCE (политика расширения криптографии Java). Существуют правила экспорта по использованию этого, поэтому, если вы отправляете свой код за границей, что может иметь последствия... все же это то, что решило мою проблему.

В этой ссылке объясняется, как установить обновленные политики http://suhothayan.blogspot.com/2012/05/how-to-install-java-cryptography.html

Это была отличная ссылка, которая помогла мне понять, что именно происходит https://support.f5.com/kb/en-us/solutions/public/15000/200/sol15292.html#id

Это может быть или не быть проблемой, но когда рукопожатие выходит из строя сразу после клиента Hello, похоже, что клиент и сервер не могут что-то согласовать (во многих случаях его алгоритмы шифрования, которые они будут взаимно общаться).

Ответ 4

Вы видите эту ошибку, скорее всего, потому, что хранилище ключей, доступное вашему JBoss 6, недоступно для вашего экземпляра JBoss 7.

Я бы порекомендовал следующее.

Ваш самоподписанный серверный сертификат должен быть импортирован в доверительный магазин

keytool -import -alias gridserver -file server.crt -storepass $YOUR_PASSWORD_HERE -keystore server.keystore

Добавьте следующие свойства в run.conf

-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=server.keystore
-Djavax.net.debug=ssl # very verbose debug. Turn this off after everything looks good.
-Djavax.net.ssl.keyStorePassword=$YOUR_PASSWORD_HERE
-Djavax.net.ssl.trustStorePassword=$YOUR_PASSWORD_HERE

Ответ 5

Трассировка стека от вашего клиентского кода и вашего клиента "Получено [a] фатальное предупреждение". Другими словами, ошибка SSL произошла в Jboss, а не в вашем клиенте.

Пользовательские TrustManager клиентской стороны не имеют к этому никакого отношения. Моя дикая догадка заключается в том, что ваш новый Jboss 7 настроен на то, чтобы потребовать сертификат клиента, а ваш клиент не представил его.

Чтобы отладить ваше SSL-соединение, используйте openssl и попробуйте следующее:

openssl s_client -connect jboss.server.com:443

или это сервер SSLV3

openssl s_client -connect jboss.server.com:443 -ssl3

Это должно печатать много интересной информации.

Ответ 6

Я думаю, что это связано с ошибкой Java 7. Трудно быть уверенным без каких-либо подробностей.

Ответ 7

Для меня решение было: System.setProperty("https.protocols", "TLSv1.1,TLSv1.2");