Jira server throws SSL handshake failure errors when behind a proxy
Platform notice: Server and Data Center only. This article only applies to Atlassian products on the Server and Data Center platforms.
Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Problem
JIRA is running behind the proxy which is configured with SSL. JIRA is throwing the following SSL handshake_failure error.
The following appears in the atlassian-jira.log
2018-01-10 18:09:55,431 http-nio-8080-exec-5 ERROR [c.a.g.r.internal.http.HttpClientFetcher] Unable to perform a request to: https://<jira-hostname/rest/gadgets/1.0/g/messagebundle/und/gadget.common%2Cgadget.activity.stream
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
Same problem is reproducible with HttpClientTest
Diagnosis
Proxy
Nginx has been configured with the following strong ciphers:
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA;
Nmap output shows the same:
[root@jira ~]# nmap --script ssl-enum-ciphers -p 443 <jira-hostname> Starting Nmap 6.40 ( http://nmap.org ) at 2018-01-10 18:14 CET Nmap scan report for <base-hostname> (IP.IP.IP.IP) Host is up (-1600s latency). PORT STATE SERVICE 443/tcp open https | ssl-enum-ciphers: ... | TLSv1.2: | ciphers: | TLS_DHE_RSA_WITH_AES_256_CBC_SHA - strong | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - strong | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - strong | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - strong
Execute the following command to return the output:
nmap --script ssl-enum-ciphers -p 443 <jira-hostname>
JAVA DEBUG
Enable SSL DEBUG, add the following option to JVM parameters:
-Djavax.net.debug=ssl:handshake:verbose
In catalina.out you will get detailed logging, this snippet shows cipher suites which JAVA is not going to use. These ciphers are unavailable due to restrictions:
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
Also you can see logging for TLS handshake:
*** ClientHello, TLSv1.2 RandomCookie: GMT: 1515604257 bytes = { 167, 25, 54, 55, 56, 23, 147, 10, 79, 186, 46, 41, 32, 220, 5, 179, 169, 6, 109, 111, 30, 179, 70, 123, 93, 141, 30, 47 } 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_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, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA Extension server_name, server_name: [type=host_name (0), value=jira.company.com] *** HealthCheck:thread-4, WRITE: TLSv1.2 Handshake, length = 221 HealthCheck:thread-4, READ: TLSv1.2 Alert, length = 2 HealthCheck:thread-4, RECV TLSv1.2 ALERT: fatal, handshake_failure HealthCheck:thread-4, called closeSocket() HealthCheck:thread-4, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
- Note that list of Cipher Suites section. Ciphers advertised by JAVA doesn't have overlap with the list from Nginx.
Cause
- Java doesn't support 256-bit encryption w/o JCE, quote from Security - SunProviders - importlimits
- If stronger algorithms are needed (for example, AES with 256-bit keys), the JCE Unlimited Strength Jurisdiction Policy Files must be obtained and installed in the JDK/JRE
- Since these ciphers are using 256-bit encryption, Java will not support them by default (up to 8u161, see below), so there is no overlap with the list from Nginx. That leads to handshake_failure
- Starting from Java 8u161 Unlimited cryptography enabled by default, see Java 8u161 relnotes
Resolution
- One of the options could be low the encryption at proxy, eg: set TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- If stronger algorithms are needed (for example, AES with 256-bit keys), the JCE Unlimited Strength Jurisdiction Policy files must be obtained and installed in the JDK/JRE.
- Download the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8 Download
- Extract the jce\local_policy.jar and jce\US_export_policy.jar files from the archive to the JAVA_HOME directory that JIRA is currently using for eg. /opt/atlassian/jira/jre/lib/security
- Restart JIRA