Виртуализация в FreeBSD с помощью Jail


Примечание: статья немного переработана и дополнена, так как в оригинале представляет собой мысли вслух разглядывающего man jail человека.

В этой статье я расскажу о том, как создавал jail в FreeBSD 5. Хотя, в настоящий момент, уже вышла 6-ая версия этой операционной системы, особых изменений механизм создания jail не претерпел. Если вдруг какие-либо отличия будут обнаружены, я с удовольствием дополню/исправлю статью.

Моя предыдущая статья касалась работы jail в FreeBSD 4 и смысл ее был в создании изолированного окружения для разрабатываемого мной приложения. До недавнего времени, для работы системы резервного копирования Bacula, я пользовался выделенной машиной. В процессе обновления парка машин, я заменил несколько старых одной новой, более мощной и захотел избавиться от компьютера, используемого проектом Bacula. Поскольку отдавать мощный компьютер под резервное копирование не хотелось, я решил совместить выполнение нескольких задач, при этом не пересекая их.

Разделяй и властвуй

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

Я недавно приобрел машину Pentium 4 2.4GHz, это довольно мощная система, у нее много ресурсов и довольно высокое время простоя, так как я ее использую в личных целях. Вот на ней я и создам jail, в который помещу Bacula.

Находясь внутри jail невозможно попасть на уровень выше, что очень похоже на поведение chroot, но в тоже самое время, создается впечатление работы с собственной полноценной операционной системой.

Запуск виртуальной системы в jail является хорошим выбором при необходимости предоставить кому-либо ресурсы системы без права хозяйничать в ней. Jail может помочь вам решить проблему безопасного доступа пользователей и повысить КПД использования ресурсов системы.

Документация по Jail

Основным документом, описывающим механизм jail, является man jail. Далее я следовал инструкциям, описанным в разделе "Setting up a Jail Directory Tree". В процессе настройки вам понадобятся полные исходные тексты системы, в моем примере для сборки мира использовался каталог /usr/src/.

Был шаг, в котором я отступил от указаний man jail: я оставил Sendmail (в действительности Postfix) запущенным, указав, какие конкретно IP адреса прослушивать, в файле /usr/local/etc/postfix/main.cf:

inet_interfaces = $myhostname

Таким образом мы обеспечим работу в jail собственного почтового сервера.

Я поместил свою jail в каталог /home/jail/192.168.0.155.bacula. Это значение, которое я присвоил переменной D, согласно инструкции по установке:

D=/home/jail/192.168.0.155.bacula

cd /usr/src

mkdir -p $D

make world DESTDIR=$D

cd etc

make distribution DESTDIR=$D

mount_devfs devfs $D/dev

cd $D

ln -sf dev/null kernel

После того, как вы установили jail, она выглядит точно так же как корневой каталог типичной системы FreeBSD:

[dan@dfc:/home/jail/192.168.0.155.bacula] $ ls

COPYRIGHT etc libexec root usr

bin home mnt sbin var

boot kernel proc sys

dev lib rescue tmp

[dan@dfc:/home/jail/192.168.0.155.bacula] $

Терминология: Host и Jail

Host - это та машина, на которой вы первоначально устнавливаете FreeBSD, именно в этом окружении вы устанавливаете jail. И Bacula, установленная в jail не будет иметь ни какого доступа к корневой системе.

Очень важно понимать различие в окружении корневой машины и окружении jail.

В нашем примере, корневая машина имеет IP адрес 192.168.0.100, а jail имеет адрес 192.168.0.155.

Модифицируем демоны

Большинство демонов будет слушать все, назначенные системе IP адреса. Например, если после установки jail вы попробуете войти на нее по ssh, то вы попадете на корневую машину. Для того, чтобы все работало как надо, необходимо:

Указать ssh корневой машины прослушивать только свой IP адрес

Запустить ssh в jail

В файл конфигурации /etc/rc.conf поместите следущую строку:

syslogd_flags="-ss"

