ECDH+AESGCM:ECDH+AES256:ECDH+AES128:ECDH+3DES:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS

If you are not using APR, you need slightly different directives. SSL is configured in

`conf/server.xml`

, and there's a default configuration commented out:<!-- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" /> -->

After uncommenting it, we need to change a few things. Setting the certificate is beyond the scope of this post, but you'll probably need at least the

`keystorePass`

and `keyAlias`

options. Change the `protocol`

option to `protocol="org.apache.coyote.http11.Http11NioProtocol"`

, which will enable the NIO connector. The NIO connector is non-blocking for better performance with slow clients, and doesn't support client-initiated renegotiation, which mitigates some DOS attacks. If you don't care about IE6 and Java 6, you can remove SSLv3 and only leave the TLS protocols enabled using `sslEnabledProtocols="TLSv1.2,TLSv1.1,TLSv1"`

.Let's convert the cipher string into something Tomcat can understand. The option to configure is

`ciphers`

, using the JSSE naming convention, as specified in the documentation. In order to convert the OpenSSL cipher suite names to JSSE names, we can use the standard TLS codes for each cipher suite. The full list can be downloaded from the IANA registry, where you can download a tls-parameters-4.csv file. Now we can use a little bit of shell to convert the list:STRING='ECDH+AESGCM:ECDH+AES256:ECDH+AES128:ECDH+3DES:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS' CODES=`/usr/local/ssl/bin/openssl ciphers -V "$STRING" | cut -d- -f1` CIPHERS=`for CODE in $CODES; do grep "^\"$CODE\"" tls-parameters-4.csv | cut -d, -f3; done` echo $CIPHERS | sed 's/ /,/g'

Which gives us the string

`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA`

.Set your

`ciphers`

parameter to that. Note that even though the list contains GCM (Galois/Counter Mode) suites, the default Java 7 Sun JSSE provider does not implement them, and so they won't be used under Java 7. GCM suites should be implemented for Java 8 - see JEP 115. Also, if you are in a country that does not prohibit strong encryption, you need to install the JCE Unlimited Strength Jurisdiction Policy Files, otherwise you won't have any 256 bit ciphers.With the above cipher string and Oracle Java 7, the SSL Server Test provides a score of 90 for key exchange and 90 for cipher strength. It also says that BEAST is not mitigated server-side, but that attack is mitigated on the client side for most clients - see BEAST information. Apple has also finally fixed this in Mavericks - see this post. However, Tomcat does not enforce the order of the ciphers in the list, and so for some reason all version of IE that are tested choose the RSA key exchange, even though they support ECDHE. Of course, RSA key exchange does not provide forward secrecy. We can further improve this by removing RSA key exchange from the cipher string:

ECDH+AESGCM:ECDH+AES256:ECDH+AES128:ECDH+3DES:!aNULL:!MD5:!DSS

Which results in this list of ciphers:

`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA`

.With this list, IE is forced to choose ECDHE for key exchange, which provides forward secrecy. IE6/XP, IE8/XP, and Java6u45 still fail because SSLv3 is disabled. However, Bing Oct 2013 handshake now also fails, as well as OpenSSL 0.9.8y (released February 5 2013). OpenSSL 1.0.1e works fine. If you are ok with forcing some clients to upgrade, leave out the RSA key exchange.