HTTPS, Tomcat and Load Balancers.. Oh My! - Halcyon
During the implementation of a new servlet application on Tomcat we encountered an HTTP/HTTPS issue during redirects. The user would browse to a servlet via HTTPS, through a load balancer that handled SSL decryption, and during the execution of the servlet, they would be redirected to another URL. However, that redirect would be generated as a fully qualified HTTP address. This poses a problem. The page was originally requested as secure content, and the user is redirected to an insecure URL. Ultimately, the user sees a security warning. We figured it out by using the Tamper Data Firefox extension.
Now, this issue is nothing new, or unique to our environment. It’s quite simple why this is happening:
- The user’s browser makes a request for secure content on port 443.
- Load Balancer handles SSL decryption, converting the secure request to a standard HTTP request to port 80.
- Apache takes this request and passes it on to Tomcat (we use mod_jk) to handle the servlet.
- Servlet executes and generates a redirect for the browser. Tomcat’s servlet container determines that the request was made over an insecure port and generates the redirect as HTTP. (Note: Tomcat’s container is unique. It ALWAYS generates fully qualified redirects, never relative path redirects)
- The redirect is returned through the load balancer to the browser.
- Browser compares the new URL for the redirect and the original request and sees that the protocols are different, and issues a security warning.
So, how do we fix this? There are two main ways to resolve the issue. 1) Load Balancer URL Rewriting, or 2) Tomcat configuration. With a Load Balancer rewrite, you configure your hardware to inspect each “302″ (Redirect) and convert the URL from “HTTP” to “HTTPS” (this is simply a “Find and Replace”). That will work, however, it requires that your Load Balancer inspect not just individual packets, but the entire request. This adds overhead to the Load Balancer. The simpler approach is to tell Tomcat that it’s residing behind a Load Balancer that is doing SSL decryption in advance.
In Tomcat’s “server.xml” file, you’ll find “Connector” sections that define what ports are open on Tomcat and how they should be handled. Since we are using Apache to front-end our Tomcat server, the port in question is the AJP Connector on 8009. We simply told Tomcat to use “HTTPS” and port 443 instead of “HTTP” and port 80:
<Connector port="8009" enablelookups="false" redirectport="8443" protocol="AJP/1.3" scheme=”https” proxyPort=”443″ />
Restart Tomcat, and your redirects will now be generated as HTTPS. These configurations work for the regular HTTP Connector on Tomcat as well, in case you’re not using Apache to front-end Tomcat.