Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I think that I have this sorted (thanks mainly to the question How to redirect non-www to www without hardcoding using .htaccess?), but I still don't entirely understand a couple of things.

I would like to force all non-SSL connections to my server to be routed to SSL. I have only one vhost (and that will reliably remain the case for the lifetime of the server), but I would like to avoid hard-coding the domain name, partly so that the httpd.conf files for Staging and Production remain identical.

I know I can force requests to use SSL with a mod_rewrite rule like

RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

or

RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

I have two relatively simple questions, though:

  1. Should I prefer one of those RewriteCond statements over the other for any reason? Presumably if I use the %{SERVER_PORT} variable, any connections on, say, port 8000 would continue to be served in the clear? Is there some reason I should avoid using the %{HTTPS} variable that I'm overlooking?
  2. Will that %{HTTP_HOST} variable in the RewriteRule statement be respected and automagically substitute in whatever the Host: header was from the request? Is there some circumstance under which this might not work?

In case it makes a difference, we're running Apache 2 on RedHat with mod_ssl and the site used Drupal 7.

Sorry for what is a relatively stupid question; Apache sysadmin is by no means a core part of my job, so I'm trying to muddle through as best I can. Thanks, all!

share|improve this question
    
@jaymzcampbell on Twitter pointed out that he'd always use %{HTTPS}, are there's no guarantee that your non-ssl is being served over 80, which confirms my suspicion. He also mentioned "afaicr http_host comes from the inbound request indeed": twitter.com/jaymzcampbell/statuses/158980755693912064 –  Owen Blacker Jan 16 '12 at 20:50
2  
There is a possibility for %{HTTP_HOST} not to be set — where it’s the default virtual host on the port and somebody sends a request without including a Host: request header. This would be rather rare, though, to say the least. Beyond that, I can’t think of a scenario where it would occur. –  Mo. Jan 17 '12 at 13:38
    
Ah, I would guess that's plausible here — there is only the one virtual host on this server and it's possible-but-unlikely that someone might try to connect with HTTP/1.0, not sending a Host: header. Should I worry about it, in your opinion? –  Owen Blacker Jan 17 '12 at 13:53
    
I wonder if there's a way to detect the HTTP Version in apache, and redirect them to somewhere that says "Upgrade your client, bitches" –  Tom O'Connor Jan 17 '12 at 13:54
1  
There is — create a default (i.e., first in the list on that port) virtual host which does just that (it doesn’t even have to say “upgrade your client” — “you didn’t specify a virtual host in your request, so we can’t process further” will do). –  Mo. Jan 17 '12 at 13:59

1 Answer 1

up vote 4 down vote accepted

I've always used something like the following:

RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

Because occasionally, I like to serve HTTP over ports other than 80. Well, I don't like to do it, but sometimes needs must, etc. %{HTTPS} will be true, for example, if SSL is being used over port 80.

I think I usually use

RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

%{HTTP_HOST} will always be whatever is set as the Host: header by the client.

It occurs to me, however.. that there's another way to do this.

<VirtualHost *:80>
   ServerName mysite.example.com
   Redirect permanent / https://mysite.example.com/
</VirtualHost>

You'll notice there's no DocumentRoot in the above block. If you're redirecting everything, you don't need one.

If you only wanted to redirect a bit of your site to SSL, you could just do

Redirect permanent /secure https://mysite.example.com/secure

I think the Redirect option is more preferable for full site HTTPS forcing, because it's one less level of insanity (as provided so kindly by mod_rewrite).

It might even be faster, as there'd be one less module to load / run.

share|improve this answer
2  
wiki.apache.org/httpd/RedirectSSL This is pretty much what Apache themselves say. –  Tom O'Connor Jan 17 '12 at 13:35
    
We need to use mod_rewrite elsewhere in the configuration, so I think I'd rather use your first suggestion and avoid having to specify ServerName, but thanks, that's exactly what I needed to know. –  Owen Blacker Jan 17 '12 at 13:37
1  
Just implemented this and it seems to be working a treat. Thank you very much Tom and Mo. –  Owen Blacker Jan 18 '12 at 13:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.