Ошибка подключения Android 4.4 Volley к nginx

У меня возникли проблемы с подключением устройств Android с API < 21 к моему серверу nginx. Все результаты здесь получены с эмулированного устройства API 19.

Я пытался использовать VolleyToolboxExtension и NoSSLv3Factory, как было предложено в другом месте, но все еще получал серьезные ошибки, как показано ниже, за исключением того, что вместо sslv3 был tlsv1.

Мой текущий подход заключается в том, чтобы позволить старым версиям Android подключаться через SSLv3. Но это по-прежнему вызывает ошибки, как показано ниже.

Примечание. Я знаю, что SSLv3 не работает, но я использую другой сертификат и не отправляю ничего, связанного с безопасностью. Вся идея состоит в том, чтобы провести опрос, чтобы я мог решить, хочу ли я отказаться от поддержки старых версий Android SDK.

error during request: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb8a45890: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x8d959990:0x00000000)

Я использую следующий код для подключения:

final String url;
if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ){
    url = "https://abc.badssl.example.com";
} else {
    url = "https://abc.example.com";
}
final JSONObject jsonBody;
try {
    jsonBody = new JSONObject("{\"api\":" + Build.VERSION.SDK_INT + "}");
    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url,
            jsonBody,
            response -> {
                try {
                    Log.d(TAG, "Response is: " + response.getInt("api"));
                } catch (JSONException e) {
                    Log.wtf(TAG, e);
                }
                wasRunning = true;
                loading.postValue(false);
            }, e -> {
        Log.e(TAG, "error during request: " + e.getMessage());
        error.postValue(true);
    });
    jsonObjectRequest.setShouldCache(false);
    jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 5, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    queue.getCache().clear();

    queue.add(jsonObjectRequest);
} catch (JSONException e) {
    Log.wtf(TAG, e);
}

А это моя конфигурация nginx для abc.badssl.example.com с использованием другого сертификата:

listen  443 ssl;
server_name abc.badssl.example.com;

ssl on;
ssl_protocols SSLv3;
ssl_dhparam /etc/nginx/ssl/dhparams.pem;

#worker shared ssl cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_ciphers 'ECDHE-ECDSA-AES256-SHA:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:!DHE-RSA-AES256-GCM-SHA384:!DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:!DHE-RSA-AES256-SHA256:!DHE-RSA-AES128-SHA256:!DHE-RSA-AES256-SHA:!DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:!DHE-RSA-DES-CBC-SHA:!DHE-RSA-CAMELLIA256-SHA:!DHE-RSA-CAMELLIA128-SHA:!DHE-DSS-CBC-SHA:!DHE-RSA-DES-CBC3-SHA';

fastcgi_param HTTPS on;

Я думаю, что неправильно понял параметры nginx, но я не могу найти многого, поскольку 99% касаются либо отключения SSLv3, либо ничего в отношении текущей версии залпа (мертвые ссылки в SO).

0
0
360
1

Ответы 1

Итак, решение оказывается немного другим.

Прежде всего: SSLv3 отключен в debian и ubuntu в текущих версиях OpenSSL по очевидным причинам. Интересно, что это не вызывает никаких ошибок или чего-то подобного, протоколы конфигурации nginx просто игнорируются?! Я все еще могу подключиться к серверу через TLS1.X, даже если в конфигурации только SSLv3. nmap сообщает то же самое.

На Android < 21 (как сказано в других ответах) TLS существует, но SSLv3 предпочтительнее или даже принудительно.

Самым простым решением для получения работающего HTTPsUrlConnection на старых устройствах является использование NetCipher.

построить.градле:

implementation "info.guardianproject.netcipher:netcipher:2.0.0-alpha1"

А затем используйте Netcipher для создания HTTP-соединения.
Вы также можете использовать это вместе с залпом, используя пользовательский HttpStack. Обратите внимание, что StrongBuilders от Netcipher не предназначены для создания простых https-соединений! Они предназначены только для подключения через сеть Tor. Так что не обманывайте себя, думая, что вы можете просто использовать их, чтобы избежать HttpStack.

Обработчик запросов без залпа, используя сырой HttpsUrlConnection, урезанный:

final String url = "https://asd.example.com";
runner = new Thread(() -> {

    final JSONObject jsonBody;
    try {
        HttpsURLConnection con = NetCipher.getHttpsURLConnection(new URL(url));
        con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        con.setRequestProperty("Accept", "application/json");
        con.setDoOutput(true);
        con.setDoInput(true);

        jsonBody = new JSONObject("{\"api\":" + Build.VERSION.SDK_INT + "}");

        OutputStream wr = con.getOutputStream();
        wr.write(jsonBody.toString().getBytes("UTF-8"));
        wr.flush();
        wr.close();

        InputStream in = new BufferedInputStream(con.getInputStream());
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = in.read(buffer)) != -1) {
            result.write(buffer, 0, length);
        }

        JSONObject jsonObject = new JSONObject(result.toString("UTF-8"));
        in.close();


        con.disconnect();
        Log.d(TAG,"received json: "+jsonObject.toString());
        loading.postValue(false);
    } catch (
            Exception e) {
        Log.wtf(TAG, e);
    }
});
runner.start();

Другие вопросы по теме