Она укажет демону syslogd корневой машины не открывать UDP порт для приема сообщений с удаленных систем, что позволит запустить syslogd в окружении jail.

Настройка inetd корневой системы заключается в том, чтобы прописать в /etc/rc.conf строку:

inetd_flags="-wW -C 60 -a 192.168.0.100"

Обратите внимание, что первая половина взята из /etc/defaults/rc.conf:

inetd_flags="-wW -C 60" # Optional flags to inetd

Настройка sshd корневой системы потребует прописать в /etc/ssh/sshd_config такой параметр:

ListenAddress 192.168.0.100

Внеся изменения, необходимо перезапустить процесс:

kill -HUP `cat /var/run/sshd.pid`

Для проверки того, что IP адрес jail не прослушивается в настоящий момент корневой системой, воспользуйтесь утилитой telnet:

$ telnet 192.168.0.155 22

Trying 192.168.0.155...

telnet: connect to address 192.168.0.155: Connection refused

telnet: Unable to connect to remote host

Если результат такой, как указано выше, то вы все сделали правильно.

Для запуска sshd в окружении jail необходимо отредактировать файл rc.conf обычным порядком:

sshd_enable="YES"

Для того, я изменил конфигурацию syslogd jail таким образом, чтобы он выводил сообщения не на консоль, а в /var/log/messages, добавив следущие строки:

#*.err;kern.warning;auth.notice;mail.crit /dev/console

*.err;kern.warning;auth.notice;mail.crit /var/log/messages

Конфигурирование jail

Настала пора прочитать часть руководства man, озаглавленную "Configuring the Jail". В ней рассказано, как сконфигурировать несколько параметров, необходимых для функционирования jail. Я внес изменения с корневой машины, без запуска jail. Запустить оболочку в jail можно следующей командой:

jail /data/jail/192.168.11.100 testhostname 192.168.11.100 /bin/sh

Если не появилось сообщение о ошибках, то вы попадете в оболочку jail. Вы можете запустить утилиту /usr/sbin/sysinstall для дальнейшего конфигурирования или вручную отредактировать /etc/rc.conf. Изменить можно такие параметры как:

Создать пустой файл /etc/fstab для того, чтобы избежать сообщений о ошибках при запуске

Отключить портмаппер (rpcbind_enable="NO")

Выполнить newaliases(1) для устранения ошибок sendmail(8)

Отключить конфигурирование сетевых интерфейсов для устранения предупреждений ifconfig(8) (network_interfaces="")

Отредактировать /etc/resolv.conf

Установить пароль пользователя root, отличный от пароля корневой системы

Установить временную зону

Добавить пользователей

Установить необходимые пакеты

Автоматический запуск и останов jail

Я нашел довольно интересный инструментарий для работы с jail - sysutils/jailutils и установил его в корневую систему. Используя этот инструмент, я создал следущий сценарий:

#!/bin/sh

case "$1" in

start)

mount_devfs devfs /usr/jails/192.168.0.155/dev &&

mount -t procfs proc /usr/jails/192.168.0.155/proc &&

/usr/local/sbin/jstart /usr/jails/192.168.0.155 bacula.example.org 192.168.0.155

/bin/sh /etc/rc > /dev/null && echo -n ' jail bacula.example.org'

;;

stop)

/usr/local/sbin/jkill bacula.example.org > /dev/null && echo -n ' jail' &&

umount /usr/jails/192.168.0.155/proc &&

umount /usr/jails/192.168.0.155/dev

;;

*)

echo "Usage: `basename $0 {start|stop}" >&2

;;

esac

exit 0

Это довольно примитивный сценарий, например, он не проверяет, запущена ли в настоящий момент jail или нет.

В заключение, возможно вы захотите выставить эту переменную в /etc/sysctl.conf корневой машины:

security.jail.set_hostname_allowed

В версиях 4.* FreeBSD эта переменная имела несколько другое название.

Обновлено: 12.03.2015