Javax.net.ssl.SSLException: Ошибка чтения: ssl = 0x9524b800: ошибка ввода-вывода во время системного вызова, соединение reset от пользователя - программирование

Javax.net.ssl.SSLException: Ошибка чтения: ssl = 0x9524b800: ошибка ввода-вывода во время системного вызова, соединение reset от пользователя

В течение последних двух недель наши клиенты начинают видеть 100 из этих "SSLException error - Connection reset by peer", и я не могу понять, почему

  • Мы используем Retrofit с okhttp, без специальной конфигурации

    public class OkHttpClientProvider implements IOkHttpClientProvider {
    
        OkHttpClient okHttpClient;
    
        public OkHttpClientProvider() {
            this.okHttpClient = createClient();
        }
    
        public OkHttpClient getOkHttpClient() {
            return this.okHttpClient;
        }
    
        private OkHttpClient createClient() {
            return new OkHttpClient();
        }
    }
    

Вышеуказанный клиентский провайдер является одноэлементным. RestAdapter построен с использованием этого вложенного клиента (мы используем кинжал) -

RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder()
                                        .setConverter(converter)
                                        .setEndpoint(networkRequestDetails.getServerUrl())
                                        .setClient(new OkClient(okHttpClientProvider.getOkHttpClient()))
                                        .setErrorHandler(new NetworkSynchronousErrorHandler(eventBus))
                                        );

Основываясь на решениях переполнения стеллажей, что я обнаружил -

  • Продолжительность сохранения на сервере составляет 180 секунд, OkHttp имеет значение по умолчанию 300 секунд.

  • Сервер возвращает "Соединение: закрыть" в своем заголовке, но клиентский запрос отправляет "Connection: keepAlive"

  • Сервер поддерживает TLS 1.0/1.1/1.2 и использует Open SSL

  • Наши серверы недавно перешли на другой хостинг-провайдер в другой географии, поэтому я не знаю, являются ли эти DNS-сбои или нет.

  • Мы попытались настроить такие вещи, как keepAlive, перенастроить OpenSSL на сервере, но по какой-то причине клиент Android продолжает получать эту ошибку.

  • Это происходит немедленно, без каких-либо задержек, когда вы пытаетесь использовать приложение для публикации чего-либо или для обновления (оно даже не идет в сеть или не задерживается до того, как это исключение произойдет, что будет означать, что соединение уже сломаны). Но пытаюсь это несколько раз как-то "исправляет", и мы добиваемся успеха. Это происходит снова позже

  • Мы аннулировали наши записи DNS на сервере, чтобы узнать, не вызвало ли это то, что вызвало это, но это не помогло

  • В основном это происходит на LTE, но я видел его также на Wifi

Я не хочу отключать поддержку, потому что большинство современных клиентов этого не делают. Также мы используем OkHttp 2.4, и это проблема на почтовых устройствах сэндвич-мороженого, поэтому я надеюсь, что он должен позаботиться об этих проблемах с сетью. Клиент iOS также получает эти исключения, но почти в 100 раз меньше (клиент iOS использует AFNetworking 2.0). Я изо всех сил пытаюсь найти новые вещи, чтобы попробовать на этом этапе, любую помощь/идеи?

