我有一个多人游戏,其客户端服务器设置在桌面和我自己的Android测试设备(4.x - 5.x)上运行良好但是每个尝试使用Android 6+移动设备的人都不能完成与服务器的握手。
客户端获取:com.android.org.conscrypt.SSL_do_handshake(本机方法)中的对等异常关闭连接
我为服务器上的javax.net包打开了完整输出,这就是我所看到的:
Thread-5, called closeInbound()
Thread-5, fatal error: 80: Inbound closed before receiving peer's close_notify: possible truncation attack?
javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
%% Invalidated: [Session-1, TLS_DHE_RSA_WITH_AES_128_CBC_SHA]
Thread-5, SEND TLSv1.2 ALERT: fatal, description = internal_error
Thread-5, WRITE: TLSv1.2 Alert, length = 2
Thread-5, called closeOutbound()
Thread-5, closeOutboundInternal()
日志实际上是90k +字符,但我无法将其全部粘贴。但基本上服务器客户端通过TLS1.2,1.1和1.0,结果是相同的" javax.net.ssl.SSLException:收到对等关闭之前的入站关闭:可能的截断攻击?"
我正在使用自签名证书和信任库黑客:
public LoginClient() throws Exception{
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
// return null;
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
有谁知道出了什么问题以及如何解决这个问题?我觉得有点奇怪,它只发生在Android 6 +
上编辑:添加了*** Diffie-Hellman ServerKeyExchange
DH Modulus: { 233, 230, 66, 89, 157, 53, 95, 55, 201, 127, 253, 53, 103, 18, 11, 142, 37, 201, 205, 67, 233, 39, 179, 169, 103, 15, 190, 197, 216, 144, 20, 25, 34, 210, 195, 179, 173, 36, 128, 9, 55, 153, 134, 157, 30, 132, 106, 171, 73, 250, 176, 173, 38, 210, 206, 106, 34, 33, 157, 71, 11, 206, 125, 119, 125, 74, 33, 251, 233, 194, 112, 181, 127, 96, 112, 2, 243, 206, 248, 57, 54, 148, 207, 69, 238, 54, 136, 193, 26, 140, 86, 171, 18, 122, 61, 175 }
DH Base: { 48, 71, 10, 213, 160, 5, 251, 20, 206, 45, 157, 205, 135, 227, 139, 199, 209, 177, 197, 250, 203, 174, 203, 233, 95, 25, 10, 167, 163, 29, 35, 196, 219, 188, 190, 6, 23, 69, 68, 64, 26, 91, 44, 2, 9, 101, 216, 194, 189, 33, 113, 211, 102, 132, 69, 119, 31, 116, 186, 8, 77, 32, 41, 216, 60, 28, 21, 133, 71, 243, 169, 241, 162, 113, 91, 226, 61, 81, 174, 77, 62, 90, 31, 106, 112, 100, 243, 22, 147, 58, 52, 109, 63, 82, 146, 82 }
Server DH Public Key: { 23, 79, 111, 200, 124, 159, 143, 170, 244, 139, 127, 154, 15, 184, 207, 89, 0, 30, 234, 138, 254, 90, 48, 244, 171, 46, 100, 55, 220, 87, 23, 2, 3, 243, 132, 144, 17, 75, 191, 90, 239, 112, 13, 71, 150, 127, 34, 219, 174, 161, 188, 204, 151, 97, 179, 129, 103, 89, 188, 211, 14, 216, 71, 115, 12, 105, 63, 219, 23, 70, 110, 231, 202, 153, 121, 59, 194, 97, 105, 215, 57, 211, 48, 184, 22, 149, 176, 64, 186, 103, 240, 237, 224, 217, 233, 4 }
Signature Algorithm SHA512withRSA
Signed with a DSA or RSA public key
*** ServerHelloDone
更新 我终于掌握了Android 6.0.1设备,所以我可以测试一下这个。 在我的开发环境中,我在生产服务器上运行Oracle Java 7u25,其中有openjdk 7,有趣的是Android 6在我的开发环境中使用完全相同的设置但在我尝试连接到生产服务器时失败。我现在可以看到完整的例外情况,它是:
11-01 05:18:50.793: W/System.err(23793): javax.net.ssl.SSLHandshakeException: Handshake failed
11-01 05:18:50.796: W/System.err(23793): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:396)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.Connection.connect(Connection.java:143)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:185)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:437)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
11-01 05:18:50.796: W/System.err(23793): at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:245)
11-01 05:18:50.797: W/System.err(23793): at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
11-01 05:18:50.797: W/System.err(23793): at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java)
11-01 05:18:50.797: W/System.err(23793): at com.aperico.game.sylvass.netcode.LoginClient.doLogin(LoginClient.java:105)
11-01 05:18:50.797: W/System.err(23793): at com.aperico.game.sylvass.CryptCardsGame$4.run(CryptCardsGame.java:343)
11-01 05:18:50.797: W/System.err(23793): at java.lang.Thread.run(Thread.java:818)
11-01 05:18:50.797: W/System.err(23793): Suppressed: javax.net.ssl.SSLHandshakeException: Handshake failed
11-01 05:18:50.797: W/System.err(23793): ... 16 more
11-01 05:18:50.797: W/System.err(23793): Suppressed: javax.net.ssl.SSLHandshakeException: Handshake failed
11-01 05:18:50.797: W/System.err(23793): ... 16 more
11-01 05:18:50.798: W/System.err(23793): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x941df080: Failure in SSL library, usually a protocol error
11-01 05:18:50.798: W/System.err(23793): error:100c1069:SSL routines:ssl3_get_server_key_exchange:BAD_DH_P_LENGTH (external/boringssl/src/ssl/s3_clnt.c:1193 0xa9e31ad5:0x00000000)
11-01 05:18:50.798: W/System.err(23793): at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
11-01 05:18:50.798: W/System.err(23793): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:324)
11-01 05:18:50.798: W/System.err(23793): ... 15 more
11-01 05:18:50.798: W/System.err(23793): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x941df080: Failure in SSL library, usually a protocol error
11-01 05:18:50.798: W/System.err(23793): error:100c1069:SSL routines:ssl3_get_server_key_exchange:BAD_DH_P_LENGTH (external/boringssl/src/ssl/s3_clnt.c:1193 0xa9e31ad5:0x00000000)
11-01 05:18:50.798: W/System.err(23793): at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
11-01 05:18:50.799: W/System.err(23793): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:324)
11-01 05:18:50.799: W/System.err(23793): ... 15 more
11-01 05:18:50.799: W/System.err(23793): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x941df080: Failure in SSL library, usually a protocol error
11-01 05:18:50.799: W/System.err(23793): error:100c1069:SSL routines:ssl3_get_server_key_exchange:BAD_DH_P_LENGTH (external/boringssl/src/ssl/s3_clnt.c:1193 0xa9e31ad5:0x00000000)
11-01 05:18:50.799: W/System.err(23793): at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
11-01 05:18:50.799: W/System.err(23793): at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:324)
11-01 05:18:50.799: W/System.err(23793): ... 15 more
答案 0 :(得分:1)
服务器DH公钥:{... 96到0到255之间的数字......}
您的DH密钥仅为768位(96 * 8)。这被视为弱,请参阅logjam attack了解详情。因此,包括大多数现代Web浏览器的现代TLS堆栈要求DH密钥至少为1024位。
我的猜测是你在768 bit DH key is the default there以后在服务器上使用Java 7,而使用Java 8时默认是1024位。 根据{{3}},Java 7不能使用1024位且更好的DH密钥,这意味着您可以选择升级到Java 8或使用DH禁用密码。本文还介绍了如何执行后者。
除此之外,在客户端中禁用主机名验证是一个非常糟糕的主意。这实际上意味着您信任受信任CA颁发的任何证书,无论该证书对哪个主机有效。 这使得中间人攻击容易,从而有效地消除了TLS提供的主要保护。如果您有一个无法信任的证书,否则请使用证书固定在您的应用程序中仅接受此证书并阻止中间人攻击。有关更多信息,请参阅How Java 7 and 8 Handle DHE Keys Differently, and Resolving Errors,包括各种语言的示例代码,包括Java。
答案 1 :(得分:0)
在服务器上更新到Oracle Java 8解决了这个问题。不是很确定为什么,但似乎Android 6+无法与openjdk 7协商握手