Forum Moderators: phranque

Message Too Old, No Replies

Hotlink Help over here

         

andre3

12:59 pm on Oct 11, 2010 (gmt 0)

10+ Year Member



First off, thanks to JD an all the others for the previous help they have given me.

I have a issue with preventing users from hotlinking my files,
when I upload a file to: domain.com root directory, an hotlink it on another site it works like how I want it to, however, if I hotlink it to a subdomain on the same server,same domain.com, it handles the request as if the subdomain isn`t on the same domain.

I would like the htacess hotlink code to be smart enough to recognize subdomain on the same domains as a valid refer, instead of giving me the hotlink error, my code is below.

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?domain.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://(www\.)?domain.com$ [NC]

RewriteRule .*\.(jpg|jpeg|gif|png|bmp|mp3)$ error.html [R,NC]

sublime1

2:57 am on Oct 12, 2010 (gmt 0)

10+ Year Member



The description here is a bit unclear and doesn't quite match what the rewrite rules say -- when you say "a subdomain" do you mean just the "www" subdomain, or others, for example "blog.domain.com"? Assuming you only are having the problem with www, I think the following commented version is a little tighter -- but probably won't change the behavior you're seeing...


# If the request doesn't have an empty referer field
RewriteCond %{HTTP_REFERER} !^$
# and if the referer doesn't start with domain.com or www.domain.com
RewriteCond %{HTTP_REFERER} !^http://(www\.)?domain.com [NC]
# Return a 302 redirect to error.html for all files ending with these extensions
# and stop processing further rewrite rules.
RewriteRule \.(jpg|jpeg|gif|png|bmp|mp3)$ error.html [R,NC,L]


Having two RewriteCond expressions to test for your own domain is unnecessary. I removed the .*$ because it is redundant (all strings end with zero or more characters), and similarly the .* from the beginning of the RewriteRule (all strings match zero or more characters).

The only significant change is that I added the "L" flag to the rewrite rule so no further rewrites would be processed. This could be the source of the problem, but again, it doesn't fit your description ... unless there are additional rewrites before or after.

Otherwise, as far as I can see, as my changes are mostly just semantic. So if you're seeing something else, please provide more tangible examples of what works and what doesn't.

FYI, if you're writing examples here with URLs in them, surround them with the style codes "code" (in square brackets) and "/code" to make sure they don't get mangled.

Tom

andre3

7:23 pm on Oct 12, 2010 (gmt 0)

10+ Year Member



Thank you Man, an I meant subdomains such as: name.domain.com

and thats all the code I have

sublime1

7:41 pm on Oct 12, 2010 (gmt 0)

10+ Year Member



If there are subdomains other than www, and potentially multiple (e.g. foo.bar.domain.com), you'll need to change:
RewriteCond %{HTTP_REFERER} !^http://(www\.)?domain.com [NC]
to
RewriteCond %{HTTP_REFERER} !^http://(.*\.)*?domain.com [NC]


The bit (.*\.)*? means the first of zero or more something plus a dot. The * means zero or more, the ? may ore may not be needed -- in this context makes the * "non-greedy" -- normally * finds the longest match possible but adding the ? makes it find the smallest match.

You should test this out, but this might get you pointed in the right direction.

Tom

andre3

11:12 pm on Oct 12, 2010 (gmt 0)

10+ Year Member



I tried that, now it pops up the file for download even when I am on a another site clicking the url of the .mp3 file hosted on my site, instead of redirecting me to the error page.

jdMorgan

4:30 am on Oct 13, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Since we're looking at a referer, there's no telling what might be 'beyond' the protocol and the hostname at the beginning. Further using a ".*" pattern is going to force the matching engine to examine every character in the referrer string at least once. And finally, allowing the matching engine to scan the whole referrer string actually opens an exploitable hole, since all I --playing the part of Mr. "Bad Guy Hotlinker" for a moment here-- have to do is to, say, append a query string (with your domain in it) to my own page URL in order to hotlink your images. It is true that most hotlinkers aren't malicious enough to find out how to do this or to implement it, but the really malicious ones would make for a bigger problem. So a better sub-pattern is needed.

Also, you cannot redirect an image request to an HTML page unless the hotlinked image was to be loaded "naked" in a new tab or window from a clickable link on the hotlinking page. If loaded normally, using an <img src="image.jpg"> included-object tag, the browser will not be able to handle replacement of an image-type embedded object with a "whole new Web page." Simply put, "a Web page can't fit in the image box" on the hotlinking page. It simply can't work in this case, and this is a likely reason you're seeing the "download" prompt.

I suggest redirecting instead to a replacement image that scales well and that is readable over a wide range of aspect ratios that says "No Hotlinking" or something simple. If all of the hotlinked images that this replacement image might replace are big enough, then include a image of your site's URL as well (keep it short).

If this rule redirects all hotlinked image requests to a replacement .jpg image, than that replacement image request will be redirected as well (to itself, and repeatedly). An exclusion to allow the replacement image to load is needed to prevent an 'infinite' redirection loop in this case.

With all of the above in mind, the code would look like this:

RewriteCond %{HTTP_REFERER} .
RewriteCond %{HTTP_REFERER} !^http://([^.:/]+\.)?domain\.com
RewriteCond %{REQUEST_URI} !^/no_hotlinking\.jpg$
RewriteRule \.(jpe?g|gif|png|bmp)$ http://www.domain.com/no-hotlinking.jpg [NC,R=302,L]

The mp3 and other multimedia filetypes present a challenge. If you really need to replace those requests instead of out-right denying them with a 403, then I suppose you could record a nice little "Don't hotlink my stuff, my friends" jingle, or recite your site's URL, and then add another rule like the one above to replace hotlinked mp3s with your message.

While working on this, keep in mind that the hotlinked requests in your log are from people who are visiting the hotlinker's site, and it is not their fault that that site hotlinked your resources. So, err on the side of moderation when designing these 'alternate resources' to be served to hotlinked visitors... :)

When deciding what filetypes can be redirected to what replacement filetypes, I believe that you will find the initial part of the MIME-type identifiers to be most useful.. text/html and text/plain can replace each other, as can any of the image/xyz types, etc. When getting into some of the fancier types like video, be aware of cross-platform and cross-browser support issues. For example, you cannot assume that the visitor has a Flash or Windows Media player plug-in with any degree of certainty, so it's probably best to replace same with same for all of these.

Frankly, I don't bother with any of the above details, and simply use

RewriteCond %{HTTP_REFERER} .
RewriteCond %{HTTP_REFERER} !^http://([^.:/]+\.)?domain\.com
RewriteRule \.(gif|jpe?g|png|bmp|css|js|pdf|xls|doc|txt|swf|flv|wmv|avi|mov|mp[34g])$ - [F]

The only thought that goes into this approach is to order the filetypes roughly from most-frequently to least-frequently requested (check your 'stats' to determine this).

If you allow search engines to cache and display your images, you will need to add exclusions to these rules to allow that, since these are also hotlinked requests.

Other than that -- Check it, deny it, done.

Jim

andre3

1:05 am on Oct 14, 2010 (gmt 0)

10+ Year Member



Thank you guys, you`ve been very helpful, I appreciate it.
the codes work fine on www.domain.com even when I hot link a file on another domain it works fine by redirecting me to the error image.

