2013-03-21 31 views
6

Tôi có một Tomcat7 web-server mà tôi đã cố gắng để cấu hình để chấp nhận các kết nối an toàn bằng cách thêm kết nối này cho server.xml file:SSLHandshakeException: Nhận cảnh báo gây tử vong: handshake_failure khi thiết mật mã trên tomcat 7 máy chủ

<Connector SSLEnabled="true" 
      acceptCount="100" 
      connectionTimeout="20000" 
      executor="tomcatThreadPool" 
      keyAlias="server" 
      keystoreFile="c:\opt\engine\conf\tc.keystore" 
      keystorePass="o39UI12z" 
      maxKeepAliveRequests="15" 
      port="8443" 
      protocol="HTTP/1.1" 
      redirectPort="8443" 
      scheme="https" 
      secure="true" 
      sslProtocol="TLS"/> 

tôi đang sử dụng chứng chỉ tự ký được tạo bằng lệnh này:

%JAVA_HOME%/bin/keytool -genkeypair -keystore c:\opt\engine\conf\tc.keystore -storepass o39UI12z-keypass o39UI12z-dname "cn=Company, ou=Company, o=Com, c=US" -alias server -validity 36500 

Phía khách hàng Tôi có ứng dụng mùa xuân kết nối với máy chủ sử dụng RestTemplate. Khi khởi động bối cảnh ứng dụng tôi initalize các restTemplate dụ theo cách này:

final ClientHttpRequestFactory clientHttpRequestFactory = 
     new MyCustomClientHttpRequestFactory(new NullHostNameVerifier(), serverInfo); 
    restTemplate.setRequestFactory(clientHttpRequestFactory); 

Các MyCustomClientHttpRequestFactory lớp trông như thế này:

