我尝试为客户端和服务器设置自签名TLS配置,其中服务器为Tomcat 7,客户端为Apache httpclient 4.1。服务器配置是从此处获取的,而客户端代码是从此处获取的。
我的tomcat配置如下所示:
<Connector clientAuth="true" port="8443" minSpareThreads="5" maxSpareThreads="75" enableLookups="true" disableUploadTimeout="true" acceptCount="100" maxThreads="200" scheme="https" secure="true" SSLEnabled="true" keystoreFile="keys/server.jks" keystoreType="JKS" keystorePass="password" truststoreFile="keys/server.jks" truststoreType="JKS" truststorePass="password" SSLVerifyClient="require" SSLEngine="on" SSLVerifyDepth="2" sslProtocol="TLS" />
我的客户代码如下:
final HttpParams httpParams = new BasicHttpParams(); // load the keystore containing the client certificate - keystore type is probably jks or pkcs12 final KeyStore keystore = KeyStore.getInstance("pkcs12"); FileInputStream keystoreInput = = new FileInputStream("d:/dev/java/conf/keys/client.p12");; // TODO get the keystore as an InputStream from somewhere keystore.load(keystoreInput, "password".toCharArray()); // load the trustore, leave it null to rely on cacerts distributed with the JVM - truststore type is probably jks or pkcs12 KeyStore truststore = KeyStore.getInstance("JKS"); FileInputStream truststoreInput = = new FileInputStream("d:/dev/java/conf/keys/client.jks");; // TODO get the trustore as an InputStream from somewhere truststore.load(truststoreInput, "password".toCharArray()); final SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("https", new SSLSocketFactory(keystore, keystorePassword, truststore), 443)); final DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParams, schemeRegistry), httpParams);
我使用以下命令启动Tomcat CATALINA_OPTS:
CATALINA_OPTS
set CATALINA_OPTS=%CATALINA_OPTS% -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 set CATALINA_OPTS=%CATALINA_OPTS% -Djavax.net.debug=all
启动时,Tomcat在日志文件中给了我这些错误:
INFO: Starting ProtocolHandler ["http-bio-8080"] Oct 21, 2014 3:46:54 PM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["http-bio-8443"] Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA Oct 21, 2014 3:46:54 PM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["ajp-bio-8009"] Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 Oct 21, 2014 3:46:54 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 3060 ms Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA Allow unsafe renegotiation: false Allow legacy hello messages: true Is initial handshake: true Is secure renegotiation: false http-bio-8443-Acceptor-0, setSoTimeout(60000) called Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA [Raw read]: length = 5 0000: 80 65 01 03 01 .e... http-bio-8443-exec-1, handling exception: javax.net.ssl.SSLHandshakeException: SSLv2Hello is disabled http-bio-8443-exec-1, SEND TLSv1 ALERT: fatal, description = handshake_failure http-bio-8443-exec-1, WRITE: TLSv1 Alert, length = 2 [Raw write]: length = 7 0000: 15 03 01 00 02 02 28 ......( http-bio-8443-exec-1, called closeSocket() http-bio-8443-exec-1, IOException in getSession(): javax.net.ssl.SSLHandshakeException: SSLv2Hello is disabled http-bio-8443-exec-1, called close() http-bio-8443-exec-1, called closeInternal(true)
为什么SSLv2Hello禁用,我如何启用它?
SSLv2Hello
我正在使用以下配置启动客户端:
-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 -Djavax.net.debug=all
这是httpclient尝试连接到服务器时记录的内容:
adding as trusted cert: Subject: CN=GTE CyberTrust Root 5, OU="GTE CyberTrust Solutions, Inc.", O=GTE Corporation, C=US Issuer: CN=GTE CyberTrust Root 5, OU="GTE CyberTrust Solutions, Inc.", O=GTE Corporation, C=US Algorithm: RSA; Serial number: 0x1b6 Valid from Fri Aug 14 17:50:00 IDT 1998 until Thu Aug 15 02:59:00 IDT 2013 adding as trusted cert: Subject: CN=UTN-USERFirst-Object, OU=http://www.usertrust.com, O=The USERTRUST Network, L=Salt Lake City, ST=UT, C=US Issuer: CN=UTN-USERFirst-Object, OU=http://www.usertrust.com, O=The USERTRUST Network, L=Salt Lake City, ST=UT, C=US Algorithm: RSA; Serial number: 0x44be0c8b500024b411d3362de0b35f1b Valid from Fri Jul 09 21:31:20 IDT 1999 until Tue Jul 09 21:40:36 IDT 2019 adding as trusted cert: Subject: CN=UTN - DATACorp SGC, OU=http://www.usertrust.com, O=The USERTRUST Network, L=Salt Lake City, ST=UT, C=US Issuer: CN=UTN - DATACorp SGC, OU=http://www.usertrust.com, O=The USERTRUST Network, L=Salt Lake City, ST=UT, C=US Algorithm: RSA; Serial number: 0x44be0c8b500021b411d32a6806a9ad69 Valid from Thu Jun 24 21:57:21 IDT 1999 until Mon Jun 24 22:06:30 IDT 2019 adding as trusted cert: Subject: CN=Sonera Class2 CA, O=Sonera, C=FI Issuer: CN=Sonera Class2 CA, O=Sonera, C=FI Algorithm: RSA; Serial number: 0x1d Valid from Fri Apr 06 09:29:40 IST 2001 until Tue Apr 06 10:29:40 IDT 2021 adding as trusted cert: Subject: CN=TC TrustCenter Class 2 CA II, OU=TC TrustCenter Class 2 CA, O=TC TrustCenter GmbH, C=DE Issuer: CN=TC TrustCenter Class 2 CA II, OU=TC TrustCenter Class 2 CA, O=TC TrustCenter GmbH, C=DE Algorithm: RSA; Serial number: 0x2e6a000100021fd752212c115c3b Valid from Thu Jan 12 16:38:43 IST 2006 until Thu Jan 01 00:59:59 IST 2026 trigger seeding of SecureRandom done seeding SecureRandom 2014-10-21 16:36:15,296 pool-1-thread-1 DEBUG [SingleClientConnManager] Get connection for route HttpRoute[{s}->https://127.0.0.1:8443] 2014-10-21 16:36:15,316 pool-1-thread-1 DEBUG [DefaultClientConnectionOperator] Connecting to /127.0.0.1:8443 pool-1-thread-1, setSoTimeout(500000) called 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: 1413902175 bytes = { 166, 163, 15, 231, 223, 206, 71, 224, 11, 205, 126, 133, 216, 162, 9, 70, 183, 228, 17, 4, 187, 149, 177, 90, 209, 175, 23, 186 } Session ID: {} Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_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 } *** [write] MD5 and SHA1 hashes: len = 75 0000: 01 00 00 47 03 01 54 46 6F 5F A6 A3 0F E7 DF CE ...G..TFo_...... 0010: 47 E0 0B CD 7E 85 D8 A2 09 46 B7 E4 11 04 BB 95 G........F...... 0020: B1 5A D1 AF 17 BA 00 00 20 00 04 00 05 00 2F 00 .Z...... ...../. 0030: 33 00 32 00 0A 00 16 00 13 00 09 00 15 00 12 00 3.2............. 0040: 03 00 08 00 14 00 11 00 FF 01 00 ........... pool-1-thread-1, WRITE: TLSv1 Handshake, length = 75 [write] MD5 and SHA1 hashes: len = 101 0000: 01 03 01 00 3C 00 00 00 20 00 00 04 01 00 80 00 ....<... ....... 0010: 00 05 00 00 2F 00 00 33 00 00 32 00 00 0A 07 00 ..../..3..2..... 0020: C0 00 00 16 00 00 13 00 00 09 06 00 40 00 00 15 ............@... 0030: 00 00 12 00 00 03 02 00 80 00 00 08 00 00 14 00 ................ 0040: 00 11 00 00 FF 54 46 6F 5F A6 A3 0F E7 DF CE 47 .....TFo_......G 0050: E0 0B CD 7E 85 D8 A2 09 46 B7 E4 11 04 BB 95 B1 ........F....... 0060: 5A D1 AF 17 BA Z.... pool-1-thread-1, WRITE: SSLv2 client hello message, length = 101 [Raw write]: length = 103 0000: 80 65 01 03 01 00 3C 00 00 00 20 00 00 04 01 00 .e....<... ..... 0010: 80 00 00 05 00 00 2F 00 00 33 00 00 32 00 00 0A ....../..3..2... 0020: 07 00 C0 00 00 16 00 00 13 00 00 09 06 00 40 00 ..............@. 0030: 00 15 00 00 12 00 00 03 02 00 80 00 00 08 00 00 ................ 0040: 14 00 00 11 00 00 FF 54 46 6F 5F A6 A3 0F E7 DF .......TFo_..... 0050: CE 47 E0 0B CD 7E 85 D8 A2 09 46 B7 E4 11 04 BB .G........F..... 0060: 95 B1 5A D1 AF 17 BA ..Z.... [Raw read]: length = 5 0000: 15 03 01 00 02 ..... [Raw read]: length = 2 0000: 02 28 .( pool-1-thread-1, READ: TLSv1 Alert, length = 2 pool-1-thread-1, RECV TLSv1 ALERT: fatal, handshake_failure pool-1-thread-1, called closeSocket() pool-1-thread-1, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure pool-1-thread-1, IOException in getSession(): javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure pool-1-thread-1, called close() pool-1-thread-1, called closeInternal(true) 2014-10-21 16:36:15,336 pool-1-thread-1 DEBUG [DefaultClientConnection] Connection closed 2014-10-21 16:36:15,336 pool-1-thread-1 DEBUG [HttpClientImpl] retry count:1 2014-10-21 16:36:15,336 pool-1-thread-1 DEBUG [DefaultClientConnection] Connection shut down pool-1-thread-1, called close() pool-1-thread-1, called closeInternal(true) 2014-10-21 16:36:15,336 pool-1-thread-1 DEBUG [SingleClientConnManager] Releasing connection org.apache.http.impl.conn.SingleClientConnManager$ConnAdapter@1a73d30 Exception postHttpReqest function from http client :javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated Threads done working
有谁知道为什么我无法将客户端连接到服务器?
您可能 不 应该这样做(请让SSL终止!),但是您可以使用这种令人震惊的显而易见的技术 为客户端 启用该SSLv2Hello协议: __
-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2,SSLv2Hello
对于服务器,Tomcat使用sslProtocol和sslEnabledProtocols配置设置来配置自己的SSL端点。您应该在服务器端使用它们。例如:
sslProtocol
sslEnabledProtocols
<Connector sslProtocol="TLS" sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2,SSLv2Hello" ... />
您可以在Oracle有关该主题的博客上找到有关如何诊断SSL / TLS问题的更多信息。