Troubleshooting Eclipse Jetty SSL Certificates

Problem

You have received a RSA certificate from your organization to enable HTTPS within Nexus Repository Manager or IQ Server. You've imported the certificate into a Java keystore file and pointed the Jetty configuration at it.

The server appears to start up fine without errors, and the logs indicate that the server is listening on the secure port. You have confirmed that the server is listening on that port with network tools (netstat, lsof).

However, when you access the secure port in a web browser or command line tool, even from the same host as the server, you can't connect to the secure port. What is going wrong?

Symptoms

Nexus Repository Manager Server or Nexus IQ Server appears to start on the secure port without error, with default log messages similar to:

*SYSTEM org.eclipse.jetty.util.ssl.SslContextFactory - Enabled Protocols [TLSv1, TLSv1.1, TLSv1.2] of [SSLv2Hello, SSLv3, TLSv1, TLSv1.1, TLSv1.2]
*SYSTEM org.eclipse.jetty.server.AbstractConnector - Started InstrumentedSslSelectChannelConnector@0.0.0.0:8070 

If the server is started with low level network logging by using -Djavax.net.debug=ssl, and an https connection is attempted to it, the server side stderr log will contain:

%% Initialized:  [Session-2, SSL_NULL_WITH_NULL_NULL]
qtp1617118153-268, fatal error: 40: no cipher suites in common
javax.net.ssl.SSLHandshakeException: no cipher suites in common
%% Invalidated:  [Session-2, SSL_NULL_WITH_NULL_NULL]
qtp1617118153-268, SEND TLSv1.2 ALERT:  fatal, description = handshake_failure
qtp1617118153-268, WRITE: TLSv1.2 Alert, length = 2
qtp1617118153-268, fatal: engine already closed.  Rethrowing javax.net.ssl.SSLHandshakeException: no cipher suites in common 

Java keytool client commands fail with "No certificate from the SSL server":

> keytool -printcert -sslserver localhost:8070 -v
keytool error: java.lang.Exception: No certificate from the SSL server
java.lang.Exception: No certificate from the SSL server
  at sun.security.tools.keytool.Main.doPrintCert(Main.java:2429)
  at sun.security.tools.keytool.Main.doCommands(Main.java:1069)
  at sun.security.tools.keytool.Main.run(Main.java:343)
  at sun.security.tools.keytool.Main.main(Main.java:336)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:992)
  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)
  at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
  at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
  at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
  at sun.security.provider.certpath.ssl.SSLServerCertStore.engineGetCertificates(SSLServerCertStore.java:109)
  at java.security.cert.CertStore.getCertificates(CertStore.java:151)
  at sun.security.tools.keytool.Main.doPrintCert(Main.java:2418)
  ... 3 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
  at sun.security.ssl.InputRecord.read(InputRecord.java:505)
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
  ... 12 more 

Web browsers cannot load the application user interface on the secure port - for example:

Google Chrome reports "unexpectedly closed the connection":

Firefox reports the connection "was interrupted while the page was loading":

Safari reports "can't establish a secure connection to the server":

curl commands receive an error: "Server aborted the SSL handshake":

 > curl -v https://localhost:8070
* Rebuilt URL to: https://localhost:8070/
*   Trying ::1...
* Connected to localhost (::1) port 8070 (#0)
* Server aborted the SSL handshake
* Closing connection 0
curl: (35) Server aborted the SSL handshake

wget commands report "Unable to establish SSL connection"

> wget https://localhost:8070
--2016-08-10 12:23:07--  https://localhost:8070/
Resolving localhost... ::1, 127.0.0.1, fe80::1
Connecting to localhost|::1|:8070... connected.
Unable to establish SSL connection.

Cause

The cause is that you were likely provided a certificate file only, instead of

  • a PKCS12 formatted keystore file containing both the private key and certificate or
  • a certificate with a complete certificate chain, which includes your organization's intermediary signing authority certificate

Please see the note in the Jetty documentation:

You need both the private key and the certificate in the JSSE keystore. You should load the certificate into the keystore used to generate the CSR with keytool. If your key pair is not already in a keystore (for example, because it has been generated with OpenSSL), you need to use the PKCS12 format to load both key and certificate (see PKCKS12 Keys &Certificates).

A giveaway that you were given a single public certificate is that the aliased entry in the Jetty keystore file in which you imported the certificate shows the following:

Entry type: trustedCertEntry

... instead of ...

Entry type: PrivateKeyEntry

You can print the keystore contents by using the keytool -list -v -keystore mykeystorefile.jks command.

Solution

Contact the team who gave you the certificate file and ask them to review the Jetty documentation above. Stipulate that in order for Nexus products to terminate SSL connections, Java keystore files require the private key used to generate the Certificate Signing Request or a complete certificate chain including all the intermediate CA certificates.

You may notice generating a self-signed certificate using keytool does not have this problem. This is because the keytool -gencert command creates a private key by default.

How can I tell if I was given a PKCS12 private key + certificate?

Use a keytool command to check if the file you were given was a valid PKCS12 keystore file.

> keytool -list -keystore the-file-you-were-given-by-your-certificate-team.pkcs12 -storetype PKCS12

If this command errors, or gives output that does not indicate the contents contain a PrivateKeyEntry, then you need to check the file with your certificate issuer.

How can I tell if I was given a only a single certificate?

Use a keytool command:

> keytool -printcert -file the-file-you-were-given-by-your-certificate-team.pem -rfc

If the output contains only 1 line that reads 

-----BEGIN CERTIFICATE-----

...then this is a single certificate, not signed by an intermediary certificate authority or ROOT CA.

 

Have more questions? Submit a request

0 Comments

Article is closed for comments.
Powered by Zendesk