I'm working on an app for which the (power)users have to set up their own server (i.e. nginx) to run the backend application. The corresponding domain needs to be configured in the app so it can connect. I've been testing primarily on my own phone (sony z3c) and started developing for 5.1. Later I received an update for 6.0 but still maintained a working 5.1 inside the emulator. Not too long ago, I started to work on an AVD with an image for 7.0 and to my suprise it won't connect to my server, telling me the ssl handshake failed. My nginx configuration is pretty strict, but it works for both 5.1 and 6.0, so .... ?!
Here is what I know:
- I use v24 for support libs, i.e. my compileSdkVersion is 24.
- I use Volley v1.0.0.
- I've tried the TLSSocketFactory, but it doesn't change anything. This seems to be used most of the times to prevent SSL3 use for older SDK versions anyway.
- I've tried increasing the timeout, but it doesn't change anything.
- I've tried using HttpURLConnection directly, but it doesn't change anything apart from the stack trace (it's without the volley references, but identical otherwise).
Without the TLSSocketFactory the request are made through a bare request queue, instantiated with Volley.newRequestQueue(context)
.
This is what I see in android studio:
W/System.err: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Connection closed by peer W/System.err: at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:151) W/System.err: at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112) W/System.err: Caused by: javax.net.ssl.SSLHandshakeException: Connection closed by peer W/System.err: at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357) W/System.err: at com.android.okhttp.Connection.connectTls(Connection.java:235) W/System.err: at com.android.okhttp.Connection.connectSocket(Connection.java:199) W/System.err: at com.android.okhttp.Connection.connect(Connection.java:172) W/System.err: at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:367) W/System.err: at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:130) W/System.err: at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:329) W/System.err: at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:246) W/System.err: at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457) W/System.err: at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:126) W/System.err: at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:257) W/System.err: at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218) W/System.err: at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java) W/System.err: at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:264) W/System.err: at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:234) W/System.err: at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:107) W/System.err: at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96) W/System.err: ... 1 more W/System.err: Suppressed: javax.net.ssl.SSLHandshakeException: Handshake failed W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429) W/System.err: ... 17 more W/System.err: Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x7ffef3748040: Failure in SSL library, usually a protocol error W/System.err: error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/s3_pkt.c:610 0x7ffeda1d2240:0x00000001) W/System.err: error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/s3_clnt.c:764 0x7ffee9d2b70a:0x00000000) W/System.err: at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357) W/System.err: ... 17 more
Since it says SSLV3_ALERT_HANDSHAKE_FAILURE
I can only assume it for some reason tries to connect using SSLv3 and fails, but this doesn't make any sense to me whatsoever. It might be a cipher-issue, but how can I tell what it is trying to use ? I would rather not enable a ciphers on the server, make a connection attempt and repeat.
My nginx site uses a let's encrypt certificate and has the following configuration:
ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/ssl/certs/lets-encrypt-x1-cross-signed.pem; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:!aNULL; ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_ecdh_curve secp384r1; ssl_prefer_server_ciphers on; ssl_protocols TLSv1.2;
To test these ciphers I've a script and it confirms these ciphers (run on a wheezy vps outside the server's network):
Testing ECDHE-RSA-AES256-GCM-SHA384...YES Testing ECDHE-ECDSA-AES256-GCM-SHA384...NO (sslv3 alert handshake failure) Testing ECDHE-RSA-AES256-SHA384...NO (sslv3 alert handshake failure) Testing ECDHE-ECDSA-AES256-SHA384...NO (sslv3 alert handshake failure) Testing ECDHE-RSA-AES256-SHA...NO (sslv3 alert handshake failure) Testing ECDHE-ECDSA-AES256-SHA...NO (sslv3 alert handshake failure) Testing SRP-DSS-AES-256-CBC-SHA...NO (sslv3 alert handshake failure) Testing SRP-RSA-AES-256-CBC-SHA...NO (sslv3 alert handshake failure) Testing DHE-DSS-AES256-GCM-SHA384...NO (sslv3 alert handshake failure) Testing DHE-RSA-AES256-GCM-SHA384...NO (sslv3 alert handshake failure) Testing DHE-RSA-AES256-SHA256...NO (sslv3 alert handshake failure) Testing DHE-DSS-AES256-SHA256...NO (sslv3 alert handshake failure) Testing DHE-RSA-AES256-SHA...NO (sslv3 alert handshake failure) Testing DHE-DSS-AES256-SHA...NO (sslv3 alert handshake failure) Testing DHE-RSA-CAMELLIA256-SHA...NO (sslv3 alert handshake failure) Testing DHE-DSS-CAMELLIA256-SHA...NO (sslv3 alert handshake failure) Testing AECDH-AES256-SHA...NO (sslv3 alert handshake failure) Testing SRP-AES-256-CBC-SHA...NO (sslv3 alert handshake failure) Testing ADH-AES256-GCM-SHA384...NO (sslv3 alert handshake failure) Testing ADH-AES256-SHA256...NO (sslv3 alert handshake failure) Testing ADH-AES256-SHA...NO (sslv3 alert handshake failure) Testing ADH-CAMELLIA256-SHA...NO (sslv3 alert handshake failure) Testing ECDH-RSA-AES256-GCM-SHA384...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-AES256-GCM-SHA384...NO (sslv3 alert handshake failure) Testing ECDH-RSA-AES256-SHA384...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-AES256-SHA384...NO (sslv3 alert handshake failure) Testing ECDH-RSA-AES256-SHA...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-AES256-SHA...NO (sslv3 alert handshake failure) Testing AES256-GCM-SHA384...NO (sslv3 alert handshake failure) Testing AES256-SHA256...NO (sslv3 alert handshake failure) Testing AES256-SHA...NO (sslv3 alert handshake failure) Testing CAMELLIA256-SHA...NO (sslv3 alert handshake failure) Testing PSK-AES256-CBC-SHA...NO (no ciphers available) Testing ECDHE-RSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing ECDHE-ECDSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing SRP-DSS-3DES-EDE-CBC-SHA...NO (sslv3 alert handshake failure) Testing SRP-RSA-3DES-EDE-CBC-SHA...NO (sslv3 alert handshake failure) Testing EDH-RSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing EDH-DSS-DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing AECDH-DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing SRP-3DES-EDE-CBC-SHA...NO (sslv3 alert handshake failure) Testing ADH-DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing ECDH-RSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing DES-CBC3-SHA...NO (sslv3 alert handshake failure) Testing PSK-3DES-EDE-CBC-SHA...NO (no ciphers available) Testing ECDHE-RSA-AES128-GCM-SHA256...YES Testing ECDHE-ECDSA-AES128-GCM-SHA256...NO (sslv3 alert handshake failure) Testing ECDHE-RSA-AES128-SHA256...NO (sslv3 alert handshake failure) Testing ECDHE-ECDSA-AES128-SHA256...NO (sslv3 alert handshake failure) Testing ECDHE-RSA-AES128-SHA...NO (sslv3 alert handshake failure) Testing ECDHE-ECDSA-AES128-SHA...NO (sslv3 alert handshake failure) Testing SRP-DSS-AES-128-CBC-SHA...NO (sslv3 alert handshake failure) Testing SRP-RSA-AES-128-CBC-SHA...NO (sslv3 alert handshake failure) Testing DHE-DSS-AES128-GCM-SHA256...NO (sslv3 alert handshake failure) Testing DHE-RSA-AES128-GCM-SHA256...NO (sslv3 alert handshake failure) Testing DHE-RSA-AES128-SHA256...NO (sslv3 alert handshake failure) Testing DHE-DSS-AES128-SHA256...NO (sslv3 alert handshake failure) Testing DHE-RSA-AES128-SHA...NO (sslv3 alert handshake failure) Testing DHE-DSS-AES128-SHA...NO (sslv3 alert handshake failure) Testing DHE-RSA-SEED-SHA...NO (sslv3 alert handshake failure) Testing DHE-DSS-SEED-SHA...NO (sslv3 alert handshake failure) Testing DHE-RSA-CAMELLIA128-SHA...NO (sslv3 alert handshake failure) Testing DHE-DSS-CAMELLIA128-SHA...NO (sslv3 alert handshake failure) Testing AECDH-AES128-SHA...NO (sslv3 alert handshake failure) Testing SRP-AES-128-CBC-SHA...NO (sslv3 alert handshake failure) Testing ADH-AES128-GCM-SHA256...NO (sslv3 alert handshake failure) Testing ADH-AES128-SHA256...NO (sslv3 alert handshake failure) Testing ADH-AES128-SHA...NO (sslv3 alert handshake failure) Testing ADH-SEED-SHA...NO (sslv3 alert handshake failure) Testing ADH-CAMELLIA128-SHA...NO (sslv3 alert handshake failure) Testing ECDH-RSA-AES128-GCM-SHA256...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-AES128-GCM-SHA256...NO (sslv3 alert handshake failure) Testing ECDH-RSA-AES128-SHA256...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-AES128-SHA256...NO (sslv3 alert handshake failure) Testing ECDH-RSA-AES128-SHA...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-AES128-SHA...NO (sslv3 alert handshake failure) Testing AES128-GCM-SHA256...NO (sslv3 alert handshake failure) Testing AES128-SHA256...NO (sslv3 alert handshake failure) Testing AES128-SHA...NO (sslv3 alert handshake failure) Testing SEED-SHA...NO (sslv3 alert handshake failure) Testing CAMELLIA128-SHA...NO (sslv3 alert handshake failure) Testing PSK-AES128-CBC-SHA...NO (no ciphers available) Testing ECDHE-RSA-RC4-SHA...NO (sslv3 alert handshake failure) Testing ECDHE-ECDSA-RC4-SHA...NO (sslv3 alert handshake failure) Testing AECDH-RC4-SHA...NO (sslv3 alert handshake failure) Testing ADH-RC4-MD5...NO (sslv3 alert handshake failure) Testing ECDH-RSA-RC4-SHA...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-RC4-SHA...NO (sslv3 alert handshake failure) Testing RC4-SHA...NO (sslv3 alert handshake failure) Testing RC4-MD5...NO (sslv3 alert handshake failure) Testing PSK-RC4-SHA...NO (no ciphers available) Testing EDH-RSA-DES-CBC-SHA...NO (sslv3 alert handshake failure) Testing EDH-DSS-DES-CBC-SHA...NO (sslv3 alert handshake failure) Testing ADH-DES-CBC-SHA...NO (sslv3 alert handshake failure) Testing DES-CBC-SHA...NO (sslv3 alert handshake failure) Testing EXP-EDH-RSA-DES-CBC-SHA...NO (sslv3 alert handshake failure) Testing EXP-EDH-DSS-DES-CBC-SHA...NO (sslv3 alert handshake failure) Testing EXP-ADH-DES-CBC-SHA...NO (sslv3 alert handshake failure) Testing EXP-DES-CBC-SHA...NO (sslv3 alert handshake failure) Testing EXP-RC2-CBC-MD5...NO (sslv3 alert handshake failure) Testing EXP-ADH-RC4-MD5...NO (sslv3 alert handshake failure) Testing EXP-RC4-MD5...NO (sslv3 alert handshake failure) Testing ECDHE-RSA-NULL-SHA...NO (sslv3 alert handshake failure) Testing ECDHE-ECDSA-NULL-SHA...NO (sslv3 alert handshake failure) Testing AECDH-NULL-SHA...NO (sslv3 alert handshake failure) Testing ECDH-RSA-NULL-SHA...NO (sslv3 alert handshake failure) Testing ECDH-ECDSA-NULL-SHA...NO (sslv3 alert handshake failure) Testing NULL-SHA256...NO (sslv3 alert handshake failure) Testing NULL-SHA...NO (sslv3 alert handshake failure) Testing NULL-MD5...NO (sslv3 alert handshake failure
I can open the server-url in the emulator's browser and get a perfect json response so I know the system itself is capable.
So the question is, why can't I connect on Android 7 ?
Update:
I've looked at a captured packet using tcpdump and wireshark and the enabled ciphers are in the ClientHello, so that should not be a problem.
Cipher Suites (18 suites) Cipher Suite: Unknown (0xcca9) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c) Cipher Suite: Unknown (0xcca8) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e) Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014) Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033) Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039) Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c) Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d) Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f) Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
As you can see 0xc02f
and 0xc030
match, but the next TLSv1.2 packet says: Alert (21), Handshake Failure (40)
.
Update 2:
These are the curves from Android 5.1 in the ClientHello:
Elliptic curves (25 curves) Elliptic curve: sect571r1 (0x000e) Elliptic curve: sect571k1 (0x000d) Elliptic curve: secp521r1 (0x0019) Elliptic curve: sect409k1 (0x000b) Elliptic curve: sect409r1 (0x000c) Elliptic curve: secp384r1 (0x0018) Elliptic curve: sect283k1 (0x0009) Elliptic curve: sect283r1 (0x000a) Elliptic curve: secp256k1 (0x0016) Elliptic curve: secp256r1 (0x0017) Elliptic curve: sect239k1 (0x0008) Elliptic curve: sect233k1 (0x0006) Elliptic curve: sect233r1 (0x0007) Elliptic curve: secp224k1 (0x0014) Elliptic curve: secp224r1 (0x0015) Elliptic curve: sect193r1 (0x0004) Elliptic curve: sect193r2 (0x0005) Elliptic curve: secp192k1 (0x0012) Elliptic curve: secp192r1 (0x0013) Elliptic curve: sect163k1 (0x0001) Elliptic curve: sect163r1 (0x0002) Elliptic curve: sect163r2 (0x0003) Elliptic curve: secp160k1 (0x000f) Elliptic curve: secp160r1 (0x0010) Elliptic curve: secp160r2 (0x0011)
In the ServerHello secp384r1 (0x0018)
is returned.
And this is from Android 7:
Elliptic curves (1 curve) Elliptic curve: secp256r1 (0x0017)
Resulting in the Handshake Failure.
Changing the nginx configuration by removing secp384r1 or replacing it with the default (prime256v1) does get it to work. So I guess the question remains: am I able to add elliptic curves ?
The captured data is the same when using the emulator as when using an Android 7.0 device (General Mobile 4G).
Update 3:
Small update, but worth mentioning: I got it to work in the emulator using Android 7.1.1 (!). It shows the following data (again, grabbed using tcpdump and viewed using wireshark):
Elliptic curves (3 curves) Elliptic curve: secp256r1 (0x0017) Elliptic curve: secp384r1 (0x0018) Elliptic curve: secp512r1 (0x0019)
It shows the same 18 Cipher Suites.