Комментарии

Галерея

Опрос

Из каких стран идет больше всего спама, попыток взлома на ваши серверы?:

Виртуализация или запускаем приложение в chroot-окружении. Размышления.

Аватар пользователя maximum
     

Недавно передо мной встала задача запускать определенное приложение или набор приложений в так называемой песочнице.
Немного покапавшись в гугле я нашел для себя несколько вариантов как можно реализовать это. В этой заметке я опишу несколько вариантов, а так же напишу почему некоторые мне не подошли. Предполагается, что мы знакомы с lxc, chroot, openvz, jail, и считаем свой уровень познаний в linux высоким.
Краткий экскурс в суть вопроса:
Предположим у нас есть парк компьютеров, с linux на борту, нам в силу определенных интересов, будь то вопрос о защите персональных данных или вопрос о сохранении чистоты файловой системы необходимо запускать приложение, в моем случае браузер firefox и утилита для сканирования sane в собственном окружении изолированном от хост-системы, при чем, каждый раз, когда пользователь включает свой компьютер это окружение автоматически создается и по факту пользователь работает полностью в новой системе.
Вариант №1
Использование lxc-контейнера.

Цитата:
LXC (англ. Linux Containers) — система виртуализации на уровне операционной системы для запуска нескольких изолированных экземпляров ОС Linux на одном компьютере. LXC не использует виртуальные машины, а создает виртуальное окружение с собственным пространством процессов и сетевым стеком. Все экземпляры LXC используют один экземпляр ядра ОС.

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

ls -l /usr/lib/lxc/templates/
lxc-busybox - набор минимальный, для запуска busybox
lxc-debian - полноценный шаблон для debian, для установки необходим пакет debootstrap
lxc-fedora - полноценный шаблон для fedora
lxc-sshd - минимальный набор для создания контейнера для запуска ssh-сервера, после создания потребуется настроить сеть bridge
lxc-ubuntu - шаблон для ubuntu

Что пробовал я, создавал полностью систему из шаблона ubuntu, вышло примерно 700мб дискового пространства, учесть что каждый день контейнер должен пересоздаваться + автоматически устанавливаться firefox и sane, этот вариант отпал сразу. Хотя "из коробки" все завелось без проблем. От создания полноценной виртуальной системы пришлось отказаться, я перешел к созданию контейнера lxc для запуска в нем приложения, за основу брал шаблон debian, после установки контейнер занимал примерно ~400мб, что тоже не айс. Немного почитал про структуру файловой системы в lxc контейнерах, я предпринял попытку ручного создания контейнера, для этого необходимо создать дерево файловой системы:

root@server:/home/hellname# tree /var/lxc/simple/
/var/lxc/simple/
├── fstab
├── lxc-simple.conf
└── rootfs
    ├── bin
    ├── dev
    │   └── pts
    │       ├── network
    │       └── shm
    ├── etc
    ├── lib
    ├── proc
    ├── root
    ├── sbin
    ├── sys
    ├── usr
    └── var
        ├── empty
        ├── lib
        └── run

Немного поясню, /var/lxc/simple -- директория файлов контейнера, rootfs - директория с псевдо-файловой системой
fstab - файл, в котором мы указываем что и куда монтировать из хост-системы в контейнер, lxc-simple.conf - конфиг контейнера.

root@server:/home/hellname# cat /var/lxc/simple/fstab 
/lib /var/lxc/simple/rootfs/lib none ro,bind 0 0
/bin /var/lxc/simple/rootfs/bin none ro,bind 0 0
/usr /var/lxc/simple/rootfs/usr none ro,bind 0 0
/sbin /var/lxc/simple/rootfs/sbin none ro,bind 0 0
root@server:/home/hellname# cat /var/lxc/simple/lxc-simple.conf 
lxc.utsname = simple
lxc.mount = /var/lxc/simple/fstab
lxc.rootfs = /var/lxc/simple/rootfs

Для запуска firefox из этого контейнера, нам необходимо создать симлинки библиотек firefox, чтобы узнать какие либы он использует поможет утилита ldd. Делаем симлинки, либо просто копируем эти либы в аналогичные директории lxc-контейнера, далее копируем саму директорию с firefox в аналогичную директорию lxc-контейнера. Иногда возникает проблема с запуском графических приложений которые должны использовать X хост-системы, по этому если приложение не запускается, следует примонтировать:
/tmp/X11/.X11-unix в /var/lxc/simple/rootfs/tmp/.X11-unix/ Соответсвенно директория /tmp/.X11-unix в lxc-контейнере должна присутствовать.
Пробуем запустить контейнер:
lxc-execute -n simple -f /var/lxc/simple/lxc-simple.conf firefox
Если все прошло хорошо, firefox должен запуститься.
С этим вариантом мы разобрались, теперь почему он не подходит мне! Изначально я не просто так упомянул такие слова, как персональные данные и чистота системы, а учитывая что дела в lxc с cgroup обстоят плохо, то о никакой песочницы гостевой файловой системы речи не идет. Мы можем просто нажать Ctrl+O в firefox и увидеть файловую систему хост-системы. Но я не хочу сказать что LXC это сырое и ужасное поделие, отнюдь, простота и легкость создания и масштабирования контейнеров просто впечатляет, и если разработчики не оставят свой проект, то я думаю у него большое и светлое будущее, кстати в Яндекс насколько я знаю используют допиленный LXC для создания виртуальных контейнеров.
Еще немного обдумав все варианты и возможные концепции создания отдельного, изолированного окружения, которое никак не позволит гостевому пользователю заглянуть в файловую систему хост-системы (тавтология, мать вашу) я начал копать в сторону нативного chroot и легковестных дистрибутивов linux.
Вариант №2
Создание chroot окружения и запуск приложения.

