Friday, September 23, 2011

Hosting multiple SSL sites on Tomcat 7 with Virtual Hosting

Foreword
Virtual Hosting is where you serve multiple websites from the same server. This post describes how to achieve virtual hosting with tomcat on linux where each site requires it's own certified SSL capability. As per my previous posts we're assuming Tomcat is your public facing server and you are using APR for performance thus negating the need to sit apache in front. (If you do have apache in front you'd configure SSL there instead).
I haven't found anywhere else on the web explaining how to do this so thought I'd share it with you.

Virtual Hosting Concepts
Virtual hosting comes in 2 guises:
  1. Name-based Virtual Hosting: This is where all your sites can share a common IP and the server looks to the HTTP request header to decide what site to serve up. This is the most common type of virtual hosting.
  2. IP-based Virtual Hosting: Here your sites each have their own distinct IP address. The server listens to multiple IP addresses to determine which site to serve. This type of virtual hosting is less common as it uses more IP addresses, which with IPv4 are scarce and have a cost implication.

The Problem
We are interested in setting up virtual hosting on tomcat with SSL, it's fine to use name-based hosting if all your sites want to share a single ssl certificate. However, this is rarely the case. With a shared cert users receive a scary browser warning if the ssl cert presented doesn't match the requested domain name exactly. For this reason for commercial sites you're going to need a separate, officially certified ssl certificate for each site.
The problem is that the SSL handshake between the client-server happens very early on, before the server looks at the HTTP request header: The server presents the ssl cert tied to the IP before it even looks at the website being asked for!

The Solution 
We must use multiple IP's in conjunction with name-based Virtual Hosting. I'm assuming your server has a single ip address and you only wish to host 2 ssl secured sites, this approach will scale but you'll need a new IP address assigned to your server for each additional SSL site you wish to host. Talk to you hosting provider about this as adding IPs is out of scope but basically once the IP is assigned to your server you'll need to cd /etc/sysconfig/network-scripts then add a file ifcfg-eth0:1 to bind the IP to your main Ethernet device, you don't need >1 NIC. Then service network restart

So now you have 2 public-facing IPs configured for your server, e.g.
10.0.0.1
10.0.0.2

Now you need to configure tomcat to listen on them:
vi $CATALINA_HOME/conf/server.xml

Set up your sites as Host elements as if you were using only Name-based Virtual Hosting, this is simple and well documented.
Now turn your attention to your connectors. It needs to look something like:

    <Connector port="80" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="443" />

    <Connector port="443" protocol="HTTP/1.1" address="10.0.0.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               SSLCertificateFile="/home/tomcat/ssl/www_domain1_com.crt"
               SSLCertificateKeyFile="/home/tomcat/sslkey/myserver.pem"
               SSLCertificateChainFile="/home/tomcat/ssl/www_domain1_com.ca-bundle"
               clientAuth="false" sslProtocol="TLS" />

    <Connector port="443" protocol="HTTP/1.1" address="10.0.0.2" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               SSLCertificateFile="/home/tomcat/ssl/www_domain2_com.crt"
               SSLCertificateKeyFile="/home/tomcat/sslkey/myserver.pem"
               SSLCertificateChainFile="/home/tomcat/ssl/www_domain2_com.ca-bundle"
               clientAuth="false" sslProtocol="TLS" />

Some explanation:
  • The connector on port 80 will listen to all IP's by default.
  • We launch 2 https connectors each listening to port 443 on a separate address. We specify the address attribute to dictate the ip they bind to, see The HTTP Connector.
  • Each https/ssl connector is tied to it's own SSL Cert.
  • We set our DNS A-records for the domains to ensure the requests go to the correct connector.
Conclusion
We solve our problem using name-based virtual hosting over multiple IP's. Strict IP-based hosting on tomcat involves setting the useIPVHosts attribute on the connector, but doesn't help in serving multiple SSL sites as you still need multiple https connectors because each can only have a single ssl cert specified (SSLCertificateFile).



6 comments:

  1. ty very much sir! i rly appreciate!

    ReplyDelete
  2. Should this approach work if you have 2 distinct Tomcat servlet containers running rather than the same one ?? I have a situation where I run a new (Tomcat 7) on the same machine as an existing (tomcat 5). I assume that the above strategy will work with 2 tomcats running SSL on the same machine as with 1 tomcat as given above.

    ReplyDelete
  3. Many Thanks for this post.The above blog describes the method of virtual hosting with tomcat on linux.

    ReplyDelete
  4. how to proceed when I have one public ip and need to measure it locally for different IP based on subdomain?

    ReplyDelete
  5. Good read , I’m going to spend more time learning about this subject https://onohosting.com/

    ReplyDelete