HttpClient 在 Android 5.0 Lollipop 中因握手失败而失败 [英] HttpClient fails with Handshake Failed in Android 5.0 Lollipop

查看:28
本文介绍了HttpClient 在 Android 5.0 Lollipop 中因握手失败而失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Android 5.0 Lollipop 中的 DefaultHttpClient 似乎已损坏.它无法设置与以前版本的 Android 成功设置的某些站点的连接.

DefaultHttpClient in Android 5.0 Lollipop seems to be broken. It can not set the connection to some sites that were successfully set by previous versions of Android.

例如,我尝试连接到 https://uralsg.megafon.ru

//Create httpclient like in https://stackoverflow.com/questions/18523784/ssl-tls-protocols-and-cipher-suites-with-the-androidhttpclient
HttpClient client = new DefaultHttpClient(manager, params);
HttpGet httpGet = new HttpGet("https://uralsg.megafon.ru");
HttpResponse client = httpclient.execute(httpGet);

此代码在 Android 2.3-4.4 中有效,但在 Android 5.0(设备和模拟器)上失败,并出现错误 Connection closed by peer.当然这是可以理解的,因为 Android 5.0 尝试将这个旧服务器与 TLSv1.2 和现代密码连接起来,但它不支持它们.

This code works in Android 2.3-4.4, but fails on Android 5.0 (devices and emulator) with error Connection closed by peer. Of course this is understandable because Android 5.0 tries to connect this old server with TLSv1.2 and modern ciphers and it does not support them.

好的,使用SSL/TLS 协议中的示例代码和带有 AndroidHttpClient 的密码套件,我们将协议和密码限制为 TLSv1SSL_RSA_WITH_RC4_128_MD5.现在它因不同的错误而失败:

Ok, using the sample code in SSL/TLS protocols and cipher suites with the AndroidHttpClient we limit the protocol and cipher to TLSv1 and SSL_RSA_WITH_RC4_128_MD5. Now it fails with a different error:

javax.net.ssl.SSLHandshakeException: Handshake failed
caused by 
    error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac 
    (external/openssl/ssl/s3_pkt.c:1286 0x7f74c1ef16e0:0x00000003) 
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake

当然,这段代码在 Android 2.3-4.4 上运行流畅.

And of course this code runs smoothly on Android 2.3-4.4.

我使用wireshark检查了流量:

I examined the traffic with wireshark:

302 4002.147873000  192.168.156.30  83.149.32.13    TLSv1   138 Client Hello
303 4002.185362000  83.149.32.13    192.168.156.30  TLSv1   133 Server Hello
304 4002.186700000  83.149.32.13    192.168.156.30  TLSv1   1244    Certificate
305 4002.186701000  83.149.32.13    192.168.156.30  TLSv1   63  Server Hello Done
307 4002.188117000  192.168.156.30  83.149.32.13    TLSv1   364 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
308 4002.240695000  83.149.32.13    192.168.156.30  TLSv1   61  Alert (Level: Fatal, Description: Bad Record MAC)

您可以看到连接已建立但服务器收到警报,因为它可能无法解码加密的握手消息.

You can see that connection was established but server alerted because it probably could not decode encrypted handshake message.

我无法在 Android 上使用 HttpClient 连接到 https://uralsg.megafon.ru5.0.股票浏览器确实连接它.Android 2.3-4.4 以任何方式连接本网站没有任何困难.

I didn't manage to connect to https://uralsg.megafon.ru using HttpClient on Android 5.0. Stock browser does connect it though. Android 2.3-4.4 connects this site in any way without any difficulties.

有什么办法可以让 HttpClient 连接这样的站点?这只是一个例子,我相信有很多旧服务器无法通过 Android 5.0 和 HttpClient 连接.

Is there any way to make it possible for HttpClient to connect such sites? This is only one example, I am sure there are plenty of legacy servers that couldn't be connected by Android 5.0 and HttpClient.

推荐答案

更新:结果证明是后端的错误,而不是 android 5,尽管确实与有问题的密码.

update: it turned out to be a bug in the back-end, not android 5, though indeed with the cipher in question.

我遇到了同样的问题.对我来说,结果是密码 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,它是从 android 5 的(更新的)默认密码集中选择的.

I had the same problem. For me it turned out to be the cipher TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 which was chosen from android 5's (updated) set of default ciphers.

一旦我将其从可接受密码的客户端列表中删除,连接就会再次工作.

As soon as i removed it from the client list of acceptable ciphers, connections worked again.

android 5 更改日志提到:

  • AES-GCM (AEAD) 密码套件现已启用,

我很确定这就是罪魁祸首.一旦 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 成为首选(服务器),连接就会失败.

I'm pretty sure this is the culprit. As soon as TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 is preferred (by the server), the connection will fail.

请注意,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 有效.

我的猜测是 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 的 Android 实现有问题,或者您正在与之交谈的服务器之一.

My guess is that either the Android implementation of TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 is buggy, or the one of the server you're talking to.

解决方案:

  1. 从服务器上的可用密码中删除 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(无需重新部署应用).
  2. 从客户端提供的密码列表中删除 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(在 CLIENT_HELLO 期间).
  1. Remove TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 from the available ciphers on the server (no app redeployment needed).
  2. Remove TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 from the list of ciphers the client offers (during the CLIENT_HELLO).

您可以在客户端通过实现自己的 SSLSocketFactory 并调用

You can do that on the client side by implementing your own SSLSocketFactory and calling

sslSocket.setEnabledCipherSuites(String[] suites);

关于 SSLSocket 创建.

on SSLSocket creation.

请注意,这不一定是 android 错误,可能是服务器实现有问题.如果您的问题确实是由密码引起的,请在 android bug tracker 上发表评论](https://code.google.com/p/android/issues/detail?id=81603).谢谢!

edit: note that this isn't necessarily an android bug, it might be that the server implementation is faulty. if your problem is indeed caused by the cipher, please leave a comment on the android bug tracker](https://code.google.com/p/android/issues/detail?id=81603). thank you!

这篇关于HttpClient 在 Android 5.0 Lollipop 中因握手失败而失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