当前位置: 首页 > 知识库问答 >
问题:

Apache HTTP服务器出现间歇性SSL握手错误

卫鸿朗
2023-03-14

我看到断断续续的SSL握手错误,Java客户端和浏览器通过Apache HTTP服务器访问网站。这种情况很少发生,但它每天都会破坏构建并影响用户体验。服务器被配置为建立安全连接,但不需要来自客户端的证书。

我已经在Java测试客户端和服务器上打开了SSL调试输出(见下文)。我所观察到的是,每当发生握手异常时,服务器似乎已经发送了对客户端证书的请求。我不明白为什么它会这样做,为什么这只是偶尔发生。当它发送证书请求时,错误几乎总是发生,但是我也捕获了成功的请求(可能有1%的时间,99%的时间失败)。

客户端使用Java 8(1.8.0_31-b13),Apache HTTP服务器版本为2.2.19。

以下是日志中的片段:

1) Apache配置摘录

SSLProtocol ALL -SSLv2 -SSLv3
SSLCertificateFile <path-to-pem1>
SSLCertificateChainFile <path-to-pem2>
SSLCACertificateFile <path-to-pem3>
SSLVerifyDepth 10
SSLVerifyClient none

这个pem文件是世界可读的。

2)客户日志(略)

*** ClientHello, TLSv1.2
***
*** ServerHello, TLSv1
***
*** Certificate chain
***
*** Diffie-Hellman ServerKeyExchange
*** CertificateRequest
*** ServerHelloDone
*** Certificate chain
***
*** ClientKeyExchange, DH
*** Finished
***
...
main, WRITE: TLSv1 Handshake, length = 48
main, waiting for close_notify or alert: state 1
main, Exception while waiting for close java.net.SocketException: Software caused connection abort: recv failed
main, handling exception: java.net.SocketException: Software caused connection abort: recv failed
%% Invalidated:  [Session-1, TLS_DHE_RSA_WITH_AES_128_CBC_SHA]
main, SEND TLSv1 ALERT:  fatal, description = unexpected_message
...
main, WRITE: TLSv1 Alert, length = 32
main, Exception sending alert: java.net.SocketException: Software caused connection abort: socket write error
main, called closeSocket()

3) 服务器日志(缩写)

[info] [client x.x.x.x] Connection to child 1 established (server XXX:443)
[info] Seeding PRNG with 0 bytes of entropy
[debug] ssl_engine_kernel.c(1866): OpenSSL: Handshake: start
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: before/accept initialization
[debug] ssl_engine_io.c(1897): OpenSSL: read 11/11 bytes from BIO#82f6820 [mem: 82c5290] (BIO dump follows)
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1869): | 0000: XX XX XX XX XX XX XX XX-XX XX XX                 ...........      |
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1897): OpenSSL: read 245/245 bytes from BIO#82f6820 [mem: 82c529b] (BIO dump follows)
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1869): | 0000: XX XX XX XX XX XX XX XX-XX XX XX XX XX XX XX XX  ................ |
...
[debug] ssl_engine_io.c(1869): | 00f0: XX XX XX XX XX                                   .....            |
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+
[debug] ssl_engine_kernel.c(1987): [client x.x.x.x] SSL virtual host for servername XXX found
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 read client hello A
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write server hello A
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write certificate A
[debug] ssl_engine_kernel.c(1274): [client x.x.x.x] handing out temporary 1024 bit DH key
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write key exchange A
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write certificate request A
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 flush data
[debug] ssl_engine_io.c(1897): OpenSSL: read 5/5 bytes from BIO#82f6820 [mem: 82c5290] (BIO dump follows)
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1869): | 0000: 16 03 01 00 8d                                   .....            |
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1897): OpenSSL: read 141/141 bytes from BIO#82f6820 [mem: 82c5295] (BIO dump follows)
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1869): | 0000: XX XX XX XX XX XX XX XX-XX XX XX XX XX XX XX XX  ................ |
...
[debug] ssl_engine_io.c(1869): | 0080: XX XX XX XX XX XX XX XX-XX XX XX XX XX           .............    |
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+
[debug] ssl_engine_kernel.c(1884): OpenSSL: Write: SSLv3 read client certificate B
[debug] ssl_engine_kernel.c(1903): OpenSSL: Exit: error in SSLv3 read client certificate B
[debug] ssl_engine_kernel.c(1903): OpenSSL: Exit: error in SSLv3 read client certificate B
[info] [client x.x.x.x] SSL library error 1 in handshake (server XXX:443)
[info] SSL Library Error: 336105671 error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate No CAs known to server for verification?
[info] [client x.x.x.x] Connection closed to child 1 with abortive shutdown (server XXX:443)

在好的情况下,我们始终不会在客户端看到“***CertificateRequest”,也不会在服务器上看到这样的输出

[debug] ssl_engine_kernel.c(1987): [client x.x.x.x] SSL virtual host for servername XXX found
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 read client hello A
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write server hello A
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write certificate A
[debug] ssl_engine_kernel.c(1274): [client x.x.x.x] handing out temporary 1024 bit DH key
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write key exchange A
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 write server done A
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 flush data
[debug] ssl_engine_io.c(1897): OpenSSL: read 5/5 bytes from BIO#82d82d8 [mem: 82c8790] (BIO dump follows)
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1869): | 0000: 16 03 01 00 86                                   .....            |
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1897): OpenSSL: read 134/134 bytes from BIO#82d82d8 [mem: 82c8795] (BIO dump follows)
[debug] ssl_engine_io.c(1830): +-------------------------------------------------------------------------+
[debug] ssl_engine_io.c(1869): | 0000: XX XX XX XX XX XX XX XX-XX XX XX XX XX XX XX XX  ................ |
...
[debug] ssl_engine_io.c(1869): | 0080: XX XX XX XX XX XX                                ......           |
[debug] ssl_engine_io.c(1875): +-------------------------------------------------------------------------+
[debug] ssl_engine_kernel.c(1874): OpenSSL: Loop: SSLv3 read client key exchange A

