Search code examples
.htaccesshotlinkingunknown-host

Stop hotlinking using htaccess and non-specific domain code


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]

Solution

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