Начнем с хостинга

Хостинг - это десятки тысяч сайтов и пользователей находящихся под управлением одного сервера.

Зачастую пользователь хостинга не погружается в детали настроек сервера, а знает только основное — на сервере есть PHP, Ruby, Python, MySQL и Apache, чтобы его сайт успешно функционировал . Ему не интересно, как и что настроено на сервере, главное, чтоб все работало и не создавало ему проблем.

Рисунок 1: Классическая (упрощенная)  схема хостинг-сервера
Рисунок 1: Классическая (упрощенная) схема хостинг-сервера

По схеме видно, что из сети приходит запрос, проходит фильтрацию в модуле безопасности (фаервол, антивирус и т.д.), далее он попадает на веб сервер (apache, nginx, openlitespeed и т. д.), далее запрос адресуется конкретному сайту, который написан на PHP или на Python или на Ruby, скрипты обращаются к диску к базе данных и т. д. Также для пользователя имеется доступ по ssh, ftp. Каждый пользователь имеет свои cron задачи.

Какие проблемы встречаются чаще всего?

  1. Один «прожорливый» пользователь легко съедает все ресурсы процессора своими скриптами.

  2. Кто-то забивает диск под завязку.

  3. Cron-задачи отдельных клиентов отнимают ресурсы у всех.

  4. Взлом сайта через старый WordPress или уязвимый плагин превращается в дыру для всего сервера.

Но есть еще проблемы безопасности, когда злоумышленник, используя вовремя не обновленный WordPress, забрасывает PHP Shell скрипт и, не имея доступа к SSH, может выполнять команды от пользователя на сервере.

Такой скрипт дает возможность:

1) получить набор пользователей сервера, идентифицировать запущенные сервисы, определить установленные на сервере программные комплексы. Вот пример вывода shell скрипта, при безопасной настройке:

[user1@manager2 ~]$ rpm -qa
error: cannot open Packages database in /var/lib/rpm

А вот пример вывода shell скрипта при небезопасной настройке доступа:

[user2@manager2 ~]$ rpm -qa | head -n5
publicsuffix-list-dafsa-20210518-3.el9.noarch
ncurses-base-6.2-10.20210508.el9.noarch
...

По версиям установленных пакетов, можно определить набор программ, установленных на сервере, и их версии. И возможность обнаружить проблемное или уязвимое ПО.

2) или с помощью такого (гипотетического) скрипта:

for i in `awk -F':' '/\/home/ { print $6 }' /etc/passwd`; 
do 
	ln -sf $i/public_html $i;
	pushd $i 
	cat > .htaccess << EOF
		AddType text/plain .php
	EOF
	popd
done

при неправильной настройке доступа можно получить содержимое PHP-скриптов соседних сайтов и похитить пароли доступа, например к базе данных или API.

3) организовать fork-бомбу, уже не на php, а с помощью shell команды. А такая fork-бомба уже сломает работу программ всех других пользователей.

4) некоторые режимы PHP после обработки запроса не завершаются, а остаются в памяти для ускорения следующих запросов. Это повышает производительность, но может значительно увеличить потребление памяти. Пользователь с большим числом сайтов будет иметь больше запущенных и ожидающих экземпляров PHP, чем пользователь с меньшим числом сайтов. Например подобное поведение характерно для mod_fcgid модуля Apache, который конфигурирует число обработчиков относительно виртуального хоста, а не относительно пользователя.

А какие же существуют решения?

Опытный администратор

Можно положиться на системного администратора, который грамотно настроит сервер. Но это дорого, сложно и требует постоянного внимания.

VPS/VDS/Виртуализация

Данный тип изоляции - решение идеальное, все изолировано по максимуму: файловая система, ресурсы.

Но содержать для каждого сайта отдельную виртуальную машину — дорого и сложно. Это требует от пользователя навыков администрирования: ему самому приходится устанавливать панель управления и настраивать сервер. Такое решение подходит только для профессионалов.

Docker

Существуют панели, которые структуру хостинга распределяют по докер-контейнерам. Каждый пользователь в своем контейнере. Такие панели управления объединяют все сервисы, необходимые пользователю в пользовательском контейнере. В такой контейнер помещаются веб-сервер, база данных, PHP и прочее.

Все это управляется панелью через веб интерфейс и не требует глубоких знаний настройки веб-сервера.

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

