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

I'm trying to write the "ultimate" anti hot linking .htaccess...

You can find many examples/tutorials/generators on the net but many of them are wrong or incomplete (or even both).

These are the features I'm looking for:

  • Must block hot linking for a list of file extensions when HTTP_REFERER is an foreign site.
  • Must allow hot linking for the current domain (duh) without harcoding it in the .htaccess.
    • For the current domain it must work under http and https.
    • For the current domain it must work with www and without www.
  • Must be able to add exceptions domains to these rules (like our friend Google) and these domains must work under http and https and with www or without www.

This is what I've achieved so far:

<IfModule mod_rewrite.c>

Options +FollowSymlinks
RewriteEngine On

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?mydomain.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?google.com/.*$ [NC]
RewriteRule \.(gif|jpe?g|png|zipx?)$ - [NC,F]

</IfModule>

My questions:

  1. How to avoid to hardcode mydomain.com in the .htaccess? (It would be great to be able to deploy this .htaccess to all my domains without having to modify it for each of them.)
  2. In my RewriteRule, gif|jpe?g|png|zipx? is equivalent to gif|jpg|jpeg|png|zip|zipx right? (Sorry still new at regular expressions.)
  3. Do you see anything bad in my .htaccess that I'm unaware of?

For #1 I know it's somewhat possible. The closest I found is this snippet that removes the www from the URL without hardcoding the domain. Is there a way to use this method to my question #1?

RewriteCond %{HTTP_HOST} ^www\.(.+)
RewriteCond %{HTTPS}s/%1 ^(on(s)|offs)/(.+)
RewriteRule ^ http%2://%3%{REQUEST_URI} [L,R=301]

Update:

I'm aware of solutions that will serve a watermarked image instead of the regular one. But I'm not looking for this kind of solution. I want a universal solution (serve 403 errors) that will work for all kind of binary files (zip, exe, iso, jpg, png, gif...).

share|improve this question
    
IMHO Apache should come with this configuration file at least as an option to include. I wonder if any Apache developers would be willing to add it if you/we could come up with one? –  Chris Nava Aug 11 '11 at 15:09
5  
Don't. Here's why - tomoconnor.eu/blogish/mod-rewrite-killing-social-media –  Tom O'Connor Aug 12 '11 at 13:45
    
@Tom O'Connor Interesting reading and I agree with that. But my script in my case will be used for large binary files (like zip, exe...) and not images and such. So I would still need to get an answer. Yes bandwidth is cheap, but a 500 MB zip is not the same as a 100 KB jpg... –  AlexV Aug 12 '11 at 18:57
    
I wasn't ducking an answer. I was just bitching ;) –  Tom O'Connor Aug 12 '11 at 21:12
    

5 Answers 5

up vote 8 down vote accepted
+25

No matter what you do you will be "wasting" CPU cycles (to determine if the referrer site (the one doing the linking) is authorized or not you must do some processing of the request data).
The only thing you can do is save bandwidth while wasting a minimum of CPU cycles.

There are some examples in the Apache Docs that do exactly what you want. This one:

SetEnvIf Referer example\.com localreferer
<FilesMatch \.(jpg|png|gif)$>
Order deny,allow
Deny from all
Allow from env=localreferer
</FilesMatch>

seems to be the most applicable (and doesn't require the full weight of mod_rewrite).
You can add additional valid referrers with additional SetEnvIf and Allow directives.

share|improve this answer
    
Not bad, but I need a solution that don't hardcode the domain name in the htaccess (read my question carefully). –  AlexV Aug 16 '11 at 13:43
    
Then you need a programmatic solution like Oliver proposed (which still requires you to hardcode a list, regular expression, or some other representation of the allowed referrers - It just lets you put it in a discrete file) –  voretaq7 Aug 16 '11 at 15:01
    
Not necessarily if you look at my 2nd code block you can see it can be done... I just need to adapt it to my case... –  AlexV Aug 16 '11 at 15:33
    
You can use the cleanup logic in your second code block (or similar magic on just %{HTTP_HOST} for less regex parsing) to insert the URL's host into your ruleset, which should buy you dynamic local domains (test extensively), but you would still need to hard-code "nice" external referrers like Google (by referrer, user agent, IP, etc.) –  voretaq7 Aug 16 '11 at 15:47

How about writing a rule that, if referer is unknown (of forbidden), just call a Php file where you pass the image as a param, and in the Php file, just put in big red: "this file comes from MYWEBSITE.COM and has no official authorization to be shown here".

As for your question, make your rule global. Correct me if I'm wrong, but if the rule is declared before any vhost it will be applied on all the vhost (kind of "default rule").

And another idea is simple: just redirect to a Php file (here filter.php) which will look in the authorized website and return the required file if everything is ok:

RewriteRule /(.*)\.jpg$ /filter.php?im=$2\.jpg [QSA,L]

In filter.php just load dynamically a list of vhost or something like that:

if (isset($_SERVER['HTTP_HOST'])) {
   if ((mb_ereg('thereferers\.I\.HATE\.com',HOST) !== false) ) {
       ... your code ...
   }
}
share|improve this answer
    
It's a possibility, but I don't want to "waste" CPU over this (by using PHP). I only want to serve 403s. Also with PHP, you have to manage all the caching issues and this can be quite complex. –  AlexV Aug 12 '11 at 13:48

Cloudflare may be of some help to you: http://www.cloudflare.com

This however only works for images but that seems to be what you are after.

Hotlink Protection

Automatically enable hotlink protection for your images to prevent off-site linking. Referers that are not in-zone and not blank will be denied access. Supported file extensions are gif, ico, jpg, jpeg, and png.

Protected: http://mydomain.com/images/pic.jpg To bypass: http://mydomain.com/images/hotlink-ok/pic.jpg

share|improve this answer

question 1:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://(.+)?yoursite.com/ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule .*.(jpe?g|gif|bmp|png)$ - [F]

question 2:

yes

question 3

I'd use my one

share|improve this answer
    
For question 1, "yoursite.com" is hardcoded so it's not helpful. –  AlexV Aug 22 '11 at 2:03
    
@AlexV: It's not. Just replace yoursite.com with your address you want to ALLOW and other referers will fail to download any images –  genesis Aug 22 '11 at 10:59
    
And how I allow myself without hardcoding it? –  AlexV Aug 22 '11 at 11:32

Or use CoralCDN ant let folk hotlink to their heart's content?

share|improve this answer

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.