Elasticsearch throws a SSLHandshakeException: Client requested protocol TLSv1.2 is not enabled or supported in server context

Hello there,

I am trying to configure Elasticsearch 8.5 to support both TLSv1.3 AND TLSv1.2 communication, but following all documentation available, but it still supports TLSv1.3 only.
I did the basic setup following this [Security Basic Setup](https://www.elastic.co/guide/en/elasticsearch/reference/8.5/security-basic-setup-https.html)
In the elasticsearch I added:

xpack.security.http.ssl:
  enabled: true
  keystore.path: certs/elasticsearch/http.p12
  truststore.path: certs/elasticsearch/http.p12
  supported_protocols: ["TLSv1.3", "TLSv1.2"]
  cipher_suites: ["TLS_AES_256_GCM_SHA384",
                  "TLS_AES_128_GCM_SHA256",
                  "TLS_CHACHA20_POLY1305_SHA256",
                  "ECDHE-ECDSA-AES128-GCM-SHA256",
                  "ECDHE-RSA-AES128-GCM-SHA256",
                  "ECDHE-ECDSA-AES256-GCM-SHA384",
                  "ECDHE-RSA-AES256-GCM-SHA384",
                  "ECDHE-ECDSA-CHACHA20-POLY1305",
                  "ECDHE-RSA-CHACHA20-POLY1305",
                  "DHE-RSA-AES128-GCM-SHA256",
                  "DHE-RSA-AES256-GCM-SHA384"]

xpack.security.transport.ssl:
  enabled: true
  verification_mode: certificate
  client_authentication: required
  keystore.path: certs/elastic-certificates.p12
  truststore.path: certs/elastic-certificates.p12
  supported_protocols: ["TLSv1.3", "TLSv1.2"]
  cipher_suites: ["TLS_AES_256_GCM_SHA384",
                  "TLS_AES_128_GCM_SHA256",
                  "TLS_CHACHA20_POLY1305_SHA256",
                  "ECDHE-ECDSA-AES128-GCM-SHA256",
                  "ECDHE-RSA-AES128-GCM-SHA256",
                  "ECDHE-ECDSA-AES256-GCM-SHA384",
                  "ECDHE-RSA-AES256-GCM-SHA384",
                  "ECDHE-ECDSA-CHACHA20-POLY1305",
                  "ECDHE-RSA-CHACHA20-POLY1305",
                  "DHE-RSA-AES128-GCM-SHA256",
                  "DHE-RSA-AES256-GCM-SHA384"]

As I read in [this JDK TLS versions documentation](https://www.elastic.co/guide/en/elasticsearch/reference/8.5/jdk-tls-versions.html#jdk-enable-tls-protocol), I also added to Java options:
-Djdk.tls.client.protocols=TLSv1.3,TLSv1.2
-Dhttps.protocols=TLSv1.3,TLSv1.2
-Dcrypto.policy=unlimited (it seems to be default, but there is another error message on the beginning that states: unsupported ciphers [[...]] were requested but cannot be used in this JVM, however there are supported ciphers that will be used [[...]]. If you are trying to use ciphers with a key length greater than 128 bits on an Oracle JVM, you will need to install the unlimited strength JCE policy files, which leads me to try reinforce this setting, although I believe that is a misleading message since JCE policy files are all configured to unlimited strength in this version, but this issue is not a blocker for now... let's go back to the subject :sweat_smile:)
These options were added to $ELASTICSEARCH_INSTALLATION_PATH/jdk/conf/security/es.java.security and then $ELASTICSEARCH_INSTALLATION_PATH/config/jvm.options.d/java.security.options file was created with an entry:

-Djava.security.properties=......../jdk/conf/security/es.java.security

I can see that Elasticsearch started with this option properly set by doing ps -uf | grep "\-Djdk.tls.client.protocols"
but when I try to test a request with TLSv1.2

curl --user elastic \
     --cacert $ELASTICSEARCH_INSTALLATION_PATH/config/certs/client-ca.cer \
     --cert $ELASTICSEARCH_INSTALLATION_PATH/config/certs/client.cer \
     --key $ELASTICSEARCH_INSTALLATION_PATH/config/certs/client.key \
     --request GET "$ELASTICSEARCH_HOST:$ELASTICSEARCH_PORT" \
     --verbose \
     --ciphers DHE-RSA-AES128-GCM-SHA256,DHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-RSA-CHACHA20-POLY1305,TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_CCM_8_SHA256,TLS_AES_128_CCM_SHA256 \
     --tlsv1.2 --tls-max 1.2

It just throw an exception:

[2023-03-22T21:10:29,633][WARN ][o.e.h.AbstractHttpServerTransport] [eb-elk-node-1] caught exception while handling client http traffic, closing connection Netty4HttpChannel{localAddress=/10.117.159.100:9200, remoteAddress=/10.117.159.100:59596}io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Client requested protocol TLSv1.2 is not enabled or supported in server context
        at io.netty.codec@4.1.77.Final/io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:480)
        at io.netty.codec@4.1.77.Final/io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279)
        at io.netty.transport@4.1.77.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.transport@4.1.77.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.transport@4.1.77.Final/io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)

See logs for more details.

