Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Ignoring the merits of whether we should make this change or not (the circumstances are slightly complex and probably covered by my NDA), our client would like us to require that visitors to the site we're building have come from another of their sites. If a user comes to us from elsewhere, they should be sent to the login screen of that other site.

It feels like the easiest way to do this is using mod_rewrite to redirect anything with a referrer that is neither our site nor this other one.

My current thinking is

In httpd.conf

RewriteMap deflector txt:/path/to/
RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} =NOT-FOUND
RewriteRule ^ [R=307,L]


// -
// -
// -
// -

This would allow us to expand the list of "permissible referrers" quite easily, which feels like a good idea.

I have three questions then:

  1. Is mod_rewrite (which we're already using extensively) the best way of doing this?
  2. If it is, then is a 307 Temporary Redirect response the best way to handle it?
  3. As I'm not primarily a LAMP dev / admin, have I made any stupid typos in those rewrite rules? ;o)

It feels to me that 307 Temporary Redirect or 403 Forbidden are the most appropriate status codes and I assume it's A Bad Thing™ to send a Location: redirect header with a 4xx response.

That all make sense?

Edit: Are the map searches case-*in*sensitive by default? Do I need to worry about case here?
Edit 2: Are map searches a regex search or a whole-key match? If the map contains and the Referer: header reads will it match?

share|improve this question
Think about what's going to happen here when a browser doesn't return a referer. BTW you can't send a location response with a 4xx status code. – symcbean Jan 19 '12 at 14:25
@symcbean Yeah, that's why I have RewriteCond %{HTTP_REFERER} !="" there first. And thanks, I didn't think I could send a Location: header with a 4xx code. – Owen Blacker Jan 19 '12 at 14:42

I think the map will be case-sensitive, and also you need to extract the hostname from the Referer. I haven't tested it at all but something like this might perhaps work:

RewriteMap deflector txt:/path/to/
RewriteMap lc int:tolower
RewriteCond %{HTTP_REFERER} ^https?://([^:/?]+)
RewriteCond ${lc:%1} (.+)
RewriteCond ${deflector:%1|NOT-FOUND} =NOT-FOUND
RewriteRule ^ [L]

Don't faff around with unusual response codes; the default of 302 is fine.

share|improve this answer
Ah, of course. Thank you. The only thing I'm not sure about is the arguments to the last line — should that [L] be [R,L] (with R=302 being implicit)? – Owen Blacker Jan 19 '12 at 17:58
I think the [R] isn't necessary as the rewrite is to an absolute URL so mod_rewrite defaults to it. – Jon Ribbens Jan 19 '12 at 18:03
up vote 0 down vote accepted

What we've actually ended up doing is as follows:

RewriteCond %{REMOTE_HOST} !A.B.C.(D|E)
RewriteCond %{HTTP_HOST}==%{HTTP_REFERER} !^(.*?)==https?://\1/ [NC]
RewriteCond %{HTTP_REFERER} !https?:// [NC]
RewriteRule ^ [R,L]

The first RewriteCond (and several more lines like it) mean that developers and the client are not restricted by this referrer check (as it's really tiresome to have to go there first before going to our site).

The second RewriteCond is a work of genius to check if the referrer is the same as the Host: in the request. This is based on terrye's answer to SO#7398191: Generic mod_rewrite referrer check — because mod_rewrite only does variable interpolation in the test string, you can't have a line reading

RewriteCond %{HTTP_HOST} !^https?://%{HTTP_REFERER}/ [NC]

as it simply won't do that check.

Apparently we're "never" gonna need to allow any other referrers. If we did, I guess I'd just have to set that last RewriteCond line to end [NC,OR] and chain some more conditions along.

All working nicely. Thanks for your help, everyone!

share|improve this answer

Your Answer


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.