Jail - механизм виртуализации в системе FreeBSD

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

Содержание:

Введение

И так немного истории. Jail является потомком chroot и имеет поддержку на уровне ядра и мы можем ограничивать некоторые ресурсы потребляемые клеткой, а так же привязываем её к определенному IP адресу с определенным именем хоста и определенным местом корневого каталога. Получаем изолированные процессы - клетки, в которых вы можете делать, что хотите и это не повлияет на основную систему.

Создание клетки

Необходимо провести несколько манипуляций:

  1. bsd# setenv D /usr/home/jails/test.local
  2. bsd# mkdir -p $D
  3. bsd# cd /usr/src
  4. bsd# make buildworld
  5. bsd# make installworld DESTDIR=$D
  6. bsd# make distribution DESTDIR=$D
  7. bsd# mount -t devfs devfs $D/dev
1. Укажем переменную имени к окружению.
2. Создадим домашнюю директорию по переменной.
5. Заполним каталог поддерева необходимыми двоичными файлами, библиотеками, справочниками и так далее.
6. Установим все необходимые файлы из /usr/src/etc/ и /etc в каталог клетки $D/etc/.

Конфигурация rc.conf

# Значения для всех клеток
jail_enable="YES"     # Включаем jail
jail_interface="em0"    # Сетевой интерфейс
jail_devfs_enable="YES"  # Монтируем devfs в клетках
jail_procfs_enable="YES" # Монтируем procfs в клетках
jail_set_hostname_allow="YES"
 
# Список клеток
jail_list="test"     # Имя клеток через пробел для списка клеток
 
# Значения для созданной клетки "test"
jail_test_rootdir="/usr/home/jails/test.local"     # Рутовая директория jail
jail_test_hostname="test.local"     # Имя хоста клетки
jail_test_ip="192.168.0.4"     # IP адрес хоста клетки
#jail_test_interface="em0"     # Сетевой интерфейс клетки (если нужен)
#jail_test_devfs_enable="YES"     # Монтируем devfs в клетке
#jail_test_procfs_enable="YES" # Монтируем procfs в клетке
 
jail_test_exec_start="/bin/sh /etc/rc"
jail_test_exec_stop="/bin/sh /etc/rc.shutdown"
jail_test_flags="-l -U root"      # Необходимые флаги для клетки

Конфигурация сети

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

bsd# cat /etc/rc.conf |grep if
ifconfig_em0="inet 192.168.0.2  netmask 255.255.255.0"
# Алиас для первой клетки
ifconfig_em0_alias0="inet 192.168.0.4 netmask 255.255.255.255"

Запуск

Для запуска всех клеток используйте:

bsd# /etc/rc.d/jail start
bsd# /etc/rc.d/jail stop


Для запуска необходимой клетки используйте ее имя:
bsd# /etc/rc.d/jail start test
bsd# /etc/rc.d/jail stop test
Выведем список работающих клеток:

bsd# jls
   JID  IP Address      Hostname                      Path
     1  192.168.0.4     test.local               /usr/home/jails/test.local
     2  192.168.0.5     jabber.local             /usr/home/jails/jabber.local
Зайдем в первую клетку:

bsd# jexec 1 tcsh
test#

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

Дополнительная настройка

Окружение

FSTAB
Создадим в клетке пустой файл /etc/fstab чтобы при ее запуске не появлялось сообщение об отсутствующем файле fstab.

bsd# touch /home/jails/test.local/etc/fstab

PORT MAPPER
Выключите в клетке port mapper.

bsd# cat /home/jails/test.local/etc/rc.conf |grep rpcbind
rpcbind_enable="NO"

RESOLV
Настроим resolv.conf так, чтобы разрешение имен в клетке работало правильно. Создадим в клетке файл с нужным DNS сервером или скопируем с основной машины в клетку.

bsd# cat /home/jails/test.local/etc/resolv.conf
nameserver 192.168.0.1

SENDMAIL
Запустим в клетке newaliases чтобы при запуске не появлялось сообщение от sendmail.

test# /etc/mail/ && newaliases

IFCONFIG
Отключим сетевой конфигурационный интерфейс чтобы при запуске не появлялось сообщение от ifconfig.

bsd# cat /home/jails/test.local/etc/rc.conf |grep network
network_interfaces = ""

Пароли
Обязательно измените пароль root в клетке (сделайте отличным от основной машины).
Создадим нового пользователя. Для этого есть штатная утилита jexec с помощью нее мы добавим нового пользователя состоящего в группе wheel [цифра это JID клетки]:

