SSL with Virtual Hosts Using SNI


Using name-based virtual hosts with SSL adds another layer of complication. Without the SNI extension, it's not generally possible (though a subset of virtual host might work). With SNI, it's necessary to consider the configuration carefully to ensure security is maintained.

(Note: this page is just about support that comes with the Apache web server. Alternatives such as mod_gnutls are another topic.)

The Problem

The problem with using named virtual hosts over SSL is that named virtual hosts rely on knowing what hostname is being requested, and the request can't be read until the SSL connection is established. The ordinary behavior, then, is that the SSL connection is set up using the configuration in the default virtual host for the address where the connection was received.

While Apache can renegotiate the SSL connection later after seeing the hostname in the request (and does), that's too late to pick the right server certificate to use to match the request hostname during the initial handshake, resulting in browser warnings/errors about certificates having the wrong hostname in them.


Server Name Indication

The solution is an extension to the SSL protocol called Server Name Indication (RFC 4366), which allows the client to include the requested hostname in the first message of its SSL handshake (connection setup). This allows the server to determine the correct named virtual host for the request and set the connection up accordingly from the start.


Prerequisites to use SNI

How can you tell if your Apache build supports SNI? If you configure multiple name-based virtual hosts for an address where SSL is configured, and SNI isn't built into your Apache, then upon Apache startup a message like "You should not use name-based virtual hosts in conjunction with SSL!!" will occur in the error log. If SNI is built in, then the error log will show "[warn] Init: Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)".


(per Wikipedia)

Changes in configuration to use SNI



Since the first (default) vhost will be used for any request where the provided server name doesn't match another vhost, it is important that the first vhost have the most restrictive access control, otherwise clients can access restricted resources by sending a request for any unknown hostname. (This isn't actually any different from using virtual hosts without SSL.)

Environment variables



SNI/Request hostname mismatch, or SNI provides hostname and request doesn't.


Client doesn't support SNI.





Server configuration

# Ensure that Apache listens on port 443
Listen 443
# Listen for virtual host requests on all IP addresses
NameVirtualHost *:443

# Go ahead and accept connections for these vhosts
# from non-SNI clients
SSLStrictSNIVHostCheck off

<VirtualHost *:443>
  # Because this virtual host is defined first, it will
  # be used as the default if the hostname is not received
  # SNI.
  DocumentRoot /www/example1

  # Other directives here


<VirtualHost *:443>
  DocumentRoot /www/example2

  # Other directives here


Detailed Processing

Before there is even an SSL handshake, Apache finds the best match for the IP address and TCP port the connection is established on (IP-based virtual hosting)

If there is a NameVirtualHost directive that has the same literal arguments as this best-matching VirtualHost, Apache will instead consider ALL VirtualHost entries with identical arguments to the matched VirtualHost. Otherwise, SNI processing has no selection to perform.

If the client sends a hostname along with its TLS handshake request, Apache will compare this TLS hostname to the ServerName/ServerAlias of the candidate VirtualHost set determined in the preceding steps.

Whichever VirtualHost is selected on the preceding basis will have its SSL configuration used to continue the handshake. Notably, the contents of the certificates are not used in any comparison.

This process mimics the normal (albet misundersood) consecutive application of IP-based, then name-based, vhost matching algorithms used with HTTP, except that the input is the TLS data and not an HTTP header.

NameBasedSSLVHostsWithSNI (last edited 2013-01-06 22:52:11 by TimBannister)