Как снизить нагрузку на виртуальный хостинг

Много посетителей на сайте — это всегда радость для веб-мастера. По мере роста сайта, можно перейти на более дорогой тариф или арендовать дополнительные ресурсы сервера, например, дополнительное процессорное время:

Но иногда нагрузка на сервер непропорциональна количеству посетителей, обычно такие проблемы возникают из-за разного рода сканеров, создателей зеркал веб-сайтов, агрессивно скачивающих содержимое ботов. Из-за них нагрузка на сервер может возрастать слишком резко и, главное, неоправданно:

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

Я буду показывать на примере самой ходовой связки: виртуальный хостинг на котором работает WordPress. Я буду показывать на примере своего хостера (Hostland) — некоторые из инструкций вы сможете применить у себя в том виде, как они даны, но для некоторых инструкций нужно будет внести соответствующие изменения под ваши условия.

Поскольку за основу взят виртуальный хостинг, то мы исходим из того, что основные DDoS защиты установлены на уровне хостера (против разного SYN флуда, полуоткрытых соединений и прочего) — нам эти настройки в любом случае недоступны (к тому же, обычно под это выделено специальное оборудование). Мы рассмотрим защиту и настройку на уровне веб-приложений.

Установка и настройка плагина iThemes Security

Установите в WordPress плагин iThemes Security. У него есть разные функции, но самыми полезными для снижения нагрузки на сервер являются:

  • Отслеживание ошибки 404
  • Заблокированные пользователи

Ошибка 404 возникает если не существует файла, который запрашивает пользователь. Чаще всего эта ошибка возникает при сканировании вашего сайта, когда злоумышленник ищет бэкапы, конфигурации с неправильными расширениями файла и вообще другие интересные ему вещи. С помощью функции «Отслеживание ошибки 404» если посетитель слишком много раз запросил файл, который не существует, то сначала он блокируется временно, а после рецидива — блокируется перманентно.

Заблокированные IP адреса автоматически добавляются в раздел настроек «Заблокированные пользователи». От вас вообще не требуется никаких действий — всё происходит полностью автоматически.

Также в разделе «Заблокированные пользователи» можно добавить пользовательские агенты (User-Agent) которые также будут блокироваться. Пример моего списка:

