Сброс соединения SSL
Я пытаюсь подключиться к конечной точке HTTPS в Java. Каждый метод, который я пробовал (более подробно ниже), в конечном итоге генерирует эту трассировку стека:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:168)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:753)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
Я пытался:
- Соединение с библиотеками javax SOAP и новым URL("https://...")
- Соединение с новым URL("https://...").openConnection()
Создание SSL-соединения вручную:
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket socket = (SSLSocket) factory.createSocket("...", 443); Writer out = new OutputStreamWriter(socket.getOutputStream()); // https requires the full URL in the GET line // out.write("GET / HTTP/1.0\r\n"); out.write("\r\n"); out.flush(); // read response BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream())); int c; while ((c = in.read()) != -1) { System.out.write(c); } out.close(); in.close(); socket.close();
Еще несколько деталей:
- Каждый метод, который я пробовал, работал против других серверов SSL, это именно этот сервер (я не вправе обсуждать, какой сервер, это деловой партнер)
- Я могу подключиться к этому серверу как через веб-браузер, так и по поддельному SOAP-запросу с помощью curl; Это что-то специфичное для Java.
Таким образом, кажется довольно ясным, что между Java и HTTPS-сервером существуют некоторые разногласия по поводу того, как должно произойти рукопожатие, что, вероятно, означает, что сервер имеет какую-то странную конфигурацию SSL. Однако у меня нет прямого доступа к серверу, и люди, которые делают это, находятся на полпути по всему миру, поэтому связь немного напрягается из-за очень разных часовых поясов.
Если мои предположения верны, какие могут быть проблемы с SSL? Что может вызвать что-то подобное? Где я могу попросить людей, управляющих сервером, искать проблемы? Когда я делаю запрос с помощью curl, я получаю следующие заголовки конфигурации сервера:
Server: Apache/2.2.9 (Debian) mod_jk/1.2.26 PHP/5.2.6-1+lenny10 with Suhosin-Patch mod_ssl/2.2.9 OpenSSL/0.9.8g mod_perl/2.0.4 Perl/v5.10.0
X-Powered-By: PHP/5.2.6-1+lenny10
X-SOAP-Server: NuSOAP/0.7.3 (1.114)
2 ответа
Это проблема версии SSL. Сервер поддерживает только SSLv3, и Java будет начинаться с версии v2 и будет пытаться выполнить согласование вверх, но не все серверы поддерживают этот тип согласования.
Заставить Java использовать только SSLv3 - единственное решение, о котором я знаю.
Отредактируйте, есть два способа сделать это, о которых я знаю:
Если вы создаете сокет вручную, вы можете установить включенные протоколы
socket.setEnabledProtocols(new String[] { "SSLv3" });
Если вы используете библиотеку более высокого уровня, вам, вероятно, нужно настроить все SSL-запросы на использование только v3, что достигается с помощью
"https.protocols"
системное свойство:java -Dhttps.protocols=SSLv3
Возможно, также попробуйте установить версию HTTP на 1.1 вместо 1.0, так как в более новом стандарте есть некоторые реальные преимущества.