繁体   English   中英

Java SSLContextImpl $ TLS10Context随机“peer not authenticated”异常

[英]Random “peer not authenticated” exceptions with Java SSLContextImpl$TLS10Context

当使用SSL连接到HAProxy服务器时,我会出现随机出现的连接失败。 我已经确认这些故障发生在JDK版本1.7.0_21和1.7.0_25上,但不是1.7.0_04或1.6.0_38。

例外是

 Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)
    at SSLTest2.main(SSLTest2.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

这些故障仅在使用TLS SSL上下文而非默认上下文时发生。 以下代码在循环中运行了一千次,并且在循环完成之前发生了故障(大约2%的连接失败):

SSLContext sslcontext = SSLContext.getInstance("TLS");   
sslcontext.init(null, null, null);
SSLSocketFactory factory = sslcontext.getSocketFactory(); 
SSLSocket socket = (SSLSocket)factory.createSocket("myserver", 443);

//socket.startHandshake();
SSLSession session = socket.getSession();
session.getPeerCertificates();
socket.close();

但是,如果我以这种方式创建SSL上下文,我在上面提到的任何Java版本上都没有连接失败:

SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();

第一种方法使用SSLContextImpl$TLS10Context ,后者使用SSLContextImpl$DefaultSSLContext 查看代码,我没有看到任何会导致异常发生的差异。

为什么我会遇到失败以及使用getDefault()调用的优点/缺点是什么?

注意:首先使用Apache HttpClient(版本4)看到了异常。 此代码是再现HttpClient所遇问题的最小子集。

这是我在添加-Djavax.net.debug=ssl时看到的错误:

main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT:  fatal, bad_record_mac
%% Invalidated:  [Session-101, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLException: Received fatal alert:   bad_record_mac
main, IOException in getSession():  javax.net.ssl.SSLException: Received fatal alert: bad_record_mac

另一条信息是,如果我关闭代理服务器上的Diffie-Hellman,则不会发生错误。

从症状来看,我这与使用TLS错误启动的浏览器有关,这是谷歌为减少TLS中的来回而引入的客户端技巧:

虚假启动主要由浏览器控制,并通过将官方SSL规范中描述的数据的两次往返传递减少到单个往返传递来工作。 它通过指示客户端在单个调度中发送完成和第一个ApplicationData消息而不是将它们放在两个不同的包中并且仅在从服务器获得确认后发送第二个消息来完成此操作。

谷歌提出虚假启动作为官方标准,使SSL更适合目前发现它太昂贵的网站。 通过缩写协商加密密钥的握手以及保护最终用户和网站之间传递数据所需的其他变量,False Start旨在降低许多人认为使用协议所带来的性能损失。

Mozilla Firefox中提出相关问题 :(强调我的)

到目前为止,已知与False Start存在当前或以前兼容性问题的产品列表不完整包括(AFAICT):F5,A10,Microsoft TMG,Cisco ASA,ServerIron ADX,ESET,NetNanny, Java SSL服务器实现的一些配置

javax.net.ssl.SSLPeerUnverifiedException仅因为http安全性而出现,您必须将连接配置为https,否则请遵循此代码。

            SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, new TrustManager[]{tm}, null);
    SSLSocketFactory ssf = new SSLSocketFactory(ctx);
    ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    ClientConnectionManager ccm = client.getConnectionManager();
    SchemeRegistry sr = ccm.getSchemeRegistry();
    sr.register(new Scheme("https", ssf, 443));
    return new DefaultHttpClient(ccm, client.getParams());

用这个。 我希望它会对你有所帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM