Apache HttpClient与TLSv1.2的握手失败

4

首先,我将解释一下情境。

我有一个运行着 jdk1.7.0_79 的 WSO2 ESB-4.6.0(使用 Apache 的 HttpClient),我的目标是调用一个只接受 TLSv1.2 协议的外部安全服务,而不需要更新 Java 到版本 8。
外部服务器指令如下:

Supported versions: TLSv1.2
Deflate compression: no
Supported cipher suites (ORDER IS NOT SIGNIFICANT):
  TLSv1.2
     RSA_WITH_3DES_EDE_CBC_SHA
     DHE_RSA_WITH_3DES_EDE_CBC_SHA
     RSA_WITH_AES_128_CBC_SHA
     DHE_RSA_WITH_AES_128_CBC_SHA
     RSA_WITH_AES_256_CBC_SHA
     DHE_RSA_WITH_AES_256_CBC_SHA
     RSA_WITH_AES_128_CBC_SHA256
     RSA_WITH_AES_256_CBC_SHA256
     RSA_WITH_CAMELLIA_128_CBC_SHA
     DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
     DHE_RSA_WITH_AES_128_CBC_SHA256
     DHE_RSA_WITH_AES_256_CBC_SHA256
     RSA_WITH_CAMELLIA_256_CBC_SHA
     DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
     TLS_RSA_WITH_AES_128_GCM_SHA256
     TLS_RSA_WITH_AES_256_GCM_SHA384
     TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
     TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
     TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
     TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
     TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
----------------------
Minimal encryption strength:     strong encryption (96-bit or more)
Achievable encryption strength:  strong encryption (96-bit or more)
BEAST status: protected
CRIME status: protected

因此,在构建和调用一个简单的代理时,需要有一个指向此服务的端点:

Using SSLEngineImpl.
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
HTTPS-Sender I/O dispatcher-1, fatal error: 40: Couldn't kickstart handshaking
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
HTTPS-Sender I/O dispatcher-1, SEND TLSv1 ALERT:  fatal, description = handshake_failure
HTTPS-Sender I/O dispatcher-1, WRITE: TLSv1 Alert, length = 2
[2016-02-25 22:15:12,689] ERROR - TargetHandler I/O error: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
        at sun.security.ssl.Handshaker.activate(Handshaker.java:470)
        at sun.security.ssl.SSLEngineImpl.kickstartHandshake(SSLEngineImpl.java:714)
        at sun.security.ssl.SSLEngineImpl.beginHandshake(SSLEngineImpl.java:740)
        at org.apache.http.impl.nio.reactor.SSLIOSession.bind(SSLIOSession.java:141)
        at org.apache.http.impl.nio.ssl.SSLClientIOEventDispatch.connected(SSLClientIOEventDispatch.java:205)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.sessionCreated(BaseIOReactor.java:250)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processNewChannels(AbstractIOReactor.java:425)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:289)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
        at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:542)
        at java.lang.Thread.run(Thread.java:745)

在这一点上,我的第一个想法是找到一种方法来“配置”Java 7以使其与此工作。因此,我使用Eclipse(使用javax.xml.soap.SOAPConnectionFactory)构建了一个简单的webservice客户端类,并在与ESB使用相同的JVM下运行它。如预期的那样,出现了相同的错误!
但是,我编辑了jre/lib/security/java.security文件并找到了这些参数,使调用起作用:

java MyClientClass -Dhttps.protocols=TLSv1.2 -Dhttps.cipherSuites=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256

在这一切之后,我认为应该适用于ESB的相同参数。但是,上述两个参数和下面的其他参数以多种不同的组合方式,都无法实现,出现了与之前相同的异常。

./wso2server.sh -Ddeployment.security.SSLv3=false \
                -Ddeployment.security.TLSv1=false \
                -Ddeployment.security.TLSv1.1=false \
                -Ddeployment.security.TLSv1.2=true \
                -Dhttps.protocols=TLSv1.2 \
                -Dhttps.cipherSuites=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256

为什么使用相同的JVM和参数,ESB不起作用,而MyClientClass却可以?问题出在Apache的http-core实现上(如堆栈跟踪所示)?是我犯了一些错误还是这些参数被简单地忽略了?

HttpCore版本为4.1.3。


1
https.protocols 属性被 HttpsUrlConnection 使用,但从堆栈跟踪来看,ESB 代码正在使用 Apache 的 HttpClient(它不遵守 https.protocols);请参阅此帖子以获取相关讨论:https://dev59.com/LF8d5IYBdhLWcg3wzEz4 - Castaglia
我明白了。因此,Apache 客户端的“替代方案”仍然未知。 - elias
使用Java 7,没错。如果你能升级到Java 8,那么你将能够使用作为安全增强功能添加的“jdk.tls.client.protocols”系统属性。 - Castaglia
我已经使用Java 8进行了测试,它可以正常工作,但也会导致ESB的其他组件出现问题。 - elias
2
这已被确认为bug[1]并在ESB 4.9.0中得到修复。请联系wso2支持团队,他们可能有ESB 4.6.0的补丁,或尝试升级到Java 8并在java.security中设置以下jdk.tls.client.protocols=TLSv1.2。 [1]https://wso2.org/jira/browse/ESBJAVA-3644 - Jenananthan
1个回答

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接