When running multiple virtual hosts on Apache with mixed SSL configurations, you might encounter an unexpected behavior where HTTPS requests to non-SSL domains get served by your default SSL virtual host. This creates security warnings and incorrect site rendering.
Apache's SSL handling follows these rules:
- If no matching
is found for port 443, the first defined SSL virtual host handles the request - Non-SSL virtual hosts on port 80 won't intercept HTTPS requests
- Modern browsers enforce HTTPS by default, potentially exposing this issue
Create a dedicated virtual host that catches all unwanted HTTPS requests:
ServerName example2.com
ServerAlias *.example2.com
Redirect permanent / http://example2.com/
SSLEngine off
For maximum isolation:
# HTTP-only IP (192.168.1.100)
ServerName example2.com
DocumentRoot /var/www/example2
# SSL-enabled IP (192.168.1.101)
ServerName example1.com
DocumentRoot /var/www/html
SSLEngine on
# SSL configuration...
For installations where IP separation isn't possible:
ServerName example2.com
RewriteEngine On
RewriteCond %{HTTPS} on
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Always verify changes with:
apachectl configtest
systemctl restart apache2
curl -I https://example2.com
For complex setups, consider adding this to your SSL virtual hosts:
SSLStrictSNIVHostCheck on
When configuring multiple virtual hosts on Apache with mixed HTTP/HTTPS requirements, you might encounter situations where HTTPS requests for non-SSL enabled domains get served by your default SSL VirtualHost. This commonly manifests as:
# Problem scenario:
1. User visits https://example2.com (no SSL configured)
2. Server serves content from https://example1.com (default SSL host)
3. Browser shows certificate mismatch warning
Apache's SSL implementation has an important characteristic: The first defined SSL VirtualHost becomes the default for all HTTPS requests on that IP:port combination. This explains why https://example2.com shows example1.com's content.
Here are three proven approaches to prevent HTTPS access to specific virtual hosts:
# Option 1: Create dedicated non-SSL VirtualHost on port 443
ServerName example2.com
ServerAlias *.example2.com
Redirect 301 / http://example2.com/
SSLEngine off
# Option 2: Use mod_rewrite in main SSL config
ServerName example1.com
SSLEngine on
# ... SSL config ...
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?example2\.com$ [NC]
RewriteRule ^(.*)$ http://example2.com$1 [L,R=301]
# Option 3: Return 403 Forbidden
ServerName example2.com
ServerAlias *.example2.com
SSLEngine on
SSLCertificateFile /path/to/dummy.crt
SSLCertificateKeyFile /path/to/dummy.key
Require all denied
For production environments, I recommend combining redirection with proper error handling:
ServerName example2.com
ServerAlias *.example2.com
# Use a self-signed cert to avoid browser warnings
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
# Redirect all requests to HTTP
RewriteEngine On
RewriteRule ^(.*)$ http://%{HTTP_HOST}$1 [R=301,L]
# Fallback if mod_rewrite isn't available
Redirect 301 / http://%{HTTP_HOST}/
# Log the redirects for tracking
CustomLog ${APACHE_LOG_DIR}/ssl_redirect.log combined
After implementing these changes, verify with:
# Check config syntax
sudo apachectl configtest
# Test with curl
curl -v -k https://example2.com # Should show 301 redirect
curl -v -k -I https://example2.com | grep Location # Verify redirect target
# Check error logs
tail -f /var/log/apache2/error.log