There is no additional relevant information in the logs. So I tried again, but this time added the parameters directly:

echo "-Djdk.tls.client.protocols=TLSv1.3,TLSv1.2
-Dhttps.protocols=TLSv1.3,TLSv1.2
-Dcrypto.policy=unlimited
" > $ELASTICSEARCH_INSTALLATION_PATH/config/jvm.options.d/java.security.options

I also can see that Elasticsearch started with all these options, but when I try to execute the same curl test, I got the same exception "javax.net.ssl.SSLHandshakeException: Client requested protocol TLSv1.2 is not enabled or supported in server context...."
Does anyone knows how to configure the Elasticsearch and/or its bundled JDK properly to support TLSv1.2 ?

Are you using the bundled JDK? TLSv1.2 should be supported by default.

BTW, java security policy configuraiton is not through system properties, .e.g. -Dcrypto.policy=unlimited does not work. But that should be irrelevant for your problem because TLSv1.2 should be supported out of the box if you are using bundled JDK.

The documentation also states that. The point is when I force TLSv1.2 using this curl command:

curl --user elastic \
     --cacert $ELASTICSEARCH_INSTALLATION_PATH/config/certs/client-ca.cer \
     --cert $ELASTICSEARCH_INSTALLATION_PATH/config/certs/client.cer \
     --key $ELASTICSEARCH_INSTALLATION_PATH/config/certs/client.key \
     --request GET "$ELASTICSEARCH_HOST:$ELASTICSEARCH_PORT" \
     --verbose \
     --ciphers DHE-RSA-AES128-GCM-SHA256,DHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-RSA-CHACHA20-POLY1305,TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_CCM_8_SHA256,TLS_AES_128_CCM_SHA256 \
     --tlsv1.2 --tls-max 1.2

Elasticsearch simply throws an error saying that TLSv1.2 is not supported:

[2023-03-22T21:10:29,633][WARN ][o.e.h.AbstractHttpServerTransport] [eb-elk-node-1] caught exception while handling client http traffic, closing connection Netty4HttpChannel{localAddress=/10.117.159.100:9200, remoteAddress=/10.117.159.100:59596}io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Client requested protocol TLSv1.2 is not enabled or supported in server context
        at io.netty.codec@4.1.77.Final/io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:480)
        at io.netty.codec@4.1.77.Final/io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279)
        at io.netty.transport@4.1.77.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.transport@4.1.77.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.transport@4.1.77.Final/io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)

See logs for more details.

Is there any missing configuration in my elasticsearch.yml? The changes I made are basically those I put above.

Even though both TLS versions are set as supported protocols, Elasticsearch still starts with TLSv1.3 as we can understand from this misleading error message:

[2023-03-24T13:08:21,639][ERROR][o.e.x.c.s.SSLService     ] [eb-elk-node-1] unsupported ciphers [[ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-ECDSA-CHACHA20-POLY1305, ECDHE-RSA-CHACHA20-POLY1305, DHE-RSA-AES128-GCM-SHA256, DHE-RSA-AES256-GCM-SHA384]] were requested but cannot be used in this JVM, however there are supported ciphers that will be used [[TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256]]. If you are trying to use ciphers with a key length greater than 128 bits on an Oracle JVM, you will need to install the unlimited strength JCE policy files.

And yes, I am using the bundled JDK, there is no environment variable changing it.
image

You need look into elasticsearch log to be sure. At node launch time, ES will log information about the JDK it is using. Please make sure it says something like ... using bundled JDK [true].

Ok, I am definitely using bundled JDK :point_up_2:

Since no where else were changed, do you have any idea of why this error is thrown when we try to use TLSv1.2?

OK thanks for checking. It turns out that the cipher suites you configured is not compatible with TLSv1.2. In fact, most of them are not recognisable by JVM. You should see a logging line like the follows in your server log

unsupported ciphers [[ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-ECDSA-CHACHA20-POLY1305, ECDHE-RSA-CHACHA20-POLY1305, DHE-RSA-AES128-GCM-SHA256, DHE-RSA-AES256-GCM-SHA384]] were requested but cannot be used in this JVM, however there are supported ciphers that will be used [[TLS_AES_256_GCM_SHA384, TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256]]. If you are trying to use ciphers with a key length greater than 128 bits on an Oracle JVM, you will need to install the unlimited strength JCE policy files.

You should check the jdk doc for the correct cipher suite names. The ones that are usable (from the above logging line) are all for TLSv1.3. That's why the connection using TLSv1.2 is failing. For it to work, you need add a supported cipher suite. For example, if you have TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 in the cipher suites, you will be able to make connection with TLSv1.2 using the following curl command

curl -v -k --tlsv1.2 --tls-max 1.2 --ciphers ECDHE-RSA-AES256-GCM-SHA384 https://ES_HOST:9200

NOTE curl requires cipher suites to be separated with colon (:) instead of comma (,).

1 Like

Thank you for the help @Yang_Wang ! Now it is working.
The problem was that cipher suite list I configured in elasticsearch.yml was using OpenSSL naming, after changing to IANA naming based on this correspondence table, it worked. Thank you very much!
NOTE my curl command is actually correct, it does accept both colon (:) and comma (,).

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.