Рекурсивное множественное добавление IP для блокировки в файл .htaccess

    Задача. На 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
    • +3
      Вопрос: что же делать, когда на сервере не 2 и не 3 сайта, а намного больше?

      Если цель — заблокировать на уровне сервера, для всех сайтов — почему бы не добавить блокировку один раз в одно единственное место — центральный конфиг апача?
      И поддерживать легче, и велосипеды не нужны.
      • 0
        это верно, если есть доступ к центральному конфигу. Если это твой сервер и ты админ — да. Если это виртуальный хостинг и ты клиент — скорее всего нет. Так именно в моем случае.
        • 0
          Опять же, если ты админ, то да. Но я забыл упомянуть, что это виртуальный хостинг и доступа к конфигу iptables нет
          • 0
            Опять же, если ты админ, то да. Но я забыл упомянуть, что это виртуальный хостинг и доступа к конфигу iptables нет
      • 0
        если для IP не надо отдавать страницу 403, то можно обойтись iptables -I INPUT -s 194.165.16.76 -j DROP
        • 0
          Опять же, если ты админ, то да. Но я забыл упомянуть, что это виртуальный хостинг и доступа к конфигу iptables нет
        • 0
          А unban как делается? Например, по причине ошибки.
          • 0
            Думаю, что здесь подойдет команда sed '0,/Deny from 194.87.147.196/{//d;}' .htaccess

            Точнее могу сказать, когда попробую и всё проверю.
          • 0
            А чего не положить блокирующий .htaccess в ~/public_html?
            • 0
              А потому, что на виртуальном хостинге он там бесполезен.
            • +1
              http://stackoverflow.com/questions/13640511/include-another-htaccess-file-from-htaccess
              Второй ответ с редиректом — не?
              • 0
                что же делать, когда на сервере не 2 и не 3 сайта, а намного больше?

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

                • +5
                  Что за бред на хабре?
                  • 0

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

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

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.