Задача. На web-сервере в домашней папке ~/public_html привычным образом располагаются каталоги различных сайтов. Таким же привычным образом в каждом каталоге сайта располагается файл .htaccess. Известно, что с помощью этого файла, в том числе, ограничивается доступ по IP. В моём случае этот файл выглядит так:

Order Allow,Deny
Allow from all
Deny from 194.87.147.196

Эта запись (блок) встречается в каждом файле .htaccess каждого сайта в папке public_html всего один раз. И если требуется заблокировать доступ ко всем сайтам по IP, например 194.165.16.76 – в каждый файл, после строки «Allow from all» добавляется новая строка:

Deny from 194.165.16.76

Вопрос: что же делать, когда на сервере не 2 и не 3 сайта, а намного больше?
Вот как я попытался решить эту задачу.

Команда find


Команда find поможет нам найти все файлы .htaccess рекурсивно, начиная с указанной папки, если мы из любого места выполним следующее:

find ~/public_html -type f -name .htaccess

Параметр –exec


Далее нам нужно выполнить некоторые манипуляции над файлом, а именно:

  1. Найти строчку «Allow from all»
  2. Вставить после неё строчку «Deny from 194.165.16.76»

В этом нам поможет параметр –exec для команды find. В частности я использовал потоковый редактор sed. То есть, для частного случая, для конкретного файла .htaccess мне помогает команда:

sed -i "/Allow from all/a Deny from 194.165.16.76" .htaccess

Теперь, соединяем вместе find и sed:

find ~/public_html -type f -name .htaccess –exec sed -i "/Allow from all/a Deny from 194.165.16.76" {} \;

Выполнив эту команду, bash найдет все файлы .haccess и вставить в них Deny from 194.165.16.76 сразу после Allow from all.

Скрипт bash


Сократили одну часть рутины, Идем дальше, стремясь к тому, чтобы не набирать каждый раз одни и те же длинные команды. Создаём в домашней папке файл ~/addblacklistip со следующим содержимым:

#!/bin/bash

me=`basename $0`

if [[ $# -lt 2 ]]; then
    echo "Usage $me <start_path> <IP_address>"
    exit
fi

find $1 -type f -name .htaccess -exec sed -i "/Allow from all/a Deny from $2" {} \;

Далее выполняем команду:

chmod +x ~/addblacklistip

Наш скрипт готов к использованию. Например, для внесения во все файлы .htaccess блокировки по IP 7.7.7.7 просто выполняем команду:

~/addblacklistip ~/public_html 7.7.7.7

Замечания и дополнения


ТО, ЧТО ВЫ ДЕЛАЕТЕ – ВЫ ДЕЛАЕТЕ НА СВОЙ СТРАХ И РИСК!


Во-первых, много раз проверяйте все команды и скрипты, что вы запускаете. Тем более, когда речь идет о файлах .htaccess. Во-вторых, не поленитесь создать тестовую папочку с вложенными папками и файлами .htaccess, чтобы всё проверить.

Если раздел блокировки у вас выглядит по другому…


Добавьте в то место, куда бы вы хотели вносить новые записи о блокировке, ключевое слово, например #Add next IP here. Это могло бы выглядеть так:

Order Allow,Deny
Allow from all
Deny from 194.87.147.196
#Add next IP here
Deny from 194.87.147.196

А в скрипте строку:

find $1 -type f -name .htaccess -exec sed -i "/Allow from all/a Deny from $2" {} \;

замените на строку:

find $1 -type f -name .htaccess -exec sed -i "/#Add next IP here/a Deny from $2" {} \;

Теперь новые записи о блокировке будут появляться после ключевой записи #Add next IP here.

Если все сайты находятся не в папке ~/public_html, а в ~/www?


Просто выполняйте скрипт с такими параметрами:

~/addblacklistip ~/www 7.7.7.7

где 7.7.7.7 – блокируемый IP.

Если у меня много IP для добавления?


Насколько много? Тут отдельная тема для анализа вопроса и дальнейшей автоматизации.
Поделиться с друзьями
-->

Комментарии (16)


  1. kornerz
    03.02.2017 16:13
    +3

    Вопрос: что же делать, когда на сервере не 2 и не 3 сайта, а намного больше?

    Если цель — заблокировать на уровне сервера, для всех сайтов — почему бы не добавить блокировку один раз в одно единственное место — центральный конфиг апача?
    И поддерживать легче, и велосипеды не нужны.


    1. mokhin-denis
      03.02.2017 17:08

      это верно, если есть доступ к центральному конфигу. Если это твой сервер и ты админ — да. Если это виртуальный хостинг и ты клиент — скорее всего нет. Так именно в моем случае.


      1. mokhin-denis
        03.02.2017 17:14

        Опять же, если ты админ, то да. Но я забыл упомянуть, что это виртуальный хостинг и доступа к конфигу iptables нет


        1. mokhin-denis
          03.02.2017 17:16

          Опять же, если ты админ, то да. Но я забыл упомянуть, что это виртуальный хостинг и доступа к конфигу iptables нет


  1. potapuff
    03.02.2017 16:20

    если для IP не надо отдавать страницу 403, то можно обойтись iptables -I INPUT -s 194.165.16.76 -j DROP


    1. mokhin-denis
      03.02.2017 17:36

      Опять же, если ты админ, то да. Но я забыл упомянуть, что это виртуальный хостинг и доступа к конфигу iptables нет


  1. rocket
    03.02.2017 16:33

    А unban как делается? Например, по причине ошибки.


    1. mokhin-denis
      03.02.2017 17:39

      Думаю, что здесь подойдет команда sed '0,/Deny from 194.87.147.196/{//d;}' .htaccess

      Точнее могу сказать, когда попробую и всё проверю.


  1. scorp13
    03.02.2017 18:55

    А чего не положить блокирующий .htaccess в ~/public_html?


    1. mokhin-denis
      03.02.2017 19:08

      А потому, что на виртуальном хостинге он там бесполезен.


  1. imwode
    03.02.2017 23:23
    +1

    http://stackoverflow.com/questions/13640511/include-another-htaccess-file-from-htaccess
    Второй ответ с редиректом — не?


  1. selivanov_pavel
    04.02.2017 00:23

    что же делать, когда на сервере не 2 и не 3 сайта, а намного больше?

    Нагенерить конфиги и разложить их во нужным папкам чем-нибудь вроде ansible/chef/…, что умеет шаблоны. Потребует много работы в начале, зато потом поддержка всего этого хозяйства станет значительно проще.


  1. l0rda
    04.02.2017 01:02
    +5

    Что за бред на хабре?


    1. maggg
      04.02.2017 22:46

      Да ваще. Виртуальный хостинг, htaccess, bash-скрипты для раскладывания конфигов Апача… Серьёзно?


    1. Nauti1us
      05.02.2017 10:20
      +1

      Поддерживаю. Не проще ли если сайтов "… не 2 или 3.." купить нормальный впс и рулить там как админ.


      1. selivanov_pavel
        05.02.2017 17:55

        Ну почему же. Если для имеющихся задач такого хостинга хватает, то зачем впс? Ради чего добавлять себе задачи по настройке сервера, обслуживанию, регулярным обновлениям, мониторингу? Наоборот, всё непрофильное надо выносить на аутсорс. Вот когда начнёт упираться в ограничения этой технологии — тогда переходить и стоит.