Running multiple HTTPS sites on a single IP with Apache 2.2 presents a unique challenge when dealing with legacy browsers. Server Name Indication (SNI) support becomes critical for proper virtual host routing, but forcing HTTPS for non-SNI clients would break their access completely.
While user-agent sniffing isn't perfect, it's the most practical solution for Apache 2.2 environments. Here's a comprehensive list of SNI-supporting browsers that should be redirected:
# Modern browsers with SNI support
BrowserMatch "MSIE [6-8]" !SNISupport
BrowserMatch "Opera/9.*" !SNISupport
BrowserMatch "Firefox/[1-2]" !SNISupport
BrowserMatch "Chrome/[1-9]" !SNISupport
BrowserMatch "Safari/[1-4]" !SNISupport
BrowserMatch "Android [1-2]" !SNISupport
Here's the complete virtual host configuration that implements conditional redirection:
<VirtualHost *:80>
ServerName www.dummysite.com
# Check for SNI-capable browsers
BrowserMatch "MSIE [6-8]" !SNISupport
BrowserMatch "Opera/9.*" !SNISupport
# Redirect only SNI-capable browsers
<If "!(env('SNISupport') =~ /^!/)">
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</If>
# Standard HTTP configuration for non-SNI clients
DocumentRoot /var/www/html
# ... other HTTP configurations ...
</VirtualHost>
<VirtualHost *:443>
ServerName www.dummysite.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
# Enable HSTS only for SNI clients
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains" env=SNISupport
# HTTPS configuration
DocumentRoot /var/www/html
# ... other HTTPS configurations ...
</VirtualHost>
When implementing this solution:
- Test thoroughly with various browser versions
- Monitor your access logs for any unexpected behavior
- Consider implementing a gradual rollout
- Document this special configuration for future administrators
For more robust solutions consider:
1. Upgrading to Apache 2.4+ with better SNI handling
2. Using separate IPs for critical sites
3. Implementing a frontend proxy like Nginx
When running multiple SSL-enabled virtual hosts on a single IP address with Apache 2.2, Server Name Indication (SNI) becomes a critical requirement. The challenge arises when you need to implement HTTPS redirection while maintaining backward compatibility with older browsers that don't support SNI.
Instead of maintaining an exhaustive list of SNI-capable user agents, we can implement a more maintainable solution using Apache's mod_setenvif
and mod_rewrite
:
# Enable necessary modules
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule rewrite_module modules/mod_rewrite.so
# Define SNI-capable browsers using regex patterns
BrowserMatch "MSIE [6-8]" no_sni
BrowserMatch "Opera/[0-8]\." no_sni
BrowserMatch "Safari/[0-4]\." no_sni
BrowserMatch "Firefox/[0-2]\." no_sni
BrowserMatch "Chrome/[0-9]\." no_sni
BrowserMatch "Android [0-3]" no_sni
Here's a complete virtual host configuration that implements the conditional redirection:
<VirtualHost *:80>
ServerName www.dummysite.com
DocumentRoot /var/www/html
# Set environment variable for non-SNI browsers
SetEnvIf User-Agent ".*" have_sni
SetEnvIf User-Agent "^$" !have_sni
# Apply our browser matching rules
SetEnvIfExpr "!reqenv('no_sni') && reqenv('have_sni')" should_redirect
# Conditional rewrite rule
RewriteEngine On
RewriteCond %{ENV:should_redirect} 1
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
# Standard HTTP configuration
# ...
</VirtualHost>
<VirtualHost *:443>
ServerName www.dummysite.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
SSLCertificateChainFile /path/to/chain.pem
# HSTS Header (only for SNI-capable browsers)
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains" env=should_redirect
</VirtualHost>
For newer Apache versions (2.2.12+), you can use:
SSLStrictSNIVHostCheck on
This will cause Apache to refuse connections from non-SNI clients rather than serving them the default SSL virtual host.
Remember to:
- Regularly update your browser matching patterns
- Monitor your access logs for new non-SNI clients
- Consider implementing a gradual phase-out plan as non-SNI browser usage declines
Use cURL to verify both scenarios:
# Test SNI-capable client
curl -v -H "User-Agent: Mozilla/5.0" http://www.dummysite.com
# Test non-SNI client
curl -v -H "User-Agent: Mozilla/4.0" http://www.dummysite.com