0

I want to block a list of IP addresses and bad user agents on my Apache web server.

So I'm adding this to /etc/apache2/conf-available/blocklist.conf:

BrowserMatchNoCase "ChatGPT" bad_bot <Directory /> <RequireAll> Require all denied # Default: don't give access to root directory Require not ip 1.2.3.4 Require not ip 5.6.7.8 Require not env bad_bot </RequireAll> </Directory> 

Each vhost is like this:

<VirtualHost *:443> ServerName example.org DocumentRoot /var/www/example.org <Directory /var/www/example.org> Require all granted # Allow access to document root only </Directory> </VirtualHost> 

Now because of the Require all granted in the vhost, the first blocklist of Require not don't apply anymore: the bots are no longer blocked.

So I thought I would use <Location /> instead:

BrowserMatchNoCase "ChatGPT" bad_bot <Location /> <RequireAll> Require all denied # Default: don't give access to root directory Require not ip 1.2.3.4 Require not ip 5.6.7.8 Require not env bad_bot </RequireAll> </Location> 

But now the Location section takes over the vhost config, and no-one can access the vhost.

So: what is the solution to be able to keep my global blocklist BUT still be able to use "Require all granted" for each vhost to restrict access to document roots?

Long story short: I just want to block some stuff, that will stay blocked even if some later rules include "all granted".

Edit: I could do this for each vhost:

 <Directory /var/www/example.org> <RequireAll> Require all granted # Allow access to document root only Include /etc/apache2/conf-available/blocklist.conf </Directory> 

But then Apache would have to re-parse and re-apply the same thousands of rules for the hundreds of vhosts, so not a good solution.

1 Answer 1

1

If you want to block the same IP-addresses for all websites that you’re hosting (and don’t want/need to present a friendly error page to site visitors) , I would block them in your firewall and not from the webserver. That is generally much “cheaper”. When you’re running a Linux server with a host based firewall , using ipset is the most efficient way to store long lists of IP-addresses for firewall block/allow lists. See among others this old answer of mine

Otherwise: using the include is indeed the best method to re-purpose the same directives in multiple VirtualHost blocks.

2
  • Yes but I also want to block based on the user-agent. Commented Jan 10 at 15:21
  • It seems that using the <If...> statement works as I want, it overrides any other config: <If "-z env('good_bot') && -z env('good_ip') && ( -n env('bad_bot') || -n env('spam_ref') || env('bad_ip')"> Require all denied </If> This is because <If> is the last to be merged: httpd.apache.org/docs/2.4/en/sections.html#merging Commented Jan 10 at 21:34

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.