9

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...).

10

5 Answers 5

9
+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.

4
  • Not bad, but I need a solution that don't hardcode the domain name in the htaccess (read my question carefully).
    – AlexV
    Aug 16, 2011 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, 2011 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, 2011 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, 2011 at 15:47
3

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 ...
   }
}
1
  • 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, 2011 at 13:48
1

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

0
0

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

3
  • For question 1, "yoursite.com" is hardcoded so it's not helpful.
    – AlexV
    Aug 22, 2011 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, 2011 at 10:59
  • And how I allow myself without hardcoding it?
    – AlexV
    Aug 22, 2011 at 11:32
-1

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .