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


4 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