Apache: порядок и объединение директив Require

Вопрос или проблема

Я хочу заблокировать список 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 /> приводит к полной блокировке доступа, включая легитимных пользователей.

Решение

Для достижения поставленной цели без значительных затрат ресурсов можно следовать двум стратегиям:

  1. Использовать уровень сети для блокировки IP:
    Оптимальным решением будет блокировка на уровне файрвола, что снимет дополнительную нагрузку с Apache и обеспечит более быструю фильтрацию. В этом случае инструменты такие как ipset помогут организовать и поддерживать большие списки IP-адресов. Это облегчит задачу вашего веб-сервера и уменьшит влияние обработки большого числа правил.

  2. Использование директив 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, если нужно контролировать и отслеживать блокировки на уровне веб-сервера.

Оцените материал
Добавить комментарий

Капча загружается...