The issue I am having now is, the code do not work on subdomains: (sub.domain.com), If I link a file to the hotlinker site example: sub.domain.com/file.mp3, instead of redirecting me to the error image, it pops the file up for download, I wonder if its because all the domains are virtually created, I also use htacess to lead to the virtual sub domains root folder path that looks like this: /Genre/sub,

my code below:


RewriteCond %{HTTP_REFERER} .
RewriteCond %{HTTP_REFERER} !^http://([^.:/]+\.)?(domain1|domain2)\.(net|com)
RewriteCond %{REQUEST_URI} !^/ref\.gif$
RewriteRule \.(jpe?g|gif|png|mp3)$ http://www.domain.com/error.gif [NC,R=302,L]

andre3

5:43 pm on Oct 15, 2010 (gmt 0)

10+ Year Member



anyone ?

jdMorgan

5:54 pm on Oct 15, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> I also use htacess to lead to the virtual sub domains root folder path that looks like this: /Genre/sub

Then you'll need a copy of the anti-hotlinking code in that subdirectory as well. Requests for that subdomain are likely mapped straight to that subdirectory, so the this (main) .htaccess file won't be executed for subdomain requests...

The image file URL-path in the last RewriteCond needs to match the image URL-path that you are redirecting to, otherwise, you will get an infinite redirection loop, as previously discussed. "ref.gif" and "error.gif" must match, and one or the other name must be wrong.

Jim

andre3

6:30 pm on Oct 15, 2010 (gmt 0)

10+ Year Member



I see, I have alot of subdomains, that means I would ever have to write a code to create htacces file to all sub directories ?

Is there any other way to create one htaccess file/ or apache config file with the hot link code to govern all sub domains ?

Thanks

jdMorgan

7:29 pm on Oct 15, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Either put a copy of the code in each subdomain's root folder, or put the code into the main server config where it will apply globally, regardless of which VirtualHost is requested.

Note that the code will need to "know" all of the valid domains and subdomains, and if you only use one rule, then those domains and subdomains will still be able to "hotlink" each other's files.

Actually, it's possible to avoid this problem using an "atomic back-refernce" if this is necessary. Otherwise, it is impossible to do a variable-to-variable compare, as in "If requesting referrer domain == this domain". You can use associativity to do this with an atomic back reference, in that, if A+B==A+A, then A=B. So that might be useful for comparing the linking hostname with the requested hostname and avoids needing to "list" and test all the hostnames in the rule.

Jim