以下是我所知道的:
- 我使用v24支持库,即我的compileSdkVersion为24。
- 我使用Volley v1.0.0。
- 我尝试过TLSSocketFactory,但没有改变任何东西。它似乎大多数情况下用于防止旧的SDK版本使用SSL3。
- 我尝试增加了timeout,但没有改变任何东西。
- 我尝试直接使用HttpURLConnection,但除了堆栈跟踪(它没有volley引用,但是其他方面相同)之外,没有改变任何东西。
没有TLSSocketFactory,请求通过使用Volley.newRequestQueue(context)
实例化的裸请求队列进行。
这是我在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
由于它显示“SSLV3_ALERT_HANDSHAKE_FAILURE”,我只能假设它因某种原因尝试使用SSLv3进行连接并失败,但这对我来说毫无意义。可能是密码问题,但我如何知道它正在尝试使用什么?我宁愿不在服务器上启用密码,而是进行连接尝试并重复。
我的nginx网站使用Let's Encrypt证书,并具有以下配置:
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;
我有一个脚本用来测试这些密码,并且它在服务器网络外的Wheezy VPS上确认了这些密码:
测试ECDHE-RSA-AES256-GCM-SHA384...是的 测试ECDHE-ECDSA-AES256-GCM-SHA384...否(sslv3 alert handshake failure) 测试ECDHE-RSA-AES256-SHA384...否(sslv3 alert handshake failure) 测试ECDHE-ECDSA-AES256-SHA384...否(sslv3 alert handshake failure) 测试ECDHE-RSA-AES256-SHA...否(sslv3 alert handshake failure) 测试ECDHE-ECDSA-AES256-SHA...否(sslv3 alert handshake failure) 测试SRP-DSS-AES-256-CBC-SHA...否(sslv3 alert handshake failure) 测试SRP-RSA-AES-256-CBC-SHA...否(sslv3 alert handshake failure) 测试DHE-DSS-AES256-GCM-SHA384...否(sslv3 alert handshake failure) 测试DHE-RSA-AES256-GCM-SHA384...否(sslv3 alert handshake failure) 测试DHE-RSA-AES256-SHA256...否(sslv3 alert handshake failure) 测试DHE-DSS-AES256-SHA256...否(sslv3 alert handshake failure) 测试DHE-RSA-AES256-SHA...否(sslv3 alert handshake failure) 测试DHE-DSS-AES256-SHA...否(sslv3 alert handshake failure) 测试DHE-RSA-CAMELLIA256-SHA...否(sslv3 alert handshake failure) 测试DHE-DSS-CAMELLIA256-SHA...否(sslv3 alert handshake failure) 测试AECDH-AES256-SHA...否(sslv3 alert handshake failure) 测试SRP-AES-256-CBC-SHA...否(sslv3 alert handshake failure) 测试ADH-AES256-GCM-SHA384...否(sslv3 alert handshake failure) 测试ADH-AES256-SHA256...否(sslv3 alert handshake failure) 测试ADH-AES256-SHA...否(sslv3 alert handshake failure) 测试ADH-CAMELLIA256-SHA...否(sslv3 alert handshake failure) 测试ECDH-RSA-AES256-GCM-SHA384...否(sslv3 alert handshake failure) 测试ECDH-ECDSA-AES256-GCM-SHA384...否(sslv3 alert handshake failure) 测试ECDH-RSA-AES256-SHA384...否(sslv3 alert handshake failure) 测试ECDH-ECDSA-AES256-SHA384...否(sslv3 alert handshake failure) 测试ECDH-RSA-AES256-SHA...否(sslv3 alert handshake failure) 测试ECDH-ECDSA-AES256-SHA...否(sslv3 alert handshake failure) 测试AES256-GCM-SHA384...否(sslv3 alert handshake failure) 测试AES256-SHA256...否(sslv3 alert handshake failure) 测试AES256-SHA...否(sslv3 alert handshake failure) 测试CAMELLIA256-SHA...否(sslv3 alert handshake failure) 测试PSK-AES256-CBC-SHA...否(没有可用的密码) 测试ECDHE-RSA-DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试ECDHE-ECDSA-DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试SRP-DSS-3DES-EDE-CBC-SHA...否(sslv3 alert handshake failure) 测试SRP-RSA-3DES-EDE-CBC-SHA...否(sslv3 alert handshake failure) 测试EDH-RSA-DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试EDH-DSS-DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试AECDH-DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试SRP-3DES-EDE-CBC-SHA...否(sslv3 alert handshake failure) 测试ADH-DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试ECDH-RSA-DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试ECDH-ECDSA-DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试DES-CBC3-SHA...否(sslv3 alert handshake failure) 测试PSK-3DES-EDE-CBC-SHA...否(没有可用的密码) 测试ECDHE-RSA-AES128-GCM-SHA256...是的 测试ECDHE-我可以在模拟器的浏览器中打开服务器URL并获得完美的JSON响应,因此我知道系统本身是有能力的。所以问题是,为什么我不能在Android 7上连接?更新:我使用tcpdump和wireshark捕获了数据包,并启用了ClientHello中的密码,所以这不应该是个问题。
密码套件(18个套件)
密码套件:未知(0xcca9) 密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(0xc02b) 密码套件:TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xc02c) 密码套件:未知(0xcca8) 密码套件:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xc02f) 密码套件:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xc030) 密码套件:TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(0x009e) 密码套件:TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(0x009f) 密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(0xc009) 密码套件:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(0xc00a) 密码套件:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(0xc013) 密码套件:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(0xc014) 密码套件:TLS_DHE_RSA_WITH_AES_128_CBC_SHA(0x0033) 密码套件:TLS_DHE_RSA_WITH_AES_256_CBC_SHA(0x0039) 密码套件:TLS_RSA_WITH_AES_128_GCM_SHA256(0x009c) 密码套件:TLS_RSA_WITH_AES_256_GCM_SHA384(0x009d) 密码套件:TLS_RSA_WITH_AES_128_CBC_SHA(0x002f) 密码套件:TLS_RSA_WITH_AES_256_CBC_SHA(0x0035)
如您所见,
0xc02f
和0xc030
是匹配的,但下一个TLSv1.2数据包显示:Alert (21),Handshake Failure (40)
。
更新2:
这些是Android 5.1中ClientHello中的曲线:
椭圆曲线(25条曲线)椭圆曲线:sect571r1(0x000e) 椭圆曲线:sect571k1(0x000d) 椭圆曲线:secp521r1(0x0019) 椭圆曲线:sect409k1(0x000b) 椭圆曲线:sect409r1(0x000c) 椭圆曲线:secp384r1(0x0018) 椭圆曲线:sect283k1(0x0009) 椭圆曲线:sect283r1(0x000a) 椭圆曲线:secp256k1(0x0016) 椭圆曲线:secp256r1(0x0017) 椭圆曲线:sect239k1(0x0008) 椭圆曲线:sect233k1(0x0006) 椭圆曲线:sect233r1(0x0007) 椭圆曲线:secp224k1(0x0014) 椭圆曲线:secp224r1(0x0015) 椭圆曲线:sect193r1(0x0004) 椭圆曲线:sect193r2(0x0005) 椭圆曲线:secp192k1(0x0012) 椭圆曲线:secp192r1(0x0013) 椭圆曲线:sect163k1(0x0001) 椭圆曲线:sect163r1(0x0002) 椭圆曲线:sect163r2(0x0003) 椭圆曲线:secp160k1(0x000f) 椭圆曲线:secp160r1(0x0010) 椭圆曲线:secp160r2(0x0011)
在ServerHello中返回了
secp384r1 (0x0018)
。这是来自Android 7的信息:
椭圆曲线(1个曲线)导致握手失败。通过删除secp384r1或将其替换为默认值(prime256v1)更改nginx配置可以使其正常工作。所以问题仍然存在:我能否添加椭圆曲线?
椭圆曲线:secp256r1(0x0017)
使用模拟器和Android 7.0设备(General Mobile 4G)时,捕获的数据相同。
更新3:
小更新,但值得一提:我在使用Android 7.1.1的模拟器上使其正常工作了!它显示以下数据(再次使用tcpdump获取并使用wireshark查看):
椭圆曲线(3个曲线)它显示相同的18个密码套件。
椭圆曲线:secp256r1(0x0017) 椭圆曲线:secp384r1(0x0018) 椭圆曲线:secp512r1(0x0019)