How do I set SSL protocol version in java? And how do I know which one? javax.net.ssl.SSLException: Received fatal alert: protocol_version

匿名 (未验证) 提交于 2019-12-03 02:54:01

问题:

I am using Apache HttpClient 4.3 to interact with the API of hubic.com. My minimal reproducable example is just a one liner:

HttpClientBuilder.create().build().execute(new HttpGet("https://hubic.com")); 

However that throws:

Exception in thread "main" javax.net.ssl.SSLException: Received fatal alert: protocol_version     at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)     at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)     at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1991)     at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1104)     at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)     at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)     at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)     at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)     at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254)     at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:117)     at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314)     at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)     at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)     at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)     at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)     at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)     at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)     at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)     at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106) 

Here is the output if I run with System.setProperty("javax.net.debug", "all");:

trustStore is: /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts trustStore type is : jks trustStore provider is :  init truststore  adding as trusted cert: [... extremely large list ...]  trigger seeding of SecureRandom done seeding SecureRandom Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_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_SHA Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 Allow unsafe renegotiation: false Allow legacy hello messages: true Is initial handshake: true Is secure renegotiation: false Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for SSLv3 Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for SSLv3 Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for SSLv3 Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for SSLv3 Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for SSLv3 Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for SSLv3 Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for SSLv3 Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1 Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 for TLSv1.1 Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 for TLSv1.1 %% No cached client session *** ClientHello, TLSv1.2 RandomCookie:  GMT: 1402182685 bytes = { 227, 155, 148, 161, 7, 104, 221, 182, 254, 133, 216, 198, 118, 211, 223, 229, 43, 82, 207, 1, 102, 245, 112, 117, 253, 69, 43, 162 } Session ID:  {} Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, 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_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, 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_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, 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 Extension server_name, server_name: [type=host_name (0), value=hubic.com] *** [write] MD5 and SHA1 hashes:  len = 225 0000: 01 00 00 DD 03 03 54 94   9C 1D E3 9B 94 A1 07 68  ......T........h 0010: DD B6 FE 85 D8 C6 76 D3   DF E5 2B 52 CF 01 66 F5  ......v...+R..f. 0020: 70 75 FD 45 2B A2 00 00   46 C0 23 C0 27 00 3C C0  pu.E+...F.#.'.<. 0030: 25 C0 29 00 67 00 40 C0   09 C0 13 00 2F C0 04 C0  %.).g.@...../... 0040: 0E 00 33 00 32 C0 2B C0   2F 00 9C C0 2D C0 31 00  ..3.2.+./...-.1. 0050: 9E 00 A2 C0 08 C0 12 00   0A C0 03 C0 0D 00 16 00  ................ 0060: 13 C0 07 C0 11 00 05 C0   02 C0 0C 00 04 00 FF 01  ................ 0070: 00 00 6E 00 0A 00 34 00   32 00 17 00 01 00 03 00  ..n...4.2....... 0080: 13 00 15 00 06 00 07 00   09 00 0A 00 18 00 0B 00  ................ 0090: 0C 00 19 00 0D 00 0E 00   0F 00 10 00 11 00 02 00  ................ 00A0: 12 00 04 00 05 00 14 00   08 00 16 00 0B 00 02 01  ................ 00B0: 00 00 0D 00 1A 00 18 06   03 06 01 05 03 05 01 04  ................ 00C0: 03 04 01 03 03 03 01 02   03 02 01 02 02 01 01 00  ................ 00D0: 00 00 0E 00 0C 00 00 09   68 75 62 69 63 2E 63 6F  ........hubic.co 00E0: 6D                                                 m main, WRITE: TLSv1.2 Handshake, length = 225 [Raw write]: length = 230 0000: 16 03 03 00 E1 01 00 00   DD 03 03 54 94 9C 1D E3  ...........T.... 0010: 9B 94 A1 07 68 DD B6 FE   85 D8 C6 76 D3 DF E5 2B  ....h......v...+ 0020: 52 CF 01 66 F5 70 75 FD   45 2B A2 00 00 46 C0 23  R..f.pu.E+...F.# 0030: C0 27 00 3C C0 25 C0 29   00 67 00 40 C0 09 C0 13  .'.<.%.).g.@.... 0040: 00 2F C0 04 C0 0E 00 33   00 32 C0 2B C0 2F 00 9C  ./.....3.2.+./.. 0050: C0 2D C0 31 00 9E 00 A2   C0 08 C0 12 00 0A C0 03  .-.1............ 0060: C0 0D 00 16 00 13 C0 07   C0 11 00 05 C0 02 C0 0C  ................ 0070: 00 04 00 FF 01 00 00 6E   00 0A 00 34 00 32 00 17  .......n...4.2.. 0080: 00 01 00 03 00 13 00 15   00 06 00 07 00 09 00 0A  ................ 0090: 00 18 00 0B 00 0C 00 19   00 0D 00 0E 00 0F 00 10  ................ 00A0: 00 11 00 02 00 12 00 04   00 05 00 14 00 08 00 16  ................ 00B0: 00 0B 00 02 01 00 00 0D   00 1A 00 18 06 03 06 01  ................ 00C0: 05 03 05 01 04 03 04 01   03 03 03 01 02 03 02 01  ................ 00D0: 02 02 01 01 00 00 00 0E   00 0C 00 00 09 68 75 62  .............hub 00E0: 69 63 2E 63 6F 6D                                  ic.com [Raw read]: length = 5 0000: 15 03 00 00 02                                     ..... [Raw read]: length = 2 0000: 02 46                                              .F main, READ: SSLv3 Alert, length = 2 main, RECV TLSv1.2 ALERT:  fatal, protocol_version main, called closeSocket() main, handling exception: javax.net.ssl.SSLException: Received fatal alert: protocol_version 

