понеділок, 10 лютого 2014 р.

LXC 1.0: GUI в контейнере

Статья 9 из 10, в которой речь пойдёт о запуске графических приложений в изолированных контейнерах, что улучшает безопасность без накладных расходов.

Заметки.

Данная статья подразумевает использование непривилегированных контейнеров. Это требование не является чем-то сложным, но очень важно́ для приложений с графическим интерфейсом.

Предположим, что мы хотим запустить Google Chrome с плагинами Google Talk (Hangout) и Adobe Flash в контейнере, чтобы не рисковать хостовой машиной.

Причины запуска приложений в изолированных контейнерах:

  • Есть бинарник, но нет его исходника.
  • Внешние не-Ubuntu репозитория, которые могут после добавления пропихнуть в систему всё что пожелают. Только грамотный apt pining может уменьшить риск.
  • Софт устанавливает своё задание для Cron, которое добавляет удалённые вами репозитория.
  • Софт использует setuid бинарник для создания своей песочницы.
  • Желание отделить рабочую среду от программ, страдающих проблемами безопасности, такого как Adobe Flash, который ещё популярен в web.

Ниже будут описаны шаги, которые улучшают безопасность хостовой системы, НО до идеала далеко, так как, чтобы GUI приложения работали корректно, они должны получить доступ к:

  • pulseaudio: возможна запись звуков.
  • X11: возможен перехват клавиш или создание скриншотов экрана.
  • dri/snd устройства: с помощью их умелый злоумышленник может придумать что-нибудь зловредное.

Запуск Google Chrome в контейнере.

Идея проста. Берём для контейнера операционную систему Ubuntu 12.04 i386, которая стабильна и хорошо поддерживается многими.

lxc-create -t download -n precise-gui -- -d ubuntu -r precise -a i386

Не забываем, что речь идёт не о системных контейнерах и поэтому в ~/.local/share/lxc/precise-gui/config внесём строки, заменив USERNAME на свой аккаунт.

lxc.mount.entry = /dev/dri dev/dri none bind,optional,create=dir
lxc.mount.entry = /dev/snd dev/snd none bind,optional,create=dir
lxc.mount.entry = /tmp/.X11-unix tmp/.X11-unix none bind,optional,create=dir
lxc.mount.entry = /dev/video0 dev/video0 none bind,optional,create=file
lxc.hook.pre-start = /home/USERNAME/.local/share/lxc/precise-gui/setup-pulse.sh

В конфиге у вас будет что-то подобное

lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536

Нужно заменить на строки, подразумевая что ваш UID=1000 и GID=1000. Команда id подскажет, если забыли.

lxc.id_map = u 0 100000 1000
lxc.id_map = g 0 100000 1000
lxc.id_map = u 1000 1000 1
lxc.id_map = g 1000 1000 1
lxc.id_map = u 1001 101001 64535
lxc.id_map = g 1001 101001 64535

Эти отображения означают, что контейнер будет обладать UID/GID, начиная с 0 до 65535. Эти UID/GID сопоставляются с хостовыми - 100000 до 165535, за исключением UID/GID 1000. Этот трюк позволит пользователю в контейнере получить доступ к X, pulseaudio и устройствам DRI/snd, как пользователь в хосте, что облегчает задачу.

Создаём исполняемый скрипт ~/.local/share/lxc/precise-gui/setup-pulse.sh

#!/bin/sh
PULSE_PATH=$LXC_ROOTFS_PATH/home/ubuntu/.pulse_socket
if [ ! -e "$PULSE_PATH" ] || [ -z "$(lsof -n $PULSE_PATH 2>&1)" ]; then
    pactl load-module module-native-protocol-unix auth-anonymous=1 \
        socket=$PULSE_PATH
fi

Если скрипт будет не исполняемым, то LXC проигнорирует его. Данный скрипт связывает pulseaudio в хостовой системе с /home/ubuntu/.pulse_socket в контейнере.

Исправим права доступа в домашней директории пользователя внутри контейнера, подразумевая что ваш UID=1000 и GID=1000.

sudo chown -R 1000:1000 ~/.local/share/lxc/precise-gui/rootfs/home/ubuntu

Контейнер готов, пора его запускать и ставить нужное.

lxc-start -n precise-gui -d
lxc-attach -n precise-gui -- umount /tmp/.X11-unix
lxc-attach -n precise-gui -- apt-get update
lxc-attach -n precise-gui -- apt-get dist-upgrade -y
lxc-attach -n precise-gui -- apt-get install wget ubuntu-artwork ca-certificates -y
lxc-attach -n precise-gui -- wget https://dl.google.com/linux/direct/google-chrome-stable_current_i386.deb -O /tmp/chrome.deb
lxc-attach -n precise-gui -- wget https://dl.google.com/linux/direct/google-talkplugin_current_i386.deb -O /tmp/talk.deb
lxc-attach -n precise-gui -- dpkg -i /tmp/chrome.deb /tmp/talk.deb
lxc-attach -n precise-gui -- apt-get -f install -y
lxc-stop -n precise-gui

На данном этапе, всё что нужно у нас есть, но, чтобы в будущем работа с контейнером была проще, можно создать исполняемый скрипт start-chrome и поместить его рядом с setup-pulse.sh.

#!/bin/sh
CONTAINER=precise-gui
CMD_LINE="google-chrome --disable-setuid-sandbox $*"
STARTED=false
if ! lxc-wait -n $CONTAINER -s RUNNING -t 0; then
    lxc-start -n $CONTAINER -d
    lxc-wait -n $CONTAINER -s RUNNING
    STARTED=true
fi
PULSE_SOCKET=/home/ubuntu/.pulse_socket
lxc-attach --clear-env -n $CONTAINER -- sudo -u ubuntu -i \
    env DISPLAY=$DISPLAY PULSE_SERVER=$PULSE_SOCKET $CMD_LINE
if [ "$STARTED" = "true" ]; then
    lxc-stop -n $CONTAINER -t 10
fi

Скрипт start-chrome проверяет - работает ли контейнер? Если нет, то запускает его. Запускает google-chrome в правильном окружении, отключая его собственную песочницу.

Последний, полирующий штрих - создаём ярлык запуска Google Chrome в контейнере. Замените USERNAME на свой аккаунт.

[Desktop Entry]
Version=1.0
Name=Google Chrome
Comment=Access the Internet
Exec=/home/USERNAME/.local/share/lxc/precise-gui/start-chrome %U
Icon=/home/USERNAME/.local/share/lxc/precise-gui/rootfs/opt/google/chrome/product_logo_256.png
Type=Application
Categories=Network;WebBrowser;

Google Chrome в LXC

У вас будет ярлык для вашей среды, по щелчку которого запускается Хром в контейнере. Можно добавить функционала в виде симлинков к папке Downloads (Закачки) или заюзать bind-mount, чтобы быстро получать доступ к скачанным файлам.

Созданный precise-gui под Google Chrome можно использовать и для запуска других программ, для примера Skype. Или создать под другие программы - другие контейнеры, подобные precise-gui.

Предыдущая статья LXC 1.0: Скрипты и API.
Следующая статья LXC 1.0: Решение проблем и отладка.

Дополнительные материалы:
Серия статей LXC 1.0. от Стефана Грабера.
Adobe Flash перестанет работать в Chromium с апреля 2014.

Немає коментарів:

Дописати коментар

HyperComments for Blogger

comments powered by HyperComments