How to Disable HTTPS for Specific Virtual Hosts in Apache to Prevent SSL Mismatch


12 views

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