No exception is thrown if I try to access e.g. https://google.com. So it guess SSL with Java cannot be completely broken on my system but it has to do with the combination with hubic.com.

The error protocol_version is not very helpful, but in this question it is suggested that my client uses another protocol version than the server (I guess "server and client could not agree on a protocol" would be more accurate).

How do I figure out which protocol versions the server will agree on and how do I enable those in my client? And should I worry about the issue (e.g. like does hubic only allow an old unsupported protocol? (Firefox certainly does not complain about anything unsecure).

回答1:

I see from the debug that Java does a TLS1.2 handshake instead of the more common SSLv23 handshake:

main, WRITE: TLSv1.2 Handshake, length = 225 [Raw write]: length = 230 0000: 16 03 03 00          ^^^^^ - TLS1.2 (SSL3.3) 

The server itself can do only TLS1.0 and fails to just announce this older version. I'm not familiar with Java, but you either need set the protocol version to TLSv1 or SSLv23 to speak with this server.

The following code would set only TLSv1 with Apache HttpClient:

HttpClientBuilder   .create()   .setSslcontext(SSLContexts.custom().useProtocol("TLSv1").build())   .build()   .execute(new HttpGet("https://hubic.com")); 

EDIT to include question from comment:

If you say that the server "fails to just announce this older version", does that mean that the server is misconfigured? In this case, why don't Firefox&Chromium have any problems?

If the client announces TLS1.2 in the ClientHello and the server can do only TLS1.0 it should announce this, i.e. reply with TLS1.0. The client can then close the connection if TLS1.0 is not good enough or continue with TLS1.0. But, in this case the server just told the client that it does not like this version and closed the connection. Firefox and others instead do a SSLv23 announcement, where they do a TLS1.0 handshake but also announce the best protocol version they support. This usually works good for older servers starting from SSL3.0 but also for newer servers.

You can check the behavior of the server with a recent Perl/IO::Socket::SSL and this script.

$ perl analyze-ssl.pl hubic.com -- hubic.com port 443  * maximum SSL version  : TLSv1 (SSLv23)  * supported SSL versions with handshake used and preferred cipher(s):    * handshake protocols ciphers    * SSLv23    TLSv1     AES256-SHA    * TLSv1_2   FAILED: SSL connect attempt failed error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number    * TLSv1_1   FAILED: SSL connect attempt failed error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number    * TLSv1     TLSv1     AES256-SHA    * SSLv3     FAILED: SSL connect attempt failed because of handshake problems error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version 

Here you can see, that the hosts supports SSLv23 and TLSv1 handshakes, but not the used TLSv1_2 handshake.



回答2:

HttpClient can take an SSLContext for its SSLConnectionSocketFactory.

You can set the appropriate TLS version in the properties for the SSLContext with the getInstance static method.

Something like SSLContext context = SSLContext.getInstance("TLSv1");

If you need to force just one protocol (as getInstance can return one that supports multiple protocols), you can use the setEnabledProtocols method (which takes a String[]) on the context you retrieved using getInstance.



回答3:

I have also come across this issue. Certain sites are not accessible, throwing the mysterious: javax.net.ssl.SSLException: Received fatal alert: protocol_version

I have tried to mend it, following some of the hints given here, but without success. At one point the usual thought “it used to work before..”, really started nagging me.

Initially I had assumed something had changed in the site I tried to connect to. However, as this is a legacy kind of site, it wasn’t so likely. So, what else could it be..? At one point I thought “Java version”. Unlikely, but maybe worth a try.

As it is, I can get the content from previously error-throwing sites, if I compile my code with SDK 1.6.0_25. Newer versions gives me problems: 1.7.0_51, and 1.8.0.

I have boiled it down to the smallest piece possible, if effect reproducing the one-liner initially posted by “Yankee” above. I have used the same line, including the same URL.

Compiling with SDK 1.6 it works.

I am not sufficiently skilled in Java and SSL to understand the root issue behind this. But, someone ought to be able to put the code side by side, and track it down..

This may save someone a few wasted hours.



回答4:

It looks like you are not using java 1.8

In Java 1.8 the default TLS protocol version is v1.2, whereas in Java 1.6,1.7 default is TLS1.0. As you can see in logs ClientHello, TLSv1.2 it means you are either using java 1.6 or 1.7 now you can either switch to 1.8 or Just add

static { System.setProperty("https.protocols", "TLSv1.2"); }

in your application class before main class keeping you current java version
.. hope this helps !!



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!