Apache, Wildcard SSL and mod_rewrite

apache-2.2mod-rewritessl-certificate

I have a wildcard SSL cert, which is working fine:

<VirtualHost *:443>
    ServerName star.mydomain.com
    DocumentRoot /dev/null

    SSLEngine On
    SSLCertificateFile /etc/httpd/conf.d/star.mydomain.com.crt
    SSLCertificateKeyFile /etc/httpd/conf.d/star.mydomain.com.key
    SSLCertificateChainFile /etc/httpd/conf.d/star.mydomain.com.gd_bundle.crt
</VirtualHost>

I then have the various sub domains that listen on the SSL port:

<Virtualhost *:80 *:443>
    ServerName staging.mydomain.com
    DocumentRoot /var/www/staging.mydomain.com/
    CustomLog logs/staging.mydomain.com.log combined

    AccessFileName .htaccess
    DirectoryIndex index.php index.html
</VirtualHost>

<Virtualhost *:80 *:443>
    ServerName www.mydomain.com
    DocumentRoot /var/www/www.mydomain.com/
    CustomLog logs/www.mydomain.com.log combined

    AccessFileName .htaccess
    DirectoryIndex index.php index.html
</VirtualHost>

Which is great. I can go to http://staging.mydomain.com/ or https://staging.mydomain.com/ and everything is happy.

Now the trick is, as far as I can tell, there is know way to know if the request is SSL or not in this configuration.

For example, all the environment variables point to the request being non-ssl even when it's an SSL request. I suspect this is due to the implementation of mod_ssl.

In particular, I want to do something like this in the virtualhosts:

RewriteCond %{SERVER_PORT} 80
RewriteCond %{REQUEST_URI} dashboard
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]

But I get a redirect loop because SERVER_PORT is always 80, even under SSL.

I've also tried added a SetEnv IS_SSL 1 in the first star.mydomain.com virtualhost, but the variable also isn't available to mod_rewrite.

Without creating separate ssl/non-ssl virtual hosts for each domain, is there a way of making this work?

Thanks!

Best Answer

I'd suggest looking at the HTTPS variable, which is supposed to be a reliable indicator of whether the current connection is using HTTPS or not. You should be able to do something like this:

RewriteCond %{HTTPS} off
RewriteRule ^/dashboard.* https://%{HTTP_HOST}%{REQUEST_URI} [L,R]

I'd recommend using the [R] flag to force an external redirect because, according to the documentation, Apache checks to see if the hostname in the redirected URL is the same as the one in the current request, and if so it strips off the scheme and hostname and only does an internal rewrite using the URL path (which means it ignores the https:// part of your rewrite rule).