2013-08-23 44 views
1

我正尝试在Tomcat和APR连接器上使用SSL。我可以对服务器进行更改,但不能更改到现有的Java客户机。带APR连接器的Tomcat正在使用SSL断开Java客户端

由于某些原因,无论何时Java客户端使用SSL连接到Tomcat服务器,都无法连接 - 服务器将重置连接。但是,完全相同的Java代码可以连接到Apache使用SSL托管的不同端口上的同一台服务器。另外,非Java代码(如curl)可以连接到Tomcat SSL连接。

我已经通过强制Java客户端使用TLSv1协议(-Dhttps.protocols = TLSv1)来完成此工作。但是,这不是一个实际的解决方案,因为我们目前无法为我们的Java客户端发布更新。

因为这与服务器上的Apache一起工作,所以在我看来,我应该能够在服务器上进行某种配置更改以使用Tomcat,而无需更改Java客户端。

总结: 的Java连接到Tomcat SSL =失败

卷曲连接到Tomcat SSL =好

的Java连接到Apache SSL =好

卷曲连接到Apache SSL =好

下面是一些说明问题的示例Java代码。我与Java 6在Mac OS X上运行

public class SSLConnectTest { 
    public static void main(String[] args) throws Exception { 
     System.setProperty("javax.net.debug", "all"); 

     testConnection("https://secure2.360works.com"); //Apache running SSL. This works. 
     testConnection("https://secure2.360works.com:8443/"); //Tomcat running SSL and APR. This fails. 
    } 

    private static void testConnection(String urlString) throws IOException { 
     new URL(urlString).openStream().close(); 
    } 
} 

下面是在SSL握手会发生什么:

trigger seeding of SecureRandom 
done seeding SecureRandom 
Allow unsafe renegotiation: false 
Allow legacy hello messages: true 
Is initial handshake: true 
Is secure renegotiation: false 
%% No cached client session 
*** ClientHello, TLSv1 
RandomCookie: GMT: 1377233856 bytes = { 69, 128, 29, 114, 252, 186, 13, 192, 212, 243, 179, 208, 124, 196, 220, 137, 23, 124, 30, 226, 98, 148, 243, 6, 188, 230, 109, 119 } 
Session ID: {} 
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 
Compression Methods: { 0 } 
*** 
main, WRITE: TLSv1 Handshake, length = 81 
main, WRITE: SSLv2 client hello message, length = 110 
main, handling exception: java.net.SocketException: Connection reset 
main, SEND TLSv1 ALERT: fatal, description = unexpected_message 
main, WRITE: TLSv1 Alert, length = 2 
main, Exception sending alert: java.net.SocketException: Broken pipe 
main, called closeSocket() 
Disconnected from the target VM, address: '127.0.0.1:62146', transport: 'socket' 
Exception in thread "main" java.net.SocketException: Connection reset 
    at java.net.SocketInputStream.read(SocketInputStream.java:168) 
    at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:422) 
    at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:460) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:863) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199) 
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434) 
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) 
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172) 
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234) 
    at java.net.URL.openStream(URL.java:1010) 
    at com.prosc.license.client.network.SSLConnectTest.testConnection(SSLConnectTest.java:22) 
    at com.prosc.license.client.network.SSLConnectTest.main(SSLConnectTest.java:18) 

这里是在server.xml中的连接器配置。我希望这里的一些变化将解决这个问题:

<Connector port="8443" SSLEnabled="true" 
maxThreads="150" scheme="https" secure="true" 
sslProtocol="SSLv2+TLSv1+SSLv3" 
SSLHonorCipherOrder="true" 
protocol="org.apache.coyote.http11.Http11AprProtocol" 
clientAuth="false" SSLCertificateFile="/etc/apache2/ssl.crt/secure2.360works.com.crt" 
SSLCertificateKeyFile="/etc/apache2/ssl.crt/secure2.360works.com.key" 
SSLCertificateChainFile="/etc/apache2/ssl.crt/secure2.360works.com.chcrt" /> 

回答

3
main, WRITE: TLSv1 Handshake, length = 81 
main, WRITE: SSLv2 client hello message, length = 110 

我想这是从Java 6的环境来(除非客户已明确启用SSLv2Hello协议)。你有没有试过看看,当在Java 7 JRE中运行(这doesn't enable SSLv2Hello by default)客户端能够连接。

我猜这个问题是因为在APR连接器可能不喜欢接收的SSLv2客户端Hello(其中,从Java来了,是不是一个真正的客户端的SSLv2你好,但V3裹成V2,见EJP's answer)。

一对夫妇的可能解决这个问题的建议:

  • 尽量让APR接受的SSLv2连接,至少在SSLv3或以上包裹成V2你好。 (使用SSLv2并不是一个好主意,但带有SSLv3/TLS的SSLv2Hello应该不成问题。)
  • 在Apache Tomcat中为纯Java连接器(BIO或NIO,请参阅comparative table)切换APR。您可能需要证书和密钥转换为密钥库,但是这应该不会太困难,特别是为PKCS12密钥库。
+0

感谢您的答复。我更新了我的问题以显示server.xml文件中的connector元素。我目前启用SSLv2,SSLv3和TLSv1(根据文档,这是所有支持的协议)。 –

+0

我不想切换到BIO或NIO,因为我的所有研究都表明,为了支持SSL,APR要快得多。我改用APR的原因是为了提高性能。 –

+0

我在客户端用Java 7测试了它,而且确实有效!但是,我的客户中有90%使用Java 6,所以我仍然在寻找一种服务器端解决方案来解决他们的问题。 –

相关问题