How to show protocols and cipher suites available to Jetty HTTPS clients? - java

I have configured Jetty embedded server to include/exclude some protocols and cipher suites. Is there way to report those on working service? I think about something like getSupportedCipherSuites() and getSupportedProtocols() of javax.net.ssl.SSLServerSocket but for Jetty server objects. My code already shows things from configration:
HTTPSPDYServerConnector SSLconnector = new HTTPSPDYServerConnector(server, sslContextFactory);
SSLconnector.setPort(PortHTTPS);
...
server.setConnectors(new Connector[] { SSLconnector });
...
showInfo(sslContextFactory.getIncludeCipherSuites());
showInfo(sslContextFactory.getExcludeCipherSuites());
showInfo(sslContextFactory.getIncludeProtocols());
showInfo(sslContextFactory.getExcludeProtocols());
...
server.start();
Now I want to see what protocols and cipher suites are available for clients.
EDIT (more info):
My environment can work with those protocols:
SSLv2Hello
SSLv3
TLSv1
TLSv1.1
TLSv1.2
This is result of SSLServerSocket.getSupportedProtocols() that is reported by http://www.java2s.com/Code/JavaAPI/javax.net.ssl/SSLServerSocketgetSupportedProtocols.htm
But with Jetty environment I do not know how to get such list. I excluded some protocols by calling
sslContextFactory.addExcludeProtocols() (I disabled TLSv1.2 because of Chrome bug ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED in Google Chrome)
How can I get list of protocols available (not excluded) for Jetty server?
I suppose that for my environment such result will be:
SSLv2Hello
SSLv3
TLSv1
TLSv1.1
(TLSv1.2 was disabled)

I've just gone through a similar problem.
The way Jetty works, it instantiates a default SSLEngine and then it applies exclusions and other preferences. By default, Jetty 9.4 excludes the following protocols:
this.addExcludeProtocols("SSL", "SSLv2", "SSLv2Hello", "SSLv3");
Ciphers are managed in a similar way, but you can uge regexes. By default, Jetty 9.4 excludes the following:
this.setExcludeCipherSuites("^.*_(MD5|SHA|SHA1)$");
this.addExcludeCipherSuites("^TLS_RSA_.*$");
this.addExcludeCipherSuites("^SSL_.*$");
this.addExcludeCipherSuites("^.*_NULL_.*$");
this.addExcludeCipherSuites("^.*_anon_.*$");
If you call the include/exclude methods yourselp, you will have to deal with the particular sequence of processing that Jetty performs, which is potentially confusing. So I recommend you use the setter methods first with empty arrays, in order to clear anything Jetty put in place by default, and then add your preferred items. Example:
// empty the collections, we don't need no education
sslContextFactory.setExcludeProtocols(new String[]{});
sslContextFactory.setExcludeCipherSuites(new String[]{});
// tell me what you want, what you really really want
sslContextFactory.setIncludeProtocols("TLSv1","TLSv1.1","TLSv1.2");
sslContextFactory.setIncludeCipherSuites(omgIveNeverSeenSuchABigArrayOfCiphers);
If you need a list of ciphers that a specific Java client supports, run that client with -Djavax.net.debug=ssl:handshake:verbose and look for ClientHello messages.

Related

How to disable TLS 1.0 from JDK

To disable SSLv3 we have added -Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2" \environment variable to Java 8 run time. However due to TLSv1.0 has been considered as a weak protocol, we want to disable it from the Transport Layer Security protocols.
So just want to know whether TLSv1 is equal to TLSv1.0 ? or
TLSv1 mean it(client) will pick any Transport Layer Security protocols supported by the server(other than TLSv1.0 )?
TLSv1 is the java identifier for TLSv1.0, it's not a "wildcard" for all types of TLS. In addition to the system-property you already set, you should set https.protocols to the same values because classes in the JVM will check this setting instead of the others. See the Oracle's CVE-documentation about this for more details.

how to get negotiated information from SSL handshake in JSSE

