2017-02-21 3 views
0

비슷한 문제에 많은 게시물이있는 것 같지만 저에게 도움이되는 정보는 찾을 수 없습니다.프로덕션 서버에서만 Java HttpClient SSL 핸드 셰이크 예외가 발생했습니다.

특정 URL을 얻기 위해 HttpClient 4.3.5를 사용하는 Java 7의 코드가 있습니다. 이 코드는 mvn 테스트를 통해 로컬로 실행하거나 Tomcat 서버에 배포 할 때 작동하지만 프로덕션 서버의 Tomcat에서 실행될 때 SSL 핸드 셰이크 예외로 실패합니다. 나는 아래 코드를 사용한다. (httpclient가 어떻게 설정되었는지는 무시한다. 그것은 잘못 설정되어 있어도 모든 사이트와 인증서를 처리 할 수있다.) -Djavax를 사용하여 스택 추적을한다. net.debug = 모두 추가 로깅 세부 사항을 얻기 위해 tomcat 런타임에 포함됩니다. Java Cryptography Unlimited Strength Jurisdiction Policy Extension을 구현했으며 탄력성을 추가하여 대부분의 사이트에서 코드를 사용할 수있었습니다. 현재 프로덕션 서버에서만 오류가 있지만 로컬에서는 잘 작동하는 단일 사이트를 제외하고는 거의 모든 시스템에서 작동하는 것으로 보입니다.

내 코드 :

Security.insertProviderAt(new BouncyCastleProvider(), 1); 
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
SSLContextBuilder sslBuilder = new SSLContextBuilder(); 
sslBuilder.loadTrustMaterial(trustStore, new TrustStrategy() { 
    @Override 
    public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { 
     return true; 
    } 
}); 

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslBuilder.build(), new String[] { "TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3"}, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
PlainConnectionSocketFactory pcsf = new PlainConnectionSocketFactory(); 
Registry socketFactoryRegistry = RegistryBuilder.create().register("https", sslsf).register("http", pcsf).build(); 
multiConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); 
multiConnectionManager.setMaxTotal(100); 
multiConnectionManager.setDefaultMaxPerRoute(10); 
httpClientBuilder.setConnectionManager(multiConnectionManager); 
this.httpClient = httpClientBuilder.disableContentCompression().setSSLSocketFactory(sslsf).build(); 

HttpGet call = new HttpGet(url); 
HttpResponse getResponse; 
    try { 
     call.addHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)"); 
     call.addHeader("Accept","text/html"); 
     call.setConfig(RequestConfig.custom().setCircularRedirectsAllowed(true).setMaxRedirects(5).setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()); 
     try { 
      getResponse = httpClient.execute(call); 
     } 
     catch (Exception ex) {} 
    } 
    catch (Exception ex) {} 

스택 트레이스 :