Итак, понеслось.
В интернете существует множество легковестных дистрибутивов, например DSL, tinycorelinux и т.п. Я остановился на slitaz.
Подготавливаем место для нашей песочницы:
Создаем директорию
# mkdir -p /var/chroot/slitaz
Создаем директорию для временного монтирования образа системы
# mkdir /tmp/slitaz
Скачиваем образ slitaz, я скачал сборку cooking, взять можно отсюда.
Далее нам необходимо смонтировать этот образ в /tmp/slitaz, это нужно для того, чтобы взять rootfs.gz (корневая файловая система)
# mount -o loop /var/chroot/slitaz/slitaz-cooking.iso /tmp/slitaz
Копируем rootfs.gz в chroot-окружение
cp /tmp/slitaz/boot/rootfs.gz /var/chroot/slitaz
Нам необходимо распаковать этот архив, это не обычный gz-архив, по этому нужно сделать следующее:

# cd /var/chroot/slitaz
# unlzma rootfs.gz -S .gz
# cat rootfs | cpio -id

Итогом выполнения этих команд должен быть результат вывода утилиты tree:

# tree -L 1
.
├── bin
├── dev
├── etc
├── home
├── init
├── lib
├── media
├── mnt
├── proc
├── root
├── sbin
├── sys
├── tmp
├── usr
└── var

Но это еще не все, нам необходимо примонтировать некоторые разделы из хост-системы в chroot-окружение, для автоматизации этого процесса можно воспользоваться скриптом, написанным разработчиками slitaz, ВАЖНО! так как нам потребуется запуск графики, то монтируем /dev и /tmp

#!/bin/sh
# Chroot in SliTaz to hack.
#
ROOTFS="/var/chroot/slitaz"
 
# подключение виртуальной файловой системы ядра и chroot.
#
mount --bind /dev $ROOTFS/dev
mount --bind /tmp $ROOTFS/tmp
mount -t proc proc $ROOTFS/proc
mount -t sysfs sysfs $ROOTFS/sys
mount -t devpts devpts $ROOTFS/dev/pts
mount -t tmpfs shm $ROOTFS/dev/shm
 
echo "Переключение chroot в $ROOTFS... "
chroot $ROOTFS /bin/sh --login
 
# отключение виртуальной файловой системы ядра при выходе.
#
umount $ROOTFS/dev/shm
umount $ROOTFS/dev/pts
umount $ROOTFS/sys
umount $ROOTFS/proc
umount $ROOTFS/tmp
umount $ROOTFS/dev
 
echo "Выход из окружения chroot $ROOTFS... "
 
EOF

Теперь, чтобы зайти в гостевую систему, нам просто нужно запустить этот скрипт, а для выхода набрать exit в гостевой системе.
Находясь в гостевой системе, обновим репозитории, в slitaz используется собственная система управления пакетами tazpkg:
Но для начала настроим сеть, у меня на хост системе интерфейс wlan0

root@hell:/# udhcpc -i wlan0
udhcpc (v1.12.0) started
Sending discover...
Sending select for 192.168.0.130...
Lease of 192.168.0.130 obtained, lease time 86400
deleting routers
route: SIOCDELRT: No such process
adding dns 192.168.0.1
# tazpkg recharge
Увидим примерно следующее:
Creating backup of the last packages list...                         [ OK ]
Mirrored packages diff
================================================================================
35 new packages on the mirror.

Установим firefox:
# tazpkg get-install firefox
tazpkg сам разрулит зависимости и стянет все что необходимо для запуска графики.
Теперь для запуска firefox мы сделаем:
export DISPLAY=:0.0
а на хост-системе:

# xhost +
# access control disabled, clients can connect from any host

Собственно все, запускаем firefox:
на хост-системе выполняем:
# chroot /var/chroot/slitaz firefox
Перед нами firefox запущенный в slitaz chroot-окружении

Полезные ссылки:
http://www.slitaz.org/
http://www.slitaz.org/ru/get/flavors.php