Вопрос или проблема
Я хочу заблокировать список IP-адресов и плохих пользовательских агентов на моем веб-сервере Apache.
Поэтому я добавляю это в /etc/apache2/conf-available/blocklist.conf
:
BrowserMatchNoCase "ChatGPT" bad_bot
<Directory />
<RequireAll>
Require all denied # По умолчанию: не давать доступ к корневому каталогу
Require not ip 1.2.3.4
Require not ip 5.6.7.8
Require not env bad_bot
</RequireAll>
</Directory>
Каждый виртуальный хост выглядит так:
<VirtualHost *:443>
ServerName example.org
DocumentRoot /var/www/example.org
<Directory /var/www/example.org>
Require all granted # Разрешить доступ только к корневому каталогу документов
</Directory>
</VirtualHost>
Теперь из-за Require all granted
в виртуальном хосте, первый блоклист с Require not
больше не применяется: боты больше не блокируются.
Поэтому я подумал, что использую <Location />
вместо этого:
BrowserMatchNoCase "ChatGPT" bad_bot
<Location />
<RequireAll>
Require all denied # По умолчанию: не давать доступ к корневому каталогу
Require not ip 1.2.3.4
Require not ip 5.6.7.8
Require not env bad_bot
</RequireAll>
</Location>
Но теперь секция Location перекрывает конфигурацию виртуального хоста, и никто не может получить доступ к виртуальному хосту.
Итак: какова же возможность сохранить мой глобальный блоклист, НО все же иметь возможность использовать “Require all granted” для каждого виртуального хоста, чтобы ограничить доступ к корневым каталогам документов?
Короче говоря: я просто хочу заблокировать некоторые вещи, которые останутся заблокированными, даже если некоторые поздние правила включают “all granted”.
Правка: Я мог бы сделать это для каждого виртуального хоста:
<Directory /var/www/example.org>
<RequireAll>
Require all granted # Разрешить доступ только к корневому каталогу документов
Include /etc/apache2/conf-available/blocklist.conf
</Directory>
Но тогда Apache придется повторно парсить и применять одни и те же тысячи правил для сотен виртуальных хостов, так что это не хорошее решение.
Если вы хотите заблокировать одни и те же IP-адреса для всех веб-сайтов, которые вы размещаете (и не хотите/не нужно представлять дружелюбную страницу ошибки посетителям сайта), я бы заблокировал их в вашем брандмауэре, а не на веб-сервере. Это обычно гораздо “дешевле”. Если вы запускаете сервер Linux с хостовым брандмауэром, использование ipset
является наиболее эффективным способом хранения длинных списков IP-адресов для списков блокировки/разрешения брандмауэра. См. среди прочего этот мой старый ответ
В противном случае: использование include
действительно лучший способ повторно использовать одни и те же директивы в нескольких блоках VirtualHost.
Ответ или решение
Вопрос касается правильного порядка и слияния директив Require в конфигурации Apache для блокировки определённых IP-адресов и пользовательских агентов на веб-сервере. Рассмотрим, как можно эффективно реализовать эту задачу.
Проблема
Вы хотите запрещать доступ к серверу для ряда IP-адресов и "плохих" пользовательских агентов. Изначальная конфигурация использует директивы Require
в корневом каталоге, но при этом схема блокировки теряет свою силу из-за более поздней директивы Require all granted
в виртуальных хостах. Попытка использовать <Location />
приводит к полной блокировке доступа, включая легитимных пользователей.
Решение
Для достижения поставленной цели без значительных затрат ресурсов можно следовать двум стратегиям:
-
Использовать уровень сети для блокировки IP:
Оптимальным решением будет блокировка на уровне файрвола, что снимет дополнительную нагрузку с Apache и обеспечит более быструю фильтрацию. В этом случае инструменты такие какipset
помогут организовать и поддерживать большие списки IP-адресов. Это облегчит задачу вашего веб-сервера и уменьшит влияние обработки большого числа правил. -
Использование директив
Include
Apache:
Если вам необходимо блокировать как IP-адреса, так и пользовательские агенты с помощью конфигурации Apache, используйте директивуInclude
для интеграции вашего файла с блокировками в каждый виртуальный хост. Вот пример стратегии:<VirtualHost *:443> ServerName example.org DocumentRoot /var/www/example.org <Directory /var/www/example.org> <RequireAll> Require all granted Include /etc/apache2/conf-available/blocklist.conf </RequireAll> </Directory> </VirtualHost>
Каждому виртуальному хосту будет присваиваться единая конфигурация из
blocklist.conf
, но Apache придется анализировать этот файл для каждого хоста. Это менее оптимально с точки зрения производительности, но обеспечивает централизацию управления блокировками.
Заключение
В аспекте блокировки нежелательных обращений к вашему серверу наиболее производительным и практичным подходом будет использование сетевых решений наряду с централизованным управлением конфигурациями через Include
, если нужно контролировать и отслеживать блокировки на уровне веб-сервера.