bsd# jexec 1 adduser
Username: alex
Full name: Alex Ign
Uid (Leave empty for default):
Login group [alex]:
Login group is alex. Invite alex into other groups? []: wheel
Login class [default]:
Shell (sh csh tcsh nologin) [sh]: csh
Home directory [/home/alex]:
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Enter password:
Enter password again:
Lock out the account after creation? [no]:
Username   : alex
Password   : *****
Full Name  : Alex Ign
Uid        : 1003
Class      :
Groups     : alex wheel
Home       : /home/alex
Home Mode  :
Shell      : /bin/csh
Locked     : no
OK? (yes/no): yes
adduser: INFO: Successfully added (alex) to the user database.
Add another user? (yes/no): no
Goodbye!

SSH
Для работы с клеткой посредством ssh необходимо настроить демон sshd.
Для этого на основной машине в /etc/ssh/sshd_config укажем нужный для прослушивания IP.

bsd# cat /etc/ssh/sshd_config | grep ListenAddress
#ListenAddress 0.0.0.0
ListenAddress 192.168.0.2
#ListenAddress ::

Перезапустим демон и проверим его работу.
bsd# /etc/rc.d/sshd restart
bsd# sockstat -l |grep sshd
root     sshd       1216  3  tcp4   192.168.0.4:22        *:*
root     sshd       978   3  tcp4   *:22                  *:*

Добавим в конфигурационный файл rc.conf клетки.
bsd# cat /home/jails/test.local/etc/rc.conf |grep sshd
sshd_enable="YES"

TIMEZONE
Установите нужную временую зону в клетке.

Экспорт портов

Экспортируем существующие порты в клетку. Вы можете также скопировать их в нужную директорию или создать симлинк.

bsd# mkdir /home/jails/test.local/usr/ports
bsd# mount_nullfs /usr/ports /home/jails/test.local/usr/ports
bsd# cat /etc/fstab |grep jail
/usr/ports              /home/jails/test.local/usr/ports nullfs rw 0 0

Ограничения

Вы можете настроить некоторые переменные sysctl в основной системе для настройки работы клеток.
  1. security.jail.set_hostname_allowed: 1 # Возможность менять hostname внутри клетки.
  2. security.jail.socket_unixiproute_only: 1 # Создавать сокет в клетке можно только для PF_LOCAL, PF_INET или PF_ROUT иначе, возвращается ошибка
  3. security.jail.sysvipc_allowed: 0 # Возможность использовать System V IPC
  4. security.jail.enforce_statfs: 2 # Возможность видеть клетке все смонтированные устройства
  5. security.jail.allow_raw_sockets: 0 # Возможность использования низкоуровневых сокетов (ping и тп)
  6. security.jail.chflags_allowed: 0 # Возможность менять системные флаги файлов
  7. security.jail.jailed: 0 # Видеть список запущенных клеток
  8. security.jail.getfsstatroot_only: 1 # - клетка получает только информацию о ФС, например, возвращается df, для корневой файловой системы.
Для некоторого ограничения ресурсов клетки используйте совместно с ограничениями в /etc/login.conf ;)

Автоматизируем птицеферму

Написать о самописном скрипте или о порте который может управлять клетками?

Заключение

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


Jail problems:
Q1) # adjkerntz[44739]: sysctl(set: "machdep.adjkerntz"): Operation not permitted
A1a)You can disable adjkerntz in /etc/crontab:
#1,31   0-5     *       *       *       root    adjkerntz -a
 
A1b) There are various things in cron and periodic that don't make sense to run in 
a jail, because a jail cannot modify kernel time and read various /dev 
devices. I have this line commented out in my jails and nothing breaks, just 
less annoying emails.

You might find this list useful as well:
# cat /data/jails/tpl/RELENG_7/etc/periodic.conf
daily_clean_rwho_enable="NO"
daily_accounting_enable="NO"
daily_status_disks_enable="NO"
daily_status_rwho_enable="NO"
daily_status_security_chksetuid_enable="NO"
daily_status_security_chkmounts_enable="NO"
daily_status_security_ipfwdenied_enable="NO"
daily_status_security_ipfdenied_enable="NO"
daily_status_security_pfdenied_enable="NO"
daily_status_security_ipf6denied_enable="NO"
daily_status_security_kernelmsg_enable="NO"
monthly_accounting_enable="NO" 


Q2) /var/spool/clientmqueue
When submitting mail by using sendmail as a mail submission program,
sendmail copies all messages to /var/spool/clientmqueue first. sendmail is
a setgid smmsp program and thus gives the any user the permission to do so
(/var/spool/clientmqueue belongs to user and group smmsp).

Later, another sendmail process, the sendmail localhost-only (FreeBSD
default config) mail transfer agent (MTA) copies the messages from
/var/spool/clientmqueue to /var/spool/mqueue and sends them to their
destination.

When files accumulate in /var/spool/clientmqueue, you probably don't run
the sendmail localhost MTA, and thus the mails don't get send.

http://forums.freebsd.org/showthread.php?t=22482


http://www.ignix.ru/book/freebsd/setup/jail