public class MyCustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory { 

private static final Logger LOGGER = LoggerFactory 
    .getLogger(MyCustomClientHttpRequestFactory.class); 

private final HostnameVerifier hostNameVerifier; 
private final ServerInfo serverInfo; 

public MyCustomClientHttpRequestFactory (final HostnameVerifier hostNameVerifier, 
    final ServerInfo serverInfo) { 
    this.hostNameVerifier = hostNameVerifier; 
    this.serverInfo = serverInfo; 
} 

@Override 
protected void prepareConnection(final HttpURLConnection connection, final String httpMethod) 
    throws IOException { 
    if (connection instanceof HttpsURLConnection) { 
     ((HttpsURLConnection) connection).setHostnameVerifier(hostNameVerifier); 
     ((HttpsURLConnection) connection).setSSLSocketFactory(initSSLContext() 
      .getSocketFactory()); 
    } 
    super.prepareConnection(connection, httpMethod); 
} 

private SSLContext initSSLContext() { 
    try { 
     System.setProperty("https.protocols", "TLSv1"); 

     // Set ssl trust manager. Verify against our server thumbprint 
     final SSLContext ctx = SSLContext.getInstance("TLSv1"); 
     final SslThumbprintVerifier verifier = new SslThumbprintVerifier(serverInfo); 
     final ThumbprintTrustManager thumbPrintTrustManager = 
      new ThumbprintTrustManager(null, verifier); 
     ctx.init(null, new TrustManager[] { thumbPrintTrustManager }, null); 
     return ctx; 
    } catch (final Exception ex) { 
     LOGGER.error(
      "An exception was thrown while trying to initialize HTTP security manager.", ex); 
     return null; 
    } 
} 

Cho đến đây tất cả mọi thứ làm việc tốt. Khi tôi đặt điểm ngắt trong lớp SslThumbprintVerifier, mã đã đạt đến điểm này và cũng vào lớp NullHostNameVerifier. Điều này đã được thử nghiệm trong sản xuất và làm việc tuyệt vời.

Bây giờ tôi muốn mở rộng an ninh bằng cách hạn chế các bộ mã hoá và tôi đã thêm tài sản này để Connector tôi đã trình bày ở phần đầu:

ciphers="TLS_KRB5_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_SHA,SSL_DHE_RSA_WITH_AES_256_CBC_SHA,SSL_RSA_WITH_AES_256_CBC_SHA,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_3DES_EDE_CBC_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_KRB5_WITH_3DES_EDE_CBC_SHA" 

Bây giờ khi tôi đang chạy các mã khách hàng tôi nhận được ngoại lệ này:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 

Điều này xảy ra theo phương pháp restTemplate.doExecute(). Mã không đạt đến lớp xác minh vân tay cũng như lớp trình xác minh tên máy chủ như trước khi thêm mật mã.

Trong debug Tôi đã kiểm tra ctx.getSocketFactory().getSupportedCipherSuites() cho thấy:

[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, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA, SSL_DH_anon_WITH_RC4_128_MD5, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_256_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5] 

và cũng kiểm tra ctx.getSocketFactory().getDefaultCipherSuites():

[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] 

và cuối cùng các ctx.getSupportedSSLParameters().getCipherSuites():

[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, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA, SSL_DH_anon_WITH_RC4_128_MD5, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_256_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_RC4_40_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5] 

Theo như tôi hiểu, nếu có một giao điểm giữa sup của khách hàng các bộ mã hóa được bật/bật và bộ mã hóa được hỗ trợ của máy chủ sẽ hoạt động (chúng tôi có giao điểm như vậy với ví dụ SSL_RSA_WITH_RC4_128_SHA). Và tôi nhận được lỗi này.

Trong bước tiếp theo tôi đã thêm tham số này java:

-Djavax.net.debug=ssl,handshake,failure 

Nhật ký cho thấy chỉ có client-xin chào, không có server-xin chào đáp:

 

[2013-03-20 15:29:51.315] [INFO ] data-service-pool-37   System.out              trigger seeding of SecureRandom 
[2013-03-20 15:29:51.315] [INFO ] data-service-pool-37   System.out              done seeding SecureRandom 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37   System.out              Allow unsafe renegotiation: false 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37   System.out              Allow legacy hello messages: true 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37   System.out              Is initial handshake: true 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37   System.out              Is secure renegotiation: false 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37   System.out              %% No cached client session 
[2013-03-20 15:30:38.894] [INFO ] data-service-pool-37   System.out              *** ClientHello, TLSv1 
[2013-03-20 15:30:38.941] [INFO ] data-service-pool-37   System.out              RandomCookie: GMT: 1363720446 bytes = { 99, 249, 173, 214, 110, 82, 58, 52, 189, 92, 74, 169, 133, 128, 250, 109, 160, 64, 112, 253, 50, 160, 255, 196, 85, 93, 33, 172 } 
[2013-03-20 15:30:38.941] [INFO ] data-service-pool-37   System.out              Session ID: {} 
[2013-03-20 15:30:38.941] [INFO ] data-service-pool-37   System.out              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] 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37   System.out              Compression Methods: { 0 } 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37   System.out              *** 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37   System.out              data-service-pool-37, WRITE: TLSv1 Handshake, length = 81 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37   System.out              data-service-pool-37, READ: TLSv1 Alert, length = 2 
[2013-03-20 15:30:38.956] [INFO ] data-service-pool-37   System.out              data-service-pool-37, RECV TLSv1 ALERT: fatal, handshake_failure 
[2013-03-20 15:30:38.972] [INFO ] data-service-pool-37   System.out              data-service-pool-37, called closeSocket() 
[2013-03-20 15:30:38.972] [INFO ] data-service-pool-37   System.out              data-service-pool-37, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 
 

Khi tháo thuật toán mã hóa từ server.xml nó hoạt động trở lại. Ngoài ra tôi sẽ đề cập đến rằng tôi đang thử nghiệm cả máy chủ và máy khách trên cùng một máy. Tôi đã thử đặt ip của máy chủ trong yêu cầu của máy khách thành 'localhost' và thành ip máy thực tế và nó không hoạt động trong cả hai trường hợp.Ngoài ra, tôi đã có máy chủ này chạy trên một máy linux khác nhau (keystore được tạo ra trên máy linux với một đường dẫn linux của khóa học) và vẫn còn - nó hoạt động mà không có mật mã và ngừng làm việc với mật mã.

Trả lời

12

Vâng, tôi đã giải quyết được sự cố này. Có vẻ như bằng cách tạo chứng chỉ tự ký, sử dụng keytool, mà không cung cấp tham số -keyalg làm cho thuật toán ghép nối khóa mặc định thành DSA. Không có bộ mật mã của tôi bao gồm thuật toán DSA. Trong trường hợp đó, mặc dù máy khách và máy chủ có giao điểm giữa các bộ mã hóa của chúng, nhưng cũng không phù hợp với thuật toán chính.

Thêm -keyalg RSA khi tạo kho khóa, giải quyết được sự cố.