mod-rewriteapache2http-referer

apache2 blocking by referrer not blocking domain


I've been trying everything to block a referrer in apache2 but it's just not working and the entries are still appearing in the logs as if it's just not taking effect.

This is how the entry appears in the logs (access.log): xxx.216.45.xxx - - [09/Feb/2024:13:59:18 +0000] "GET /public/file.txt HTTP/1.1" 200 361 "https://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"

I have ensured that mod_write is on:

a2enmod rewrite
Module rewrite already enabled
root@:~#

This is what I have placed in the .htaccess directly under /var/www/html

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https://(.*\.)?example\.com [NC,OR]
RewriteCond %{HTTP_REFERER} ^https://(.*\.)?example\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^example\.com [NC,OR]
RewriteCond %{HTTP_REFERER} ^example\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^https://example\.com/ [NC]
RewriteRule ^(.*)$ – [F,L]
</IfModule>

But it's still appearing in the logs as a '200' meaning that it's being served and hammering my server. It's coming from multiple IP addresses so I cannot block it that way.

Essentially what I want to do is block anything from https://example.com from accessing anything on the server.

Other things I have checked is that the following lines appear in default-ssl.conf file:

RewriteEngine On
RewriteOptions inherit

And this is the LogFormat line from apache2.conf

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

I'm not sure what else to try, any suggestions would be welcome.


Solution

  • I entered rubbish text, no error.

    If you don't get an error when typing "nonsense" at the top of the .htaccess file (you should get a 500 Internal Server Error) then it would seem the .htaccess file is not even being processed.

    You need to ensure .htaccess overrides are enabled in the server config / VirtualHost container with AllowOverride All (or at least AllowOverride FileInfo to allow the use of mod_rewrite) set in the appropriate <Directory /var/www/html> container. And there are no overriding AllowOverride None directives.

    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTP_REFERER} ^https://(.*\.)?example\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} ^https://(.*\.)?example\.com/ [NC,OR]
    RewriteCond %{HTTP_REFERER} ^example\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} ^example\.com/ [NC,OR]
    RewriteCond %{HTTP_REFERER} ^https://example\.com/ [NC]
    RewriteRule ^(.*)$ – [F,L]
    </IfModule>
    

    Otherwise, this rule is OK, but can be greatly simplified. The <IfModule> is not required (unless this is entirely optional) and the 5 conditions (RewriteCond directives) can be reduced to a single condition.

    Conditions 3 and 4 will never be successful since the Referer header will always contain the protocol. Condition 5 is already handled by the 2nd condition.

    The regex ^(.*)$ can be simplified/optimised since you don't need to match everything (and you certainly don't need to capture anything), it just needs to be successful. And you don't need the L flag when using F since it is implied.

    So the above could be written like this instead:

    RewriteEngine On
    RewriteCond %{HTTP_REFERER} ^https?://(.+\.)?example\.com($|/) [NC]
    RewriteRule ^ – [F]
    

    This is even more encompassing than the original rule as it also blocks plain HTTP referrers as well as HTTPS.