I have been trying to get SSL working on GlassFish, when I realised that unlike Apache (where the SSL configuration can be defined in the virtual host block), the SSL settings for GlassFish is attached to the network listener, not the virtual host.
In the case of a default GlassFish OSE 4.0 installation, the network listener http-listener-2 is the SSL listener, and only one certificate can be associated with the listener at any one time. The default certificate given to http-listener-2 is a self-signed certificate given the alias s1as. Changing this to a CA-signed certificate is a matter of modifying the keystore file using the Java keytool program, and changing the certificate alias used by the network listener (via the SSL tab on the network listener configuration page).
I wanted to host multiple virtual hosts, each using a different SSL certificate as they have different domains, on GlassFish. I wondered why one listener can only use one SSL certificate, because on Apache each virtual host block can house its own SSL settings and hosting multiple SSL sites is definitely possible (I tried).
So I began scouring the documentation and found this in the GlassFish 4.0 Security Guide:
Name-based Virtual Hosts Using name-based virtual hosts for a secure application can be problematic. This is a design limitation of the SSL protocol itself. The SSL handshake, where the client browser accepts the server certificate, must occur before the HTTP request is accessed. As a result, the request information containing the virtual host name cannot be determined prior to authentication, and it is therefore not possible to assign multiple certificates to a single IP address.
If all virtual hosts on a single IP address need to authenticate against the same certificate, the addition of multiple virtual hosts probably will not interfere with normal SSL operations on the server. Be aware, however, that most browsers will compare the server’s domain name against the domain name listed in the certificate, if any (applicable primarily to official, CA-signed certificates). If the domain names do not match, these browsers display a warning. In general, only address-based virtual hosts are commonly used with SSL in a production environment.
Okay, so it seems like GlassFish is blaming the SSL protocol for not being able to use different certificates for different virtual hosts. The explanation makes sense though; the server will need to know from the client the name of the virtual host the client is connecting to, but this exchange will also have to be encrypted using SSL. But which SSL certificate should the server use for this initial exchange? The problem is understandable.
However, if the problem is the SSL protocol, shouldn’t all web servers behave the same way? If it is impossible on GlassFish, how come it is possible on Apache?
I did some more digging, and stumbled on an Apache wiki page which stated:
As a rule, it is impossible to host more than one SSL virtual host on the same IP address and port. This is because Apache needs to know the name of the host in order to choose the correct certificate to setup the encryption layer. But the name of the host being requested is contained only in the HTTP request headers, which are part of the encrypted content. It is therefore not available until after the encryption is already negotiated. This means that the correct certificate cannot be selected, and clients will receive certificate mismatch warnings and be vulnerable to man-in-the-middle attacks.
I find it quite weird that the Apache documentation is agreeing in saying that it is impossible because I am sure it worked when I tried it. This very blog is running on a multiple-certificate SSL server!
Then I clicked on the link on that wiki page that leads to another wiki page, which has the answer: Server Name Indication (SNI).
Apparently, SNI is an extension to the SSL protocol that was introduced in 2006 which allowed virtual hosts to use different SSL certificates and the Apache version that I use has already included SNI inside its SSL implementation.
Before SNI, one IP address and port combination can only use one SSL certificate. The introduction of SNI lifted this limitation of the SSL protocol. So let’s get back to GlassFish. Does it support SNI? Based on the documentation, no. Why doesn’t it support SNI? Let’s find out.
Googling GlassFish SNI brought me to an interesting post by Ricardo Martín Camarero. His encounter with SNI is the opposite of mine; he knew it was not supposed to be possible until someone told him otherwise. He made me realise through his post that since GlassFish runs on Java, SNI support will be dependent on the Java VM.
As of the current version of Java, which is version 7, SNI implementation is only supported for clients i.e. Java clients will be able to connect to servers utilizing SNI with no certificate errors.
SNI support for servers will be added to Java 8. As such, we might have to wait until the next version of GlassFish to use SNI.