mod_ssl and Server Name Indication (SNI)
While configuring Apache for SSL / SNI I ran into a few errors:
[root@webapps ~]# service httpd restart
Stopping httpd: [ OK ]
Starting httpd: Syntax error on line 1068 of /etc/httpd/conf/httpd.conf:
Invalid command 'SSLEngine', perhaps misspelled or defined by a module not included in the server configuration
[FAILED]
[root@webapps ~]# service httpd restart
Stopping httpd: [ OK ]
Starting httpd: [Sun Jan 01 03:15:08 2012] [error] (EAI 5)No address associated with hostname: Could not resolve host name *443 -- ignoring!
[Sun Jan 01 03:15:08 2012] [warn] _default_ VirtualHost overlap on port 443, the first has precedence
[ OK ]
Notes:
- Limitations of SNI on Apache (apache.org)
- Information on mod_ssl (apache.org)
- Limited SNI Support on older systems (wikipedia.org)
- VirtualHost example for SSL & SNI (gentoo-wiki.com)
- mod_ssl SSLOptions explained (apache.org)
- mod_ssl SSLProtocol explained (apache.org)
About Server Name Indication:
SNI (Server Name Indication) Allows multiple SSL websites to be hosted off of a single IP Address with each using a different certificate. Given that I don't have unlimited budget for dedicated IP Addresses, I am implementing it on my VPS based web applications. There are 2 important limitations that I should note here:
- Windows XP machines running Internet Explorer or Safari do *not* support SNI
- The work-around is to use Firefox 2.0+ or Chrome 6+
- Mac OS Versions lower than 10.5.6 / 10.5.7 need to use Chrome 5+ or Firefox 2.0+
Given that there are still a lot of XP machines out there (wikipedia.org) whose browser state is unknown, implementing SNI may not be the best thing to try in every case. I'm just using SSL to secure the channel against eavesdropping. If I were an e-commerce site I'd stick to more traditional methods.
Install mod_ssl:
mod_ssl on Apache allows SNI to be implemented in virtual hosts. There are a few Important Notes that you should keep in mind when implementing mod_ssl on Apache for purposes of SNI:
- Use OpenSSL 0.9.8f or later
- Apache must be able to resolve OpenSSL at startup
- Read the Complete List so you don't get caught by suprises
To install mod_ssl on Centos 6, you can use these commands:
- yum install mod_ssl
- service httpd restart
Note: yum will install mod_ssl. Once installed you should restart apache to use it.
How to resolve the Errors listed in the Article Header:
- Invalid command 'SSLEngine', perhaps misspelled or defined by a module not included in the server configuration
- To get around this error I just had to install mod_ssl (using the command listed above).
- To get around this error I just had to install mod_ssl (using the command listed above).
- [warn] _default_ VirtualHost overlap on port 443, the first has precedence
- To get around this error I had to:
- Edit my Apache config file (httpd.conf) to allow NameVirtualHosting
- Setup a VirtualHost directive to listen on port 443
(See further down for an example of a working SSL/SNI VirtualHost directive)
- Here is the line I added to httpd.conf for SSL NameVirtualHost (Bolded Line):
#
# Use name-based virtual hosting.
#
NameVirtualHost *:80
NameVirtualHost *:443
- To get around this error I had to:
- [error] (EAI 5)No address associated with hostname: Could not resolve host name *443 – ignoring!
- This error resulted from a typo. When I setup the NameVirtualHost directive I omitted the colon between the asterisk and the port (I used *443 where *:443 is the correct form. Once I added the colon in this error went away
Example of a VirtualHost Directive with SSL/SNI enabled:
Here is a functioning example of a VirtualHost directive setup to use SSL / SNI. You can compare the differences between this and the non-SSL/SNI version by checking out my article on mod_rewrite (Bolded Lines are explained below):
<VirtualHost *:443>
# Enable the SSL Engine
SSLEngine on
SSLCertificateFile /var/path/to/certificate_file.pem
SSLCertificateKeyFile /var/path/to/private_key.key
#Specify the server name and SSL Options (Disallow SSLv2)
ServerName html5clipboard.net
SSLOptions StrictRequire
SSLProtocol all -SSLv2
# Specify the document root
DocumentRoot /var/www/apps/php/webapp
#
# Rewrite rules for vanity urls
RewriteEngine On
# Prevent folder or file access
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
#RewriteBase /var/www/apps/php/production/html5clipboard
RewriteRule ^/about/us$ /about.php
RewriteRule ^/about/legal$ /legal.php
RewriteRule ^/[a-zA-Z0-9]+/*$ /service/clip.php?id=$1
# Logging
ErrorLog logs/webapp.net-error_log
CustomLog logs/webapp.net-access_log common
</VirtualHost>
Explanation:
- SSLEngine on
- This enables SSL for the VirtualHost
- SSLCertificateFile /var/path/to/certificate_file.pem
- This specifies the certificate associated with the VirtualHost
- SSLCertificateKeyFile /var/path/to/private_key.key
- This indicates where the corresponding Private Key is located
- SSLOptions StrictRequire
- This configures the SSL "options" (see documentation)
- SSLProtocol all -SSLv2
- This enables all Secure protocols except for SSLv2 (see documentation)
With all of the above configured, I have 0 errors when apache boots and I'm able to assign ssl key/certificate pairs for each VirtualHost on my apache server.