2

I need to write an anti-hotlink command for my .htaccess file but it can not be specific to any domain name in particular. Here's what I found on another sites so far but I'm not sure exactly why it doesn't work, can anyone spot the problem?

# Stop hotlinking.
#------------------------------
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} ^https?://([^/]+)/ [NC]
# Note the # is just used as a boundary. It could be any character that isn't used in domain-names.
RewriteCond %1#%{HTTP_HOST} !^(.+)#\1$
RewriteRule \.(bmp|gif|jpe?g|png|swf)$ - [F,L,NC]
Vince
  • 910
  • 2
  • 13
  • 29
  • Note: The code above is based on another Stackoverflow post/answer that doesn't seem to work. [link](http://stackoverflow.com/questions/12242438/how-to-generic-htaccess-to-prevent-hotlink) – Vince Jul 03 '13 at 17:33
  • That works for me when I put it in a blank htaccess, any hotlinked image comes back 403, every image I view on a page of the same site comes back 200. – Jon Lin Jul 03 '13 at 19:34
  • @jon Hi Jon, I mentioned below that for some reason it started working again for me. I think I'm being bamboozled by browsers that simply won't clear their cache when pages are refreshed using SHIFT + Reload Button. Nonetheless, I did need a little bit more help understanding exactly how this code worked and Ravi has done a great job. – Vince Jul 03 '13 at 20:48

1 Answers1

1

Try this.

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} ^https?://(www\.)?([^/]+)/.*$ [NC]
RewriteCond %2#%{HTTP_HOST} !^(.+)#(www\.)?\1$ [NC]
RewriteRule \.(bmp|gif|jpe?g|png|swf)$ - [F,L,NC]

Would even work when only one of the referrer or target url has a leading www.

EDIT : (how does this % thing work?)

%n references the n(th) bracket's matched content from the last matched rewrite condition.

So, in this case

  • %1 = either www. OR "" blank (because it's optional; used ()? to do that)
  • %2 = yourdomain.com (without www always)

So, now the rewrite condition actually tries to match

yourdomain.com#stealer.com OR yourdomain.com#www.stealer.com

with ^(.+)#(www\.)?\1$ which means (.+)# anything and everything before # followed by www. (but again optional); followed by \1 the first bracket's matched content (within this regex; not the rewrite condition) i.e. the exact same thing before #.

So, stealer.com would fail the regex while yourdomain.com would pass. But, since we've negated the rule with a !; stealer.com passes the condition and hence the hot-link stopper rule is applied.

Ravi K Thapliyal
  • 51,095
  • 9
  • 76
  • 89
  • `%2` cannot be used in the pattern parameter of a `RewriteCond` – Jon Lin Jul 03 '13 at 19:31
  • @JonLin Ah, that's correct. Suddenly, OP's condition now makes a lot of sense to me. Thanks. – Ravi K Thapliyal Jul 03 '13 at 19:45
  • @Ravi Now I'm really confused, all of a sudden my first example is working again and from the looks of it after you made that last edit your code suggestion looks almost exactly the same as my question code. Can you point out the specifics enhancements you made and why you think they are necessary? I'm most confused about how line 3 actually works. How does `%2#%{HTTP_HOST}` really work? – Vince Jul 03 '13 at 20:04
  • And why separate out `(www\.)?`, is that not something automatically included in HTTP_HOST strings for websites that use it? – Vince Jul 03 '13 at 20:16
  • Damb 5 minute timeout... Do servers that are initially setup as abc.com with an alias of www.abc.com only output abc.com for the HTTP_HOST regardless of which one is called? – Vince Jul 03 '13 at 20:25
  • @Vince Please check my updated rule as well as the explanation. – Ravi K Thapliyal Jul 03 '13 at 20:35
  • @Vince %{HTTP_HOST} would start with "www." (or not) based on whether stealer.com's hot-linked url or the url that was entered in the browser to access your site includes it or not. – Ravi K Thapliyal Jul 03 '13 at 20:37
  • @ravi Little typo I think Ravi. `yourdomain.com#stealer.com OR yourdomain.com#www.stealer.com` should be `yourdomain.com#stealer.com OR www.yourdomain.com#stealer.com`. I might be wrong, this is a difficult subject for me. – Vince Jul 03 '13 at 20:51
  • @Vince The `(www\.)?` and `%2` in the rewrite condition makes sure that the match would always start with `yourdomain.com#`. When coming from your own site with a `www.` it would apply the regex on `yourdomain.com#www.yourdomain.com` which would still pass because `(www\.)?` is optional in the regex. The reason it's so convoluted is because we can't tell whether %{HTTP_HOST} is coming with or without `www.` :) – Ravi K Thapliyal Jul 03 '13 at 21:05