How to prevent hot linking ("image theft" / "bandwidth theft") of ressources on my site?

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


Solution 1:

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.

Solution 2:

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

Solution 3:

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