Ssl – How to configure SSL with apache2/httpd mass virtual hosting using mod_vhost_alias

apache-2.2httpdhttpsSecurityssl

I have been searching quite a bit now but couldn't find any answers.

I'm using httpd 2.2.15 and Centos 6.2.

I have configured apache for mass virtual hosting. I.e.:

UseCanonicalName off
VirtualDocumentRoot /var/www/html/%0

I will have the same "main" domain with different subdomains pointing to the virtual hosts. I have created a self-signed cert for testing purpose with common name *.mydomain.com. There's one IP for the entire server.

How can I configure apache to use ssl for my vhosts?

And if possible, added to above I would like to achieve this as well:

  1. Can I define a directory, or preferable some files (e.g. login page), that should be excluded from the ssl? All vhosts are basically different instances of the same application (except the ones I mention in 2 below).

  2. Can I define some vhosts that should not use ssl (I have full control of the subdomain name for those). This will be two application, my home-page (www) and some administrative application. If it's not possible to make exceptions, I guess I will just put those on another server.

Except the ones I mentioned in 2 above, all virtual hosts will be created automatically based on users request.

Based on @Shanes comment, I update: If the user use https:// when they shouldn't, it's good if they are redirected to http://. If that's not possible I guess it's ok if they get an error message. It's of course ok if BOTH http and https works, as long as http works for the unprotected files (this may be the preferred choice actually).

I could find examples of how to do this using mod-rewrite with the exception that it wasn't for mass-domains (i.e. < VirtualHost > was used).

What's the tricks for achieving this?

If not possible, I would be most happy to get some hints about how to do this.

Best Answer

First off, you need to make sure your current configuration is prepared to have an SSL listener added in. You haven't specified if you're using the main server, or a <VirtualHost>, but if you're using the main server then you'll need to switch to a <VirtualHost>.

<VirtualHost *:80>
    ServerName everything.example.com
    ServerAlias *.example.com
    VirtualDocumentRoot /var/www/html/%0
    # insert logging config, anything else you need..
    <Directory /var/www/html/>
        Order Allow,Deny
        Allow from all
        # Get rid of this if you need to allow htaccess files:
        AllowOverride None
    </Directory>
    RewriteEngine On
    # We're going to insert some Rewrite configuration here in a minute.
</VirtualHost>

Then, we'll add you a new VirtualHost running SSL.

# Add this if you don't already have it:
Listen 443

<VirtualHost *:443>
    ServerName everything.example.com
    ServerAlias *.example.com
    VirtualDocumentRoot /var/www/html/%0

    SSLEngine On
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/private.key

    # insert logging config, anything else you need..
    <Directory /var/www/html/>
        Order Allow,Deny
        Allow from all
        # Get rid of this if you need to allow htaccess files:
        AllowOverride None
    </Directory>
    # if you want to kick someone back to HTTP if they're using HTTPS,
    # do that with Rewrite configuration here.  For example:
    #RewriteRule ^/(non/sensitive/content.*\.html)$ http://%{HTTP_HOST}/$1 [R=301,L]
</VirtualHost>

So, that gets us to the point where the content is all being served via both HTTP and HTTPS. Now, in order to force HTTPS for certain domains, we can use mod_rewrite.

Important security information! You need to be very careful here from a security perspective. If you're simply redirecting everything on HTTP to the HTTPS equivalent, you can potentially 'hide' cases where a request is sent over HTTP instead of HTTPS due to hardcoded resource locations - and if there's sensitive data in that request, then it was just sent over the internet, unencrypted. You'll need to weigh this risk against your ability to catch and correct these kind of issues, the user-unfriendliness of an error page if something is messed up, and the sensitivity of the data.

To force SSL for certain locations, you'll want to insert mod_rewrite configuration into the port 80 vhost (I've commented in its configuration above). You can build pretty much any kind of behavior you want, as far as directories or domains excluded; I'll provide a few examples:

# Exclude the domain "static.example.com"
RewriteCond %{HTTP_HOST} !^static\.example\.com$
# Exclude the directory /images
RewriteCond %{REQUEST_URI} !^/images/
# Exclude requests to .css files
RewriteCond %{REQUEST_URI} !\.css$
# This is the more secure but less user friendly version - block requests to the non-secured port.
RewriteRule ^ - [F,L]
# This is the user friendly version, where you need to be especially careful that
# your site never sends sensitive data to http accidentally:
#RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

Or, if you wanted to do the friendly redirect just for requests to the base directory, and the error behavior for others:

# Exclude the domain "static.example.com"
RewriteCond %{HTTP_HOST} !^static\.example\.com$
# ..insert other exclusion conditions here..
RewriteRule ^/$ https://%{HTTP_HOST}/ [R=301,L]

# Exclude the domain "static.example.com"
RewriteCond %{HTTP_HOST} !^static\.example\.com$
# ..insert other exclusion conditions here..
RewriteRule ^ - [F,L]

If these examples don't fit your needs, let me know.

Related Topic