Tuesday, August 31, 2010

How To: Enforce TLS Encryption on Tomcat Server 6.0

Note: I should begin this post by saying that I’m no expert on SSL or TLS encryption or the “handshakes” and negotiations that browsers and servers go through when giving the user a connection to secure material. Feel free to jump in on the comments if I get the terminology or methodology wrong.
As far as I understand it, SSL is pretty secure, but TLSv1 (its successor) is the max you can get on a standard web browser for encrypted traffic between the browser and the server today.
Recently, I was tasked with setting up a Tomcat server to enforce TLS for a government client. We had already defined a server.xml file that specified “TLSv1″ as the protocol and AES encryption. However, apparently Tomcat 6.0 doesn’t strictly enforce TLS if SSL is also enabled. That is to say, if TLSv1 is not enabled on the browser, but SSL is, the server will “fall back” to SSL in the hopes of displaying the content — I suppose it takes the “well, SSL is better than nothing” approach.
However, this wasn’t going to fly for my client — an institution with strict security rules for its web applications — which, really, is a good thing. If TLSv1 wasn’t enabled properly, the site shouldn’t display, even if SSL is enabled.
I looked around for how to do this, and to my surprise, it was incredibly difficult to find. After a great deal of Google searches and frustration, I finally found this post  on the old, archived Tomcat developers listserv/group [Note: I am currently working on finding the source link again. Will update when I do.] It turns out that there’s another attribute you can add to your server connector in server.xml — the “protocols” attribute (standing for "secure" I believe; not a pluralization)
So, in short, a Tomcat 6.0 connector in server.xml that enforces TLS looks something like the connector below (I’ve changed the password to a dummy, of course):
<Connector
port="8443"
protocol="HTTP/1.1"
protocols="TLSv1"
SSLEnabled="true"
enableLookups="false"
acceptCount="100"
maxThreads="200"
scheme="https"
keystoreFile="d:\keystore\.keystore"
keystorePass="changeme"
secure="true"
clientAuth="false"
sslProtocol="TLSv1"
cipher="AES"
allowUnsafeLegacyRenegotiation="false"
/>

I wanted to provide this bit of knowledge as a public service. Would love to hear about your own experiences enforcing TLS or security in Tomcat and other web servers in the comments! Please let me know if you’ve found this useful.

2 comments:

  1. Awesome find Sean !!!! This is great news !!!

    Surprising how none of the Tomcat documentation contains such an important piece of information.

    I would like further add to this:

    THE WAY TO DISABLE SSL2.0 IN TOMCAT IS TO ENABLE ONLY SSL3.0 OR TLS1.0 IN THE TOMCAT CONFIGURATION. INSIDE THE SERVER.XML OF THE TOMCAT CONFIGURATION, INCLUDE THE ATTRIBUTE sslProtocol="TLS" WITHIN THE CONNECTOR THAT DEFINES SSL. THIS WILL DISABLE SSL2.0.

    TO DISABLE EVEN SSL3.0 IN TOMCAT, INSIDE THE SERVER.XML OF THE TOMCAT CONFIGURATION, INCLUDE THE ATTRIBUTE protocols="TLSv1" WITHIN THE CONNECTOR THAT DEFINES SSL. THIS WILL DISABLE EVEN SSL3.0.

    NOTE: MY RECOMMENDATION IS TO USE ONLY ONE OF THE TWO ATTRIBUTES AT A GIVEN TIME.

    I HAVE TRIED AND TESTED THIS, BUT ONLY WHEN USING JSSE WITH TOMCAT FOR SSL. I HAVEN'T TRIED THIS ON APR.

    ReplyDelete
  2. @suarabh, thanks! I'm glad it was useful. I was surprised to see that it wasn't included as well, but it seems that in most situations, you'd want to have SSL as a fallback. In this particular case, the client wanted TLS encyption only (SSL was not an option, even for fallback).

    I appreciate the additional detail as well.

    ReplyDelete

Keep it classy, folks.