I want to record things like client sent tls version, server preferred version, server preferred cipher suite in JSSE. how to do this?
Note that I can only use Java code to do this.Parsing log files are not accepted.
You can add -Djavax.net.debug=all flag to your java execution string and it will dump all that info into the console.
http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html
The only way this information is available is via the javax.net.debug system property. If you can't parse that output all you can get is the data in the resulting SSLSession, which consists of what the negotiated protocol and cipher suite were, and the peer certificates. You can also have a look at your own SSLSocket's enabled protocols and cipher suites, but I don't see where it's going to get you.

how to enable only TLSv1.2 on Java 8 server application

I'm trying to configure an application running on Java 8 to support only TLSv1.2 connections. I've seen posts about altering .../jre/lib/security/java.security, using -Ddeployment.security.TLS* arguments when launching the JVM, and of course specifying an SSLContext of "TLSV1.2" in the code.
I've managed to get the server to support only TLSv1.1 and TLSv1.2, but have been unsuccessful at also turning away TLSv1.1 connections.
Any help would be appreciated. Thanks.
Editing security.java does work, assuming you have all the necessary commas.

java 1.6 TLS1.2 support using proxy nginx/ squid solution issues

I have a legacy java web application that makes calls to an external webservice. The provider of that service is turning off TLS1.0 support. So, I am trying to see how the application can continue to work with the service.
The options I have seen are a) use BouncyCastle JCE instead of Java JCE http://boredwookie.net/index.php/blog/how-to-use-bouncy-castle-lightweight-api-s-tlsclient/, which I guess requires code change/ recompile (we don't have the luxury of doing it) or 2) use proxy servers https://www.reddit.com/r/sysadmin/comments/48gzbi/proxy_solution_to_bump_tls_10_connection_to_tls_12/
I have tried nginx proxy - it doesn't seem to handle the switch between TLS1.0 incoming and TLS1.2 that the end server expects.
server { listen 443 ssl; server_name proxy.mydomain.com;
ssl_certificate D:/apps/openssl/proxy.mydomain.com.cert;
ssl_certificate_key D:/apps/openssl/proxy.mydomain.com.private;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP;
ssl_prefer_server_ciphers on;
location / {
proxy_pass https://fancyssl.hboeck.de/;
}
This fails with a 502/ bad gateway error since https://fancyssl.hboeck.de only support TLS1.2 but works with https://www.google.com that supports TLS1.0.
I am doing this on Windows.
It's not TLSv1.2, it's lack of SNI leading to renegotiation.
First, I set up nginx (1.8.1/Windows) with a config like yours except using my own key&cert and proxying to my own test server. It worked fine, connecting from Java6 requester with TLSv1.0 and to server with TLSv1.2 (and even ECDHE-RSA-AES256GCM-SHA384, one of the 'best' ciphersuites) and returned pages just fine. I tried fancyssl.hboek.de and got 502 like you.
With wireshark I saw that nginx does not send SNI (by default) and at least using the IPv4 address 46.4.40.249 (I don't have IPv6) that server apparently hosts more than one domain because without SNI it provides a different (and expired!) certificate, for *.schokokeks.org, and after the first application data (the request) it sends an encrypted handshake (a renegotiation request -- which nginx does not honor). Testing with openssl s_client confirms that the server with SNI immediately sends the page but without it renegotiates first; repointing nginx to openssl s_server confirms that if the server requests renegotiation, receives no response, and closes nginx treats that as 502.
I would guess that Apache is renegotiating because it realizes the requested Host is not covered by the certificate -- except that it again uses the 'wrong' certificate. I haven't tried to track that part down.
Google does support TLSv1.2 (and ECDHE-RSA-AESGCM) when I connect, but even without SNI doesn't renegotiate, presumably because it's such high volume nothing else runs on www.google.com servers and there's no ambiguity. My test server doesn't have vhosts so didn't need SNI.
The nginx documentation reveals a directive proxy_ssl_server_name which can be set on to enable SNI, and then proxying to this server works.
FYI: several of the statements on that webpage are wrong, although its conclusion (if possible use TLSv1.2 with ECDHE or DHE and AES-GCM) is good.
Also, most of your ssl_ciphers string is useless, but you didn't ask about that.
ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP
HIGH is an excellent start.
SEED is useless in a server used (only) by Java/JSSE client, because it's not implemented on the Java side. Even outside of Java it was pretty much used only in South Korea, where it was created as an alternative to DES or IDEA, and even there it is mostly obsoleted by ARIA which is an alternative to AES -- but is not implemented by OpenSSL and hence nginx.
aNULL is probably unneeded because JSSE disables 'anonymous' suites by default, but here it's worth it as defense in depth.
!eNULL does nothing; no eNULL suites are in HIGH, or DEFAULT, or even ALL. You can only get them explicitly or with the bizarre COMPLEMENTOFALL -- which you shouldn't.
!EXPORT !DES !RC4 do nothing; none of them are in HIGH. If instead you started from DEFAULT on older versions of OpenSSL, or from ALL, then they would be good.
!PSK is unneeded; nginx doesn't appear to configure for PSK and JSSE doesn't implement it anyway.
!RSAPSK is ignored because OpenSSL doesn't implement that keyexchange, and if it did those suites are already covered as above.
!aDH !aECDH are covered by !aNULL and thus do nothing.
!EDH-DSS-DES-CBC3-SHA is silly; there's no reason to exclude this one suite when you keep other DHE_DSS and 3DES suites.
!KRB5-DES-CBC3-SHA is ignored because OpenSSL doesn't implement Kerberos, and if it did nginx wouldn't be configured for it plus again it would be silly to exclude one suite while keeping similars.
!SRP is unneeded; like PSK nginx apparently doesn't configure and JSSE doesn't implement.
So: HIGH:!aNULL is all you need.

Configure Apache ssl.conf for Java 7u25 support

In an attempt to harden my ssl server I have inadvertently broken a third party integration. They need Java 7u25 support in our SSL config and now we apparently do not have it with this config.
ssllabs.com says we have "Java 7u25 Protocol or cipher suite mismatch"
we have configured ssl.conf
# SSL Protocol support:
SSLProtocol -SSLv2 -SSLv3 -TLSv1 +TLSv1.1 +TLSv1.2
# SSL Cipher Suite:
SSLCipherSuite
ECDHE-RSA-AES256-GCM-SHA384:
ECDHE-ECDSA-AES256-GCM-SHA384:
ECDHE-RSA-AES256-SHA384:
ECDHE-ECDSA-AES256-SHA384:
ECDHE-RSA-AES128-GCM-SHA256:
ECDHE-ECDSA-AES128-GCM-SHA256:
ECDHE-RSA-AES128-SHA256:
ECDHE-ECDSA-AES128-SHA256:
AES128-GCM-SHA256:
AES256-GCM-SHA384:
AES128-SHA256:
AES256-SHA256:
AES:
!aNULL:
!eNULL:
!EXPORT:
!DES:
!RC4:
!MD5:
!PSK:
!aECDH:
!EDH-DSS-DES-CBC3-SHA:
!EDH-RSA-DES-CBC3-SHA:
!KRB5-DES-CBC3-SHA
(formatting of cipher suites in ssl.conf is all in one line without spaces; it was changed one per line in this post for readability)
Thank you
By default Java 7 needs TLSv1 support which you've disabled. Re-enable it and you might be able to use that AES cipher depending what that corresponds to, but it probably can't use the SHA256 or SHA384 ones (again in default mode).
Best to run your site through ssllabs.com again and then compare the ciphers available to the Java 7 list: https://www.ssllabs.com/ssltest/viewClient.html?name=Java&version=7u25
Btw Java 7 can support TLSv1.1 and TLSv1.2 but not by default (see here: https://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html) and have seen people struggle to get them working.

Categories