Обновление - добавление полной трассировки стека через okhttp

      retrofit.RetrofitError: Read error: ssl=0x9dd07200: I/O error during system call, Connection reset by peer
              at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:390)
              at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
              at java.lang.reflect.Proxy.invoke(Proxy.java:397)
              at $Proxy15.getAccessTokenUsingResourceOwnerPasswordCredentials(Unknown Source)
              at com.company.droid.repository.network.NetworkRepository.getAccessTokenUsingResourceOwnerPasswordCredentials(NetworkRepository.java:76)
              at com.company.droid.ui.login.LoginTask.doInBackground(LoginTask.java:88)
              at com.company.droid.ui.login.LoginTask.doInBackground(LoginTask.java:23)
              at android.os.AsyncTask$2.call(AsyncTask.java:292)
              at java.util.concurrent.FutureTask.run(FutureTask.java:237)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
              at java.lang.Thread.run(Thread.java:818)
       Caused by: javax.net.ssl.SSLException: Read error: ssl=0x9dd07200: I/O error during system call, Connection reset by peer
              at com.android.org.conscrypt.NativeCrypto.SSL_read(Native Method)
              at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:699)
              at okio.Okio$2.read(Okio.java:137)
              at okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
              at okio.RealBufferedSource.indexOf(RealBufferedSource.java:306)
              at okio.RealBufferedSource.indexOf(RealBufferedSource.java:300)
              at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:196)
              at com.squareup.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:191)
              at com.squareup.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:80)
              at com.squareup.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:917)
              at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:793)
              at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:439)
              at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:384)
              at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)
              at com.squareup.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
              at com.squareup.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25)
              at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:73)
              at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:38)
              at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:321)
              at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
              at java.lang.reflect.Proxy.invoke(Proxy.java:397)
              at $Proxy15.getAccessTokenUsingResourceOwnerPasswordCredentials(Unknown Source)
              at com.company.droid.repository.network.NetworkRepository.getAccessTokenUsingResourceOwnerPasswordCredentials(NetworkRepository.java:76)
              at com.company.droid.ui.login.LoginTask.doInBackground(LoginTask.java:88)
              at com.company.droid.ui.login.LoginTask.doInBackground(LoginTask.java:23)
              at android.os.AsyncTask$2.call(AsyncTask.java:292)
              at java.util.concurrent.FutureTask.run(FutureTask.java:237)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
              at java.lang.Thread.run(Thread.java:818)
      ]}
4b9b3361

Ответ 1

Недавно я столкнулся с проблемой при работе над некоторым устаревшим кодом. После googling я обнаружил, что проблема повсюду, но без какой-либо конкретной резолюции. Я работал над различными частями сообщения об исключениях и анализировался ниже.

Анализ:

  • SSLException: исключение произошло с SSL (Secure Socket Layer), который реализован в пакете javax.net.ssl JDK (openJDK/oracleJDK/AndroidSDK)
  • Read error ssl=# I/O error during system call: Ошибка при чтении из сокета Secure. Это произошло при использовании собственных системных библиотек/драйверов. Обратите внимание: все платформы solaris, Windows и т.д. Имеют свои собственные библиотеки сокетов, которые используются SSL. Windows использует библиотеку WINSOCK.
  • Connection reset by peer: это сообщение сообщается системной библиотекой (отчеты Solaris ECONNRESET, отчеты Windows WSAECONNRESET), что сокет, используемый при передаче данных, больше не используется, поскольку существующее соединение было принудительно закрыто удаленный узел. Нужно создать новый безопасный путь между хостом и клиентом.

Причина:

Понимая проблему, я пытаюсь найти причину подключения reset, и я пришел к следующим причинам:

  • Одноранговое приложение на удаленном хосте внезапно остановлено, хост перезагружен, хост или удаленный сетевой интерфейс отключен, или удаленный хост использует жесткое закрытие.
  • Эта ошибка может также возникнуть, если соединение было нарушено из-за активности keep-alive, обнаруживающей сбой при выполнении одной или нескольких операций. Выполняемые операции завершились неудачей с Network dropped connection on reset(On Windows(WSAENETRESET)) и последующими операциями с Connection reset by peer(On Windows(WSAECONNRESET)).
  • Если целевой сервер защищен брандмауэром, что является истинным в большинстве случаев, время жизни (TTL) или тайм-аут, связанные с портом, принудительно закрывают незанятое соединение при заданном тайм-ауте. Это что-то интересное