Большой оверхед по потреблению памяти, т. к. даже самый маленький сайтик требует наличия своего веб-сервера, возможно базы данных и своего php обработчика и этот контейнер должен быть все время запущен. Т.е решение так же достаточно ресурсоемкое.

Какие еще есть решения?

Одно из решений предложила CloudLinux, разработав технологию LVE (легковесное виртуальное окружение).

Здесь одна хост-система управляет множеством условных легковесных "контейнеров". Каждый условный "контейнер" — это изолированная среда, где ограничивается использование ресурсов и доступ к файловой системе.

По подобному пути предлагаем идти и мы в рамках ОС «МСВСфера» 9 для хостинга, но с использованием новых технологий.

Что дает такой подход в сравнении с другими решениями для хостинга:

LS и LFS МСВСфера

Виртуализация

Docker

Лимитирование потребления ресурсов

+

+

+

Изоляция файловой системы

+/-

+

+

Легкая интеграция с существующей структурой сервера

+

-

-

Отсутствие лишней нагрузки на подсистемы CPU, память, диск

+

-

+/-

А теперь подробнее.

За основу мы взяли Cgroups и PivotRoot.

Хостинговое ПО само по себе не имеет связи с системой лимитирования и изоляции доступной в ОС. Разве что только отдельные настройки, наподобие PrivateTmp или определенной Cgroup, заданной в service файле службы, например Apache или nginx. Но это общий случай, который затрагивает весь сервис, а не конкретный запрос к сайту.

Мы же добавляем дополнительный слой, который более тесно связывает сервис с возможностями изоляции и лимитирования ОС:

Рисунок 2: Цепочка прохождения запроса с изоляцией
Рисунок 2: Цепочка прохождения запроса с изоляцией

Вот, например, для первой подсистемы (Apache, Nginx) — слой LS и LimitedFS встраивается в модули Apache (httpd-itk, mod_fcgid, suexec) или в PHP-FPM.

Т.е. в тот момент, когда порождается новый процесс для пользователя, информация об этом новом процессе и информация об этом пользователе отправляется на специальный сервис, который решает в какую cgroup поместить этот новый процесс. Для него подготавливается файловая структура, которая будет считаться корневой.

Для CRON, SSH, SU – данный слой представлен модулем PAM, в котором при проверке прав пользователя происходит настройка лимитированной и изолированной среды.

Для третьего же блока (это работа веб приложений на Python, Ruby, JS) — данная прослойка представлена модулем mod_passenger, в недрах которого мы можем получить данные о пользователе, запросившем запуск приложения. Для порождаемого приложения также подготавливается изолированная и лимитированная среда.

Лимитирование ресурсов (подсистема LS): CPU, память, своп, и максимальное число процессов в LS-контейнере. «LS-контейнер» - это условное название указывающее, что процессы сгруппированы и контролируются по одним и тем же правилам.

Значения лимитов отслеживает служба, которая позволяет изменять параметры для каждого LS-контейнера.

Т.е, если установить, что пользователь с UID = 1000 должен утилизировать не более 1.5 ядер CPU из 8 ядер, то он не сможет преодолеть этот лимит, даже при одновременной загрузке 30 сайтов. Тот же эффект достигается и для памяти.

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

Так же SSH, CRON, SU дополнительно еще и попадают в свой PID Namespace, т.е они не видят реальных системных PID процессов даже если от пользователя за пределами namespace был запущен другой процесс.

Все параметры потребления ресурсов аккуратно пишутся в базу данных и могут быть использованы администратором для анализа активности пользователя. На следующем рисунке можно увидеть статистику потребления ресурсов системы в контрольной панели ispmanager.

Рисунок 3: Пример UI с отображением статистики потребления ресурсов
Рисунок 3: Пример UI с отображением статистики потребления ресурсов

Подсистема лимитирования - LS

А сейчас хотелось бы немного подробнее рассказать про лимитирование. Как я уже ранее упоминал, лимитами посредством cgroups управляет служба klsd. Эта служба настраивает контролируемые подсистемы cgroups (на текущий момент это cpu io memory pids), если в cgroup.subtree_control нет этой нужной подсистемы — она добавляется.

Далее создается дерево из слайсов. Для каждого слайса — листика дерева, настраиваются необходимые значения для нужной подсистемы (cpu.max для cpu, memory.max для памяти и т.д). Значения лимитов сервис берет из собственной базы, в которую могут вносить изменения утилиты для конфигурирования лимитов. Таким образом организуется взаимодействие администратора и сервиса лимитирования.

