Yesterday someone remarked: With Apache you cant implement multiple SSL certificates behind one and the same IP address. This remark is actually not quite correct. A good opportunity to explain the basics behind SSL and explain why SSL implementations on servers with multiple sites can be challenging.
SSL is an acronym for ‘Secure Socket Layer’ and is a method to encrypt traffic between client and host. SSL uses a key-pair that is provided by a digital certificate to encrypt the communication. To do this, SSL needs inform the client how to decrypt the traffic prior to the actual communication. This is done by the so called, SSL-handshake, in which a public-key is shared with the client.
Each of the parties (client and host) now have a public and private key available. With this so called keypair both parties are able to encrypt and decrypt the traffic that is being send. Please view the Deffie-Hellman key exchange wikipedia for a clear example of this algorithm.
The Deffie-Hellman example also illustrates the risk of a client losing or sharing its private key.
What is an certificate
In most cases an certificate has multiple purposes. One is obviously to encrypt the traffic. An additional task is to identify the host to the client. The host is usually identified using its public DNS name. By means of the CN (Common Name) field of the certificate, the client is able tot verify that the CN in the certificate is equal to the DNS adres the client is visiting. If either one is not equal, the client will generate an warning.
Why do you still get an warning when you use a valid DNS name in your certificates CN field? Well an additional check is necessary. An external Certificate Authority needs to back your claim. This is done by signing the certificate using an certificates private key that is only known by the Certificate Authority. The client is now able to check (with the public key of that CA) the validity of your certificate and its claim.
You might now understand why there was such a buzz over Diginotar making its private key available to hackers using its auto-signing process.
What is a SOCKET
The second principle to understand is the ‘socket.’ Litteraly a socket is an communication endpoint used by an application to send data. Its important to realize that a socket only contains protocol information (like TCP/UDP or ICMP) and various settings like timeout. Usually IP information isnt given in the socket definition. If a programmer wants the socket to be open on a specific device he usually needs to ‘explicitly bind’ the socket to that IP.
So an socket is nothing more than a ‘door’ to the network that an application can programmatically use to send data over an networked device.
Apache and SSL
In case of Apache httpd SSL is implemented on a listening IP:Port. When a client connects to Apache using the ip:port configured in httpd.conf the first thing that is performed is the SSL handshake. As we noted, the SSL handshake is performed prior to sending actual data. When this is completed, the http request header is send (encrypted) to the Apache instance.
When Apache implements multiple sites behind one socket, called virtual hosts, it uses the ‘http GET header’ to determin the right content (virtual host). Apache can only do this when it received a valid requestheader, that can only be offered after SSL has been implemented.
Now here is the issue.
The http request header we are talking about actually contains a DNS site name, for instance: http://www.google.com. GET /. Now the certificate used also has ‘CN=www.google.com’. In which case there wont be any problem. All checks out, no certificate error.
Now the second site hosted in a different virtual host, provided by the same Apache instance is called using the http request header: logon.google.com. GET /. Now all hell breaks loose because our certificate still contains ‘CN=www.google.com’. The name doesnt match, and a certificate error is risen.
the reason for this is that SSL is actually being implemented by Apache, but prior to the actual request being send. There is no mechanism in place to determine the correct certificate, containing the correct CN prior to the http call.
When you are using multiple subdomains behind the same top level domain, for instance: http://www.mysite.com, service.mysite.com, mail.mysite.com. The solution might be to use a so called ‘wildcard’ certificate. This certificates CN name looks like: CN=*.mysite.com and will match correctly against all the subdomains.
When you are using mutiple top level domain sitesnames like: http://www.google.com, http://www.mysite.com, implementing SNI might be a solution. Be warned, SNI has a limited backwards compatibility. The client needs to support SNI to work property.
You could use multiple ports on the server and SSL on the various ports. This will require your visitors to add a port to the url like: https://www.google.com (default 443), https://www.mysite.com:445 (non default).
Alternativly use multiple IPs to bind the ssl. This will enable you to keep the default port 443. Requesting mulitple public IPs to do so might be costly, but is the most elegant solution (next to SNI).
Feel free to post them below 🙂