Разрешение:

  • События на стороне сервера, такие как внезапный останов обслуживания, перезагрузка, отключенный сетевой интерфейс, не могут быть обработаны никакими средствами.
  • На стороне сервера настройте брандмауэр для данного порта с более высоким временем жизни (TTL) или значениями таймаута, например 3600 секунд.
  • Клиенты могут "попробовать" поддерживать активную сеть, чтобы избежать или уменьшить Connection reset by peer.
  • Обычно при запуске сетевого трафика поддерживается соединение, а проблема/исключение часто не видны. Сильный Wifi имеет наименьшие шансы Connection reset by peer.
  • В мобильных сетях 2G, 3G и 4G, где доставка пакетных данных прерывистая и зависит от доступности мобильной сети, она может не reset таймера TTL на стороне сервера и приводит к Connection reset by peer.

Ниже приведены термины, предлагаемые на разных форумах для решения проблемы.

  • ConnectionTimeout: Используется только в момент подключения. Если хост требует времени для подключения, это означает, что клиент ждет подключения.
  • SoTimeout: Тайм-аут сокета. В нем указано максимальное время, в течение которого пакет данных принимается, чтобы считать соединение активным. Если данные не были получены в течение заданного времени, соединение считается заторможенным/сломанным.
  • Linger: В какое время сокет не должен закрываться при отправке данных в очередь, и в сокете вызывается функция закрытия сокета.
  • TcpNoDelay: Вы хотите отключить буфер, который содержит и накапливает TCP-пакеты, и отправлять их после достижения порогового значения? Установка этого значения в true будет пропускать буферизацию TCP, чтобы каждый запрос был отправлен немедленно. Замедление в сети может быть вызвано увеличением сетевого трафика из-за более низкой и более частой передачи пакетов.

Таким образом, ни один из приведенных выше параметров не помогает сохранить сеть в живом состоянии и, следовательно, неэффективен.

Я нашел один параметр, который может помочь решить проблему, которая является этими функциями.

setKeepAlive(true)
setSoKeepalive(HttpParams params, enableKeepalive="true") 

Как я решил проблему?

  • Установите HttpConnectionParams.setSoKeepAlive(params, true)
  • Поймайте SSLException и проверьте сообщение об ошибке для Connection reset by peer
  • Если обнаружено исключение, сохраните процесс загрузки/чтения и создайте новое соединение.
  • Если возможно, возобновите загрузку/чтение, перезапустите загрузку

Я надеюсь, что детали помогут. Счастливое кодирование...

Ответ 2

Если вы используете Nginx и получаете аналогичную проблему, это может помочь:

Сканируйте свой домен на этом sslTesturl и проверьте, разрешено ли подключение для вашей версии устройства.

Если устройства с более низкой версией (например, Android 4.4.2 и т.д.) не могут подключиться из-за поддержки TLS, попробуйте добавить это в свой конфигурационный файл Nginx,

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

Ответ 3

У нас была такая же проблема, начиная с сегодняшнего утра, и она решена... надеюсь, что это поможет...

SSL на IIS 8

  • Все работало хорошо вчера и вчера, наш SSL был обновлен на сайте IIS.
  • При проверке сайта привязки к SSL заметили, что IIS8 имеет новый флажок "Требовать указание имени сервера" , он не был проверен так, чтобы ему предшествовали включите его.
  • Это вызвало проблему.
  • Вернулся в IIS, отключил флажок.... Проблема решена!!!!

Надеюсь, это поможет!!!

Ответ 4

Другая возможная причина для этого сообщения об ошибке заключается в том, что HTTP-метод блокируется сервером или балансировщиком нагрузки.

Кажется, что стандартная практика безопасности блокирует неиспользуемые методы HTTP. Мы столкнулись с этим, потому что HEAD блокировался балансировщиком нагрузки (но, как ни странно, не все серверы с балансировкой нагрузки, из-за которых он проваливался только некоторое время). Я смог проверить, что сам запрос работал нормально, временно изменив его, чтобы использовать метод GET.

Код ошибки в iOS был: Ошибка запроса кода приложения: Ошибка домена = NSURLErrorDomain Code = -1005 "Сетевое соединение было потеряно".