Рисунок 4: Схема дерева cgroup
Рисунок 4: Схема дерева cgroup

И далее сервис или программа, у которой имеется привилегия с помощью библиотеки LS API отправляет информацию о процессе, который должен быть ограничен, а также идентификатор слайса, в который данный процесс должен быть помещен.

Служба klsd немедленно выполняет запрос, помещая запросивший процесс в нужный slice.

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

Например, привилегированный процесс sshd запрашивает у службы klsd помещение себя в ограниченную среду. После этого он создаёт внутри неё дочерние процессы, которые остаются в этой среде. Затем sshd выходит из-под ограничений, а процессы, обслуживающие запросы пользователя, остаются в лимитированной среде.

Порядок работы алгоритма лимитирования процесса представлен на рисунке 5.

Рисунок 5: Алгоритм процесса лимитирования
Рисунок 5: Алгоритм процесса лимитирования

Подсистема изоляции — LimitedFS

Система изоляции разделяет процессы пользователей, блокируя доступ к чужим домашним директориям и файлам. Процессы пользователя выполняются не в реальной (настоящей) файловой системе (ФС), где видны все пользователи, а в своей «персональной», изолированной файловой системе. Изоляция пользователей повышает стабильность и безопасность сервера, уменьшая возможность влияния одного пользователя на других. Файлы реальной файловой системы, содержащие конфиденциальную информацию, а также потенциально опасные программы отсутствуют в изолированной файловой системе. Это уменьшает число возможных векторов злонамеренных атак и улучшает безопасность сервера.

Большая часть файловой системы для такого изолированного процесса пользователя предоставляет доступ к файлам в режим ReadOnly, благодаря чему не ломается функционал программ в окружении пользователя, но при этом он не может и навредить другим. Производительность практически не страдает, так как личный корневой каталог каждого пользователя заранее подготавливается и кэшируется. При запуске процесса он быстро подключается, что минимизирует затраты времени.

Файловую систему LimitedFS можно разделить на общую часть, одинаковую для всех пользователей, и персональные части, что исключает дублирование файлов и экономит место на диске, по по сравнению с docker-контейнерами.

Для каждого пользователя создается персональный mount-неймспейс, внутри которого выполняется монтирование персональной части файловой системы (ФС) поверх общей части ФС. Внутри персонального mount-неймспейса примонтирована только домашняя директория этого пользователя, другие могут быть добавлены администратором. Домашние директории других пользователей отсутствуют (не видны). Поэтому всяческие скрипты, по прощупыванию прав доступа на основе доступных конфигурационных файлов и понимания состава системы, сразу отпадают.

Рисунок 6: Демонстрация работы LimitedFS
Рисунок 6: Демонстрация работы LimitedFS

Как видно на рисунке 6, на примере файла /etc/passwd, пользователь видит только то, что ему разрешено видеть - это некоторые системные пользователи, а также своя учетная запись. Другие пользователи ему не отображаются, т.е классический скрипт, приведенный ранее по поиску неверно настроенных прав в каталогах других пользователей уже не отработает.

Чем удобно решение «МСВСфера»?

  • это легкость интеграции с существующим хостингом, с контрольными панелями. Минимальные усилия по переходу на использование изоляции от «МСВСфера»

  • легкость настройки, в основном все минимально необходимые конфигурации уже включены в установку по умолчанию.

  • минимальный оверхед

  • потребление памяти аналогично использованию только Apache/nginx и PHP

  • простота интеграции с сервисами поддерживающими PAM.

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

  • изоляция менее надежная чем докер и VPS

  • не все сервисы могут быть таким образом изолированы

  • большая связь с реальной системой, например нельзя скрыть от пользователя число ядер или название процессора

В заключение хотелось бы рассказать о процедуре внедрения LS и LimitedFS на существующих серверах. Один из таких случаев описан в статье на Хабр: "Первые в России: как мы стали хостинг-провайдером на отечественной ОС".

Изоляция и ограничение пользователей — это must-have для современного хостинга, так как позволяет уплотнить пользователей на сервере, ограничить их влияние друг на друга и на сервер в целом. А средства мониторинга будут позволять выявлять нарушителей и тех, кто хочет больше, чем тариф ему позволяет.

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

Решения бывают разные: от ручной настройки до VPS. Но «МСВСфера» предлагает золотую середину — лёгкую интеграцию, минимальные затраты и адекватный уровень защиты

Надеюсь данная статья окажется полезной, при создании и планировании будущего сервера.

Спасибо за внимание.

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