HTTrack
sqlmap
wpscan
text
Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT;
-
CyotekWebCopy
Wget
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.3) Gecko/20010801
Mozilla/5.0 (Windows NT 6.2; rv:26.0) Gecko/20100101 Firefox/26.0
WebCruiser
yacybot
Opera/9.27
MauiBot
Mozilla/4.5 (compatible; HTTrack

Здесь пользовательские агенты различных сканеров, а также создателей зеркал сайтов — они очень сильно нагружают хостинг и не несут абсолютно никакой пользы.

Более подробно об этом плагине и описание его функций в этой статье.

Настройте кэширование сайтов

Для этого в Панели управления хостингом перейдите во вкладку Домены:

В списке доменов, напротив сайта с большой посещаемостью активируйте PageSpeed, а также Настройки фильтров Nginx:

В Настройке фильтров Nginx включите

  • Кеширование всех графических документов.
  • Кеширование всех текстовых документов.
  • Ограничение автоматических запросов для входа в Joomla, WP и пр.
  • Ограничение для подозрительных IP адресов

Блокировка IP, с которых приходит слишком много запросов

Мы не будет блокировать посетителей, которым нравится ваш сайт и которые смотрят много страниц. Мы будет блокировать программы, которые делают огромное количество запросов (иногда несколько запросов в секунду) в течение длительного времени.

Далее инструкция может показаться довольно трудной, но сделанные настройки стоят потраченного времени. Я постараюсь всё описать как можно подробнее — если вам что-то непонятно, то спрашивайте в комментариях.

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

И таких логов:

когда одним IP за пару часов было сделано почти 30 тысяч запросов:

Для анализа логов, нам понадобится SSH доступ. Обратите внимание, что вам не нужен SSH клиент, не нужно настраивать ключи или что-то ещё — все действия выполняются прямо в веб-браузере в Панели управления хостингом. Кстати, там работают привычные Ctrl+c и Ctrl+v — используйте эти сочетания клавиш для копирования и вставки команд.

Чтобы попасть в консоль SSH перейдите во вкладку FTP/Файлы, затем SSH, далее Открыть SSH клиент:

Файлы журналов (логи) находятся по адресам вида ДОМЕН/logs, например, для сайта hackware.ru логи лежат в директории hackware.ru/logs. Чтобы посмотреть, какие файлы в этой папке, будем использовать команду ls -l, для моего случая:

ls -l hackware.ru/logs

Перейдём в интересующую нас папку с помощью команды cd, в моём примере это папка hackware.ru/logs:

cd hackware.ru/logs

Чтобы узнать, какие IP адреса больше всего сегодня нагружали сервер, введите команду:

cat access_log | awk '{ print $1 ; }' | sort | uniq -c | sort -n -r | head -n 10

Показан «ТОП» IP, приславших больше всего запросов к серверу. В левой колонке — количество сделанных запросов, в правой — сам IP адрес.

В самом верху IP адрес 185.26.122.50 — это адрес самого веб-сервера. Такая особенность вызвана тем, что:

  • используется кэширование
  • WordPress постоянно делает запросы сам к себе, например, для работы Cron (с этим мы разберёмся дальше)

Нельзя блокировать IP адрес сервера! Вы только всё поломаете. Чтобы проверить, какой IP адрес у вашего сервера, прямо в этой командной строке введите команду:

dig ВАШ_САЙТ

Например, чтобы узнать IP адрес hackware.ru:

dig hackware.ru

Итак, адрес сервера всегда игнорируем.

Переходим к следующему — 5.144.127.143. Чтобы полностью вывести запросы, которые делал определённый IP адрес за сегодня, выполните команду вида:

cat access_log | grep 'IP адрес'

Например, я хочу увидеть все запросы, которые сделал к веб-серверу IP адрес 5.144.127.143:

cat access_log | grep '5.144.127.143'

Пример фрагмента вывода:

Несколько запросов в секунду к одной и той странице на протяжении длительного времени, а также другая хрень, в общей сложности 14119 бессмысленных запросов — всё ясно, баним его.

Скорее всего с командой cat будет выведено очень много строк, поэтому рекомендую применять для исследования также команды head, tail, less и другие для анализа с текстовыми файлами — подробности об использовании этих программ смотрите в «Основах командной строки Linux».

Смотрим следующий IP адрес 95.153.133.123, который только за сегодня сделал 11518 запросов к сайту:

cat access_log | grep '95.153.133.123'

Вновь множество бессмысленных запросов:

Если нужно исследовать лог файл за предыдущий день, например, за вчерашний, то обратите внимание на файлы с расширением .gz. access_log.1.gz — это вчерашний журнал, access_log.2.gz — это позавчерашний журнал и так далее.

.gz — это архивы, но их содержимое можно смотреть без распаковки, если использовать команду zcat. Например, я хочу узнать, какие IP адреса сделали больше всего запросов за вчера. Тогда команда следующая:

zcat access_log.1.gz | awk '{ print $1 ; }' | sort | uniq -c | sort -n -r | head -n 10

Вместо файла access_log.1.gz в этой же команде можно указать позавчерашний или архив с журналом за любой доступный день.

Кроме IP веб-сервера, имеются адреса из одного диапазона:

  • 95.153.133.123
  • 95.153.128.194
  • 95.153.128.29
  • 95.132.63.204

Они и образовали тот горб, который на скриншоте загруженности веб-сервера в самом начале этой инструкции — кому-то, видимо, нечем заняться.

Узнать информацию об IP можно прямо там же — в SSH окне. Для этого используйте команду whois. Например:

whois IP_адрес

Показанный способ нахождения и блокировки IP, с которых приходит слишком много запросов на сервер, можно автоматизировать. Можно создать простейший скрипт, который будет проверять, не превысил ли какой-либо IP адрес порог разумного количества запросов. При этом скрипт будет запускаться автоматически с помощью Cron. В результате на вашем сервере всегда будет «страж» который регулярно будет следить за логами веб сервера и в случае обнаружения нарушителя, закроет ему доступ на сервер.

Для этого создайте файл fcuker.sh и скопируйте в него:

#!/bin/bash

FULLPATH='/home/host00000/SITE.ru/'
MAXCHECKS=30
MAXREQUESTS=2000
SERVERIP='185.26.122.38'
SILENT=0

cat ${FULLPATH}logs/access_log | awk '{ print $1 ; }' | sort | uniq -c | sort -n -r | head -n $MAXCHECKS | while read count ip; do
    if [[ $count -gt $MAXREQUESTS ]]; then
        if [[ "$ip" != "$SERVERIP" ]]; then
            if [[ -z "`grep $ip ${FULLPATH}/htdocs/www/.htaccess`" && -z "`whois $ip | grep -E -i 'yandex|google'`" ]];then
                echo "" >> ${FULLPATH}htdocs/www/.htaccess
                echo "Deny from $ip" >> ${FULLPATH}htdocs/www/.htaccess
                if [[ $SILENT -ne 1 ]]; then
                    echo "Заблокирован $ip за слишком большое количество запросов."
                fi
            fi
        fi
    fi
done

Код делает следующее:

  • проверяет файл журнала за сегодняшний день и ищет 30 (можно изменить в настройках) IP, которые создали самую большую нагрузку на сервер
  • проверяет, есть ли среди этих IP те, которые сделали более 2000 (можно изменить в настройках) запросов к серверу
  • если нашлись такие адреса, то для них проверяется, не были ли они заблокированы ранее — для этого они ищутся в файле .htaccess
  • также для каждого такого адреса проверяется информация по whois. И если там есть упоминание Yandex или Google, то такие IP не блокируются — это разумно, поскольку поисковые системы могут активно индексировать сайт, но блокировать их категорически не рекомендуется
  • в конце концов, если IP сделал слишком много запросов, если он не заблокирован ранее и не имеет отношения к поисковым системам, то он банится через .htaccess

Кажется, словами я объяснял дольше, чем имеет строк сам скрипт.

Прежде чем начать работать, нужно сделать настройки.

Во первых в значении переменной FULLPATH нужно указать путь до файлов. Этот путь состоит из трёх элементов:

  • начало строки /home
  • затем через слэш ваш идентификатор на хостинге /host0000000
  • затем через слэш адрес сайта со слэшем на конце, например, /hackware.ru/

Должно получиться примерно так:

FULLPATH='/home/host0000000/hackware.ru/'

Переменная MAXCHECKS устанавливает, сколько искать самых активных IP. На не очень посещаемых сайтах достаточно и 10. Установите значение от 10 до 30, например:

MAXCHECKS=30

Далее в переменной MAXREQUESTS указывается, после скольких запросов заблокировать IP адрес. Обычный посетитель очень редко делает за сутки более 1000 запросов на один сайт — но такие бывают! Практически ни один пользователь не делает более 2000 запросов за сутки. Поэтому установите значение от 1000 до 2000. В случае если на ваш сайт идёт распределённая DDoS атака, то установите более низкое значение, чтобы скрипт быстрее банил злоумышленников. Пример:

MAXREQUESTS=2000

В переменной SERVERIP обязательно пропишите IP адрес вашего сайта — этот адрес будет всегда игнорироваться. Это важно сделать, поскольку WordPress обильно инициализирует запросы на самого себя, которые имеют IP адрес сервера, также система кэширования обращается к сайту и имеет IP сервера, пример:

SERVERIP='185.26.122.38'

Если установить SILENT на 0, то при блокировке IP будет выводиться соответствующее сообщение в консоль. Если установить на 1, то это сообщение выводиться не будет, пример:

SILENT=0

Когда настройка закончена, загрузите этот файл в корень вашего сайта — туда где лежат файлы index.php и другие.

Теперь опять вернитесь в SSH окно и там проверьте работу скрипта примерно следующей командой:

bash /home/host900000/ВАШ_САЙТ.ru/htdocs/www/fcuker.sh

В ней после bash указан полный путь до скрипта в системе. То есть этот путь начинается с /home, затем идёт ваш идентификатор на хостинге (host900000), затем ВАШ_САЙТ.ru, затем /htdocs/www/ и имя скрипта fcuker.sh.

Если скрипт кого-то заблокировал — значит он работает. Если не выведено никаких сообщений об ошибках — весьма вероятно, что всё в порядке. Если появилось сообщение об ошибке, то напишите его в комментарии — попробуем разобраться вместе.

Файл fcuker.sh не является каким-то секретным, но некоторые предпочитают не раскрывать свой идентификатор, либо свои настройки блокировки — чтобы не помогать злоумышленникам. Поэтому разумно запретить скачивание этого файла. Для этого откройте файл .htaccess и добавьте туда строки:

RewriteEngine on
RewriteRule ^fcuker\.sh - [NC,F]

Кстати, для дополнительной «конспирации» файл со скриптом можно назвать по-другому (это не принципиально), но тогда не забудьте поменять имя файла также и в команде запуска, и в .htaccess

Теперь нам нужно сделать так, чтобы этот скрипт запускался без нашего участия. Можно настроить, чтобы программа запускалась один раз в час, или каждые 30-20-10 минут — на ваш выбор.

В любом случае, мы переходим на вкладку Cron:

Нажимаем кнопку Добавить запись.

В качестве исполняемой команды вводим команду вида

bash /home/host900000/ВАШ_САЙТ.ru/htdocs/www/fcuker.sh

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

Например, можно задать запускать скрипт каждые 10 минут. Тогда нужно отметить минуты для запуска. Например, можно выбрать 1, 11, 21, 31, 41 и 51 минуты. Можно выбрать 2, 12, 22, 32, 42, и 52 минуты. Думаю, принцип вы поняли.

Если хотите запускать каждую пятнадцатую минуту, то можно выбрать, например, 0, 15, 30, 45.

Если хотите запускать каждые пол часа, тогда можно выбрать 1 и 31 минуты.

Если только один раз в час — тогда просто выберите любую минуту (только одну).

В других колонках (Часы, День месяца, Месяц, День недели) везде поставьте галочку в пункте Каждый. Получается примерно так:

Когда всё готово, нажмите кнопку Сохранить.

Кстати, все ваши запланированные задачи Cron вы можете увидеть не только в веб-интерфейсе, но и в командной строке через SSH, для этого запустите там команду:

crontab -l

На самом деле, там же их можно и редактировать и устанавливать новые, в том числе делать более тонкую настройку cron, но для этого нужно быть более знакомым как с самим Cron, так и с vim.

Для редактирования используется команда (не запускайте её, если не знаете как выйти из vim).

crontab -e

Пример, как настроено у меня:

У меня файл называется kickddosers.sh, для сайта hackware.ru установлен запуск каждые 5 минут (у сайта много недругов LOL laugh), для других сайтов установлен запуск каждые 10 минут.

После установки расписания в cron, скрипт будет регулярно запускаться и без необходимости вашего присутствия выявлять IP адреса, которые создают слишком большую нагрузку на сервер и блокировать их.

Отключение встроенного в WordPress cron'а

В WordPress встроен аналог cron'а. Он участвует в автоматической проверке и установки обновлений самого WordPress, в публикации статей по расписанию и в других автоматизированных задачах. Cron в WordPress по умолчанию включен.

При анализе логов я обратил внимание, что количество запросов к файлу wp-cron.php превышает разумное количество, например, команда для подсчёта запросов 'POST /wp-cron.php' в файле access_log.2.gz:

zcat access_log.2.gz | grep 'POST /wp-cron.php' | wc -l

За сутки только для одного сайта было сделано 23674 запросов! Я полистал веб журнал — некоторые запросы отправляются каждую секунду или по несколько раз за одну секунду — это почти как маленькая DoS атака. Это не только слишком много, это просто не нужно в таком количестве.

Дело в том, WordPress инициирует запрос к файлу wp-cron.php при каждом открытии любой страницы сайта любым пользователем. Если посещаемость сайта несколько десятков человек в сутки или несколько сотен — то это более-менее нормально. Но если посещаемость измеряется тысячами, то получаются такие запредельные цифры запросов к файлу wp-cron.php.

Из такой ситуации самым лучшим является следующий выход:

  • отключения автоматического cron в WordPress
  • настройка автоматического cron на хостинге, которые «вручную» будет запускать cron в WordPress

Для отключения cron в WordPress откройте файл wp-config.php и добавьте туда после <?php строку:

define('DISABLE_WP_CRON', true);

Сохраните и закройте файл. Всё, теперь крон отключён. Для ручного запуска cron в WordPress, чтобы он проверил и выполнил задачи по расписанию, нужно делать запрос к файлу wp-cron.php. Для этого достаточно в веб-браузере открыть адрес вида ДОМЕН/wp-cron.php. Эту рутинную работу за нас может делать программа curl, чтобы она открывала адрес используется команда вида:

curl https://ДОМЕН/wp-cron.php >/dev/null 2>&1

К команде добавлен >/dev/null 2>&1 чтобы все сообщения, в том числе об ошибках, не выводились и не отправлялись вам на почту.

Например, для сайта hackware.ru команда запуска cron в WordPress следующая:

curl https://hackware.ru/wp-cron.php >/dev/null 2>&1

Чтобы мне не приходилось её запускать вручную, я настраиваю новое задание Cron прямо на хостинге:

Я настраиваю запуск расписаний Cron для WordPress один раз в час. На мой взгляд, делать это чаще просто бессмысленно. В некоторых инструкциях я видел мнение, что среди расписаний заданий Cron в WordPress есть в том числе проверка комментариев на SPAM: то есть, если установить запуск крона раз в час, то и проверки на СПАМ будут раз в час. Но, видимо, это не так — по крайней мере в новых версиях WordPress комментарий на спам фильтры проверяются мгновенно, независимо от работы Cron.

Что ещё можно сделать для снижения нагрузки на хостинг?

Чем больше в WordPress плагинов, тем больше нагрузка на сервер. Для малопосещаемых сайтов нет смысла отказывать себе в удобстве. Но для сайтов под тяжёлой нагрузкой (много посетителей или DDoS атака) есть смысл отключить тяжёлые плагины, которые интенсивно используют базу данных. Пример таких плагинов: сбор статистики о посещениях и посетителях. В принципе, функции таких плагинов вполне могут заменить счётчики Яндекс.Метрики или Google Аналитики.

Что делать если не хватает процессорного времени на хостинге

Если вы всё настроили и попробовали как показано выше, а нагрузка на CPU на хостинге всё равно слишком большая, то есть несколько вариантов:

  • докупить процессорное время на хостинге;
  • расселить сайты по разным аккаунтам виртуального хостинга;
  • перейти на VPS хостинг.

Все три способа связаны с дополнительными денежными затратами и перечислены в порядке увеличения дополнительной платы — что именно выбрать нужно решать в индивидуальном порядке исходя из конкретных условий.

Докупить процессорное время — самый простой и наименее затратный вариант — плата за дополнительный аккаунт всё равно будет выше. Последний третий вариант нужно выбирать если вы действительно «выросли» из виртуального хостинга. Кроме оплаты за VPS также нужно учитывать оплату правильной настройки и поддержки VPS.

Хостинг где размещены мои сайты и на примере которого я делал настройки. При регистрации по ссылке — дополнительные бонусы!

Рекомендуется Вам:

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

Ваш e-mail не будет опубликован.