trigger seeding of SecureRandom 
done seeding SecureRandom 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 
Allow unsafe renegotiation: false 
Allow legacy hello messages: true 
Is initial handshake: true 
Is secure renegotiation: false 
Ignoring disabled protocol: SSLv3 
%% No cached client session 
*** ClientHello, TLSv1.2 
RandomCookie: GMT: 1470874697 bytes = { 159, 94, 240, 233, 124, 91, 106, 83, 249, 126, 156, 56, 200, 67, 114, 18, 205, 36, 55, 140, 229, 223, 66, 190, 204, 226, 223, 90 } 
Session ID: {} 
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 
Compression Methods: { 0 } 
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1} 
Extension ec_point_formats, formats: [uncompressed] 
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA 
*** 
[write] MD5 and SHA1 hashes: len = 181 
0000: 01 00 00 B1 03 03 58 AC C4 49 9F 5E F0 E9 7C 5B ......X..I.^...[ 
0010: 6A 53 F9 7E 9C 38 C8 43 72 12 CD 24 37 8C E5 DF jS...8.Cr..$7... 
0020: 42 BE CC E2 DF 5A 00 00 2C C0 0A C0 14 00 35 C0 B....Z..,.....5. 
0030: 05 C0 0F 00 39 00 38 C0 09 C0 13 00 2F C0 04 C0 ....9.8...../... 
0040: 0E 00 33 00 32 C0 08 C0 12 00 0A C0 03 C0 0D 00 ..3.2........... 
0050: 16 00 13 00 FF 01 00 00 5C 00 0A 00 34 00 32 00 ........\...4.2. 
0060: 17 00 01 00 03 00 13 00 15 00 06 00 07 00 09 00 ................ 
0070: 0A 00 18 00 0B 00 0C 00 19 00 0D 00 0E 00 0F 00 ................ 
0080: 10 00 11 00 02 00 12 00 04 00 05 00 14 00 08 00 ................ 
0090: 16 00 0B 00 02 01 00 00 0D 00 1A 00 18 06 03 06 ................ 
00A0: 01 05 03 05 01 04 03 04 01 03 03 03 01 02 03 02 ................ 
00B0: 01 02 02 01 01          ..... 
ActiveMQ Session Task-2, WRITE: TLSv1.2 Handshake, length = 181 
[Raw write]: length = 186 
0000: 16 03 03 00 B5 01 00 00 B1 03 03 58 AC C4 49 9F ...........X..I. 
0010: 5E F0 E9 7C 5B 6A 53 F9 7E 9C 38 C8 43 72 12 CD ^...[jS...8.Cr.. 
0020: 24 37 8C E5 DF 42 BE CC E2 DF 5A 00 00 2C C0 0A $7...B....Z..,.. 
0030: C0 14 00 35 C0 05 C0 0F 00 39 00 38 C0 09 C0 13 ...5.....9.8.... 
0040: 00 2F C0 04 C0 0E 00 33 00 32 C0 08 C0 12 00 0A ./.....3.2...... 
0050: C0 03 C0 0D 00 16 00 13 00 FF 01 00 00 5C 00 0A .............\.. 
0060: 00 34 00 32 00 17 00 01 00 03 00 13 00 15 00 06 .4.2............ 
0070: 00 07 00 09 00 0A 00 18 00 0B 00 0C 00 19 00 0D ................ 
0080: 00 0E 00 0F 00 10 00 11 00 02 00 12 00 04 00 05 ................ 
0090: 00 14 00 08 00 16 00 0B 00 02 01 00 00 0D 00 1A ................ 
00A0: 00 18 06 03 06 01 05 03 05 01 04 03 04 01 03 03 ................ 
00B0: 03 01 02 03 02 01 02 02 01 01     .......... 
[Raw read]: length = 5 
0000: 15 03 03 00 02          ..... 
[Raw read]: length = 2 
0000: 02 28            .(
ActiveMQ Session Task-2, READ: TLSv1.2 Alert, length = 2 
ActiveMQ Session Task-2, RECV TLSv1 ALERT: fatal, handshake_failure 
ActiveMQ Session Task-2, called closeSocket() 
ActiveMQ Session Task-2, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 

사람이 리눅스 박스를 실행 (이 악수 오류가 발생하는 이유와 단지 프로덕션 서버에 무슨 일이 일어나고 왜 문제를 해결하기 위해 제공 할 수있는 어떤 도움 Tomcat을 통한 자바 코드) 그리고 나에게 로컬로 잘 작동한다. (맥은 mvn이나 java 코드를 통해 tomcat을 통해 단위 테스트를 실행한다.) 가장 도움이 될 것이다.

+0

서버가 hello를 좋아하지 않습니다. 엄청난 가능성이 있지만 확실한 가능성은 ServerNameIndication ** 일명 SNI가 아닙니다. SNI를 보내고 있는지 확인하려면 작업중인 (현지) 사례를 확인하십시오. 그렇지만 증명되지 않으면 두 곳을 실행중인 HttpClient를 정확히 다시 확인하십시오 (특히 둘 이상이있는 경우). 어쩌면 자바 버전을 검사 할 수도 있습니다. 나는 7 년 안에 이것에 대한 어떤 변화도 기억하지 못한다. 그러나 나는 쉽게 잊을 수 있었다. –

+0

@ dave_thompson_085 이미 동일한 버전의 java가 둘 다 실행되고 있음을 확인했습니다. HttpClient의 동일한 버전이 사용되고 있는지, tomcat이나 다른 것으로 덮어 쓰지 않는지 확인하려고 시도합니다. 마지막으로 SNI를 현지 사례에 보내는 경우 어떻게 확인합니까? 로그는 실패한 대신에 성공하고 계속 진행된다는 것을 제외하고는 위에 게시 한 로그와 거의 동일하게 보입니다. 문제 해결에 도움이된다면 내 로컬에서 성공을위한 전체 로그를 포함 할 수 있습니다. – Ben

+0

SNI가 전송되면 ClientHello의 추적에 'Extension server_name, ...'으로 표시됩니다 (http://stackoverflow.com/questions/32341729/apache-http-client-defaults-dont-work 참조). (예를 들어 httpclient의 바람직하지 않은 이전 버전이 사용되었다는 문제가 정확히 발생한 사람이) 예를 들어 설명합니다. –

답변

0

마지막으로 알아 냈습니다. 나는 올바른 방향으로 나를 가리키기 위해 dave_thompson_085를 완전히 신용했다. 그것은 SNI 문제였습니다.

HttpClient를 사용하고있는 이래로 4.3.5 SNI가 내 로컬 환경과 테스트에서 기본적으로 활성화되었지만 Tomcat에서는 오래된 라이브러리를 가져 오거나 다른 구성이 설정되어있었습니다 프로덕션 서버에서 사용할 수 없게됩니다. 따라서 단순히 시스템 속성 설정 : 코드에로드 된 HttpClient를 라이브러리 전에

System.setProperty("jsse.enableSNIExtension", "true"); 

을 한 후 완전히 문제를 해결 프로덕션 서버에 바람둥이에 재배치.

관련 문제