Java客户端代码大纲:

URL url = new URL("https://...");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", "Basic " + DatatypeConverter.printBase64Binary((user + ":" + pass).getBytes(Charset.forName("UTF-8"))));
connection.setReadTimeout(60*1000);
connection.setUseCaches(false);
connection.connect();

java -Djavax.net.ssl.trustStore=... -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStorePassword=... -Djavax.net.debug=all ...

问题:

  1. 是什么使服务器发送证书请求,从而导致客户端上的输出“***CertificateRequest”

更新:我注意到Java客户机在使用Java6时从不显示错误。Java7和Java8以及Chrome、InternetExplorer和Firefox都出现了这个问题。这似乎指向了TLSv1的一个问题。1或TLSv1。2(另见https://serverfault.com/questions/513961/how-to-disable-tls-1-1-1-2-in-apache“OpenSSL v1.0.1与TLSv1.2之间存在一些已知问题”)。我将尝试至少检查是否禁用TLSv1。Java客户端中的1/2将使问题消失。

共有3个答案

翟志新
2023-03-14

经过漫长而乏味的调试和分析,我想报告一下结果。问题与客户端发送的TLS握手的第一条ClientHello消息有关。

Java7和Java8客户端(可能包括所有现代浏览器)使用“服务器名称指示”(SNI)扩展。此问题仅在使用此扩展时发生。Java6客户机不发送它,而且问题从未在那里发生过。TLSv1和TLSv1出现问题。2-我们从未观察到TLSv1。1请求,因此我无法发表评论。

对于Java7和Java8客户机,为了防止这个问题,我们可以设置-djse。enableSNIExtension=false停止客户端发送SNI扩展。

我们将尝试更改httpd.conf配置(和包含的文件),看看我们是否能让服务器表现良好。如果我们成功了,我可能会发布信息,即是否有服务器端的解决方案。上面提到的Java开关是一个客户端工作区,至少对我们的夜间构建足够好。

张鹏云
2023-03-14

是什么使服务器发送证书请求,从而导致客户端上的输出“***CertificateRequest”?

在服务器上调用SSL_CTX_set_client_CA_list。这是一个杰出名字的列表。另请参阅SSL_CTX_set_client_CA_list手册页。

服务器还需要调用SSL\u CTX\u load\u verify\u locations来建立CAs中的信任。另请参见SSL\u CTX\u load\u verify\u locations手册页。

设置“SSLVerifyClient none”是否不阻止证书请求?

可能地从SSL\u CTX\u set\u verify手册页,您需要SSL\u verify\u PEER,如果没有PEER\u证书,则可能需要SSL\u verify\u FAIL\u。

对下一步该看什么有什么建议吗?

您应该显示您的相关Java代码。

您应该说明服务器和客户端使用的OpenSSL版本。

毕魁
2023-03-14

是什么使服务器发送证书请求,从而导致客户端上的输出“***CertificateRequest”?

在某个地方,您将SSLVerifyClient设置为“可选”或更高级别,可能是在一个应用程序中。htaccess文件,这就是为什么在配置文件中找不到它的原因。这将全局覆盖设置的“SSLVerifyClient none”。

 类似资料:
  • 我们有一个SSL问题,我是99%,这不是你通常的证书信任商店旋转木马。 我们有一个Weblogic服务器试图通过LDAPS与Active Directory建立SSL连接,底层SSL实现是JSSE。 有时,它是有效的。通常在重新启动Weblogic后的几个小时内。 之后,我们开始得到SSL握手错误,与SSL调试打开我们看到: [ACTIVE]ExecuteThread:'10'用于队列:'webl

  • 出身背景我需要让我的网站通过IdentityServer(IDS)进行身份验证。“example.com” 我正在用DotNetCore构建我所有的网站,用apache在代理服务器上托管它们,让我们调用私有ip12.3.4.5。 它们应该如何工作。我去网站的例子。我应该可以和ids通话。例如。com获取身份验证信息,然后重新路由回示例。具有身份验证令牌的com。相反,我得到了一个SSL握手错误。见

  • 如有任何帮助,我们将不胜感激。 PS:我使用的是java7

  • 我似乎时断时续地遇到这个问题。如果我拔下插头并重新插入设备并重新执行测试,则没有错误,但这只是暂时的修复,直到它再次出现。我有2个appium server实例,用于2台设备- appium版本-1.15.1 appium服务器控制台上的错误- IDE-上的错误- 设备所需的功能1- 设备的移动功能2- 非常感谢任何帮助!

  • 我有一个用Java编写的REST API,在JBoss下运行。最近我们将JVM从1.6更新到1.7。这开始导致只有我们正在连接的Python客户端出现问题。间歇性地,Python客户端出现握手失败。我们编写了一个非常简单的测试来重现这个问题: 给出以下输出: 第67次调用在这次运行中失败了,但是每次测试运行失败的时间不同。 我们的其他客户端(Java、Groovy和Ruby)工作起来没有任何问题。

  • 我正在使用T.Rob的建议调试Websphere MQ服务器和客户机之间的SSL错误,并需要帮助理解SSL握手(SSL连接到MQ使用。NET MQ客户机SSLv3?)。 我的WMQ7.5客户机应用程序是C代码,使用密钥库(.kdb)。利用WebSphere管理员提供的CHLTAB。WMQ服务器运行Java,通道是用相互身份验证定义的。 本文指出,在SSL/TLS握手中,服务器总是发送其公共证书以响