четверг, 20 декабря 2007 г.

Монтирование разделов при запуске Jail

В rc.conf есть два интересных параметра, позволяющих при запуске jail монтировать необходимые разделы:
jail_<jail_name>_mount_enable="YES"
jail_<jail_name>_fstab="/path/to/fstab/file"

jail_<jail_name>_mount_enable разрешает монтировать разделы по списку в файле, указанного в jail_<jail_name>_fstab.
Формат файла идентичен формату /etc/fstab. Все пути к монтируемым точкам внутри jail задаются относительно корня основной системы.

Монтирование можно применить для усиления защиты jail при их взломе. Например, в случае если система в jail будет скомпрометирована, то злоумышленник не сможет подменить системные утилиты т.к. папки /usr/bin или /usr/lib примонтированы только чтения и не могут быть изменены.

Для этого нужно:
1. Создать папки:
▪ для jail-машин /opt/jail
▪ папку для конфигурационных файлов /opt/jail/conf
▪ папку Base для базового jail /opt/jail/Base

2. В папке Base создать базовый jail и настроить его (Например установить дополнительные и настроить пакеты perl5/sudo/etc, прописать DNS сервер).

3. Потом воспользоваться приведенным ниже скриптом new-jail.conf, предварительно изменив переменные J и JAIL_EXAMPLE (если у вас другое размещение jail).
Запуск скрипта от имени пользователя root:
# JAIL=New-jail-name ./new-jail.sh
Скрипт создает точки монтирования папок и копирует etc, var и usr/local из базового скрипта в новый jail. Потом в /opt/jail/conf создается файл в формате fstab и производится попытка записи параметров jail в /etc/rc.conf. Если /etc/rc.conf недоступен для записи, скрипт выводит список параметров.

Скрипт new-jail.conf:

#!/bin/sh
J="/opt/jail"
JAIL=${JAIL:?'$JAIL is not set'}
JAIL_LOWER="`echo $JAIL | /usr/bin/tr A-Z a-z`"
JAILDIR="$J/$JAIL"
JAIL_EXAMPLE="$J/Base"
DIR_EMPTY="dev proc media cdrom mnt boot rescue root usr usr/home usr/src usr/ports"
DIR_MOUNT="bin lib libexec sbin usr/bin usr/include usr/lib usr/libdata usr/libexec usr/sbin usr/share"
#Jail directory
echo -n "Checking $JAILDIR directory... "
if [ ! -e $JAILDIR ];
then {
/bin/mkdir -p $JAILDIR;
echo "created.";
}
else echo "already exists.";
fi;
# Empty directories
echo -n "Creating empty directories: $DIR_EMPTY... "
for dir in $DIR_EMPTY; do /bin/mkdir -p $JAILDIR/$dir; done;
echo "ok.";
# Mount points
echo -n "Creating mount points: $DIR_MOUNT... "
/usr/bin/touch $J/conf/$JAIL.fstab
echo "# Generated on `/bin/date`" >> $J/conf/$JAIL.fstab
for dir in $DIR_MOUNT;
do {
/bin/mkdir -p $JAILDIR/$dir;
printf "$JAIL_EXAMPLE/$dir\t$JAILDIR/$dir\tnullfs\tro\t0\t0\n" >> $J/conf/$JAIL.fstab;
} done;
echo "ok.";
echo "The fstab file created: $J/conf/$JAIL.fstab"
# Symbolic links
/bin/ln -s usr/home $JAILDIR/home
# Temporary directory
echo -n "Creating tmp... "
/bin/mkdir $JAILDIR/tmp
/bin/chmod ugo=rwx $JAILDIR/tmp
echo "ok.";
# Directories from $JAIL_EXAMPLE
echo -n "Copying files... "
/bin/cp -pR $JAIL_EXAMPLE/etc $JAILDIR/
/bin/cp -pR $JAIL_EXAMPLE/var $JAILDIR/
/bin/cp -pR $JAIL_EXAMPLE/usr/local $JAILDIR/usr/

/bin/rm -f $JAILDIR/var/{tmp,run}/*
for i in `/usr/bin/find -E $JAILDIR/var/log -type f \
-and -regex ".*\.[0-9]+(\..*|$)" -print`;
do /bin/rm -f $i; done;
for i in `/usr/bin/find $JAILDIR/var/log -type f -print`;
do /usr/bin/touch /dev/null > $i; done;

echo "ok.";
echo
echo The jail \'$JAIL\' created.
echo
if [ -w /etc/rc.conf ];
then {
/usr/bin/sed -Ei .bck '/^[\s]*jail_list=/s#jail_list="([^"]*)"#jail_list="\1 '${JAIL_LOWER}'"#g' /etc/rc.conf
echo >> /etc/rc.conf
echo \#\# ${JAIL} >> /etc/rc.conf
echo jail_${JAIL_LOWER}_rootdir=\"$J/${JAIL}\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_hostname=\"${JAIL}.local\" \
>> /etc/rc.conf
echo \# Don\'t forget add ip-address in \'.local\' domain zone \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_ip=\"127.0.0.xxx\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_interface=\"lo0\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_devfs_enable=\"YES\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_exec_start=\"/bin/sh /etc/rc\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_exec_stop=\"/bin/sh /etc/rc.shutdown\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_mount_enable=\"YES\" \
>> /etc/rc.conf
echo jail_${JAIL_LOWER}_fstab=\"$J/conf/${JAIL}.fstab\" \
>> /etc/rc.conf
}
else echo "Put in /etc/rc.conf:";
fi;
echo jail_${JAIL_LOWER}_rootdir=\"$J/${JAIL}\"
echo jail_${JAIL_LOWER}_hostname=\"${JAIL}.local\"
echo \# Don\'t forget add ip-address of jail in \'.local\' domain zone
echo jail_${JAIL_LOWER}_ip=\"127.0.0.xxx\"
echo jail_${JAIL_LOWER}_interface=\"lo0\"
echo jail_${JAIL_LOWER}_devfs_enable=\"YES\"
echo jail_${JAIL_LOWER}_exec_start=\"/bin/sh /etc/rc\"
echo jail_${JAIL_LOWER}_exec_stop=\"/bin/sh /etc/rc.shutdown\"
echo jail_${JAIL_LOWER}_mount_enable=\"YES\"
echo jail_${JAIL_LOWER}_fstab=\"$J/conf/${JAIL}.fstab\"

3 комментария:

Alexey комментирует...

я бы предложил использовать для создания скрипты из портов, например sysutils/jailctl

mr.tacitus комментирует...

sysutils/jailctl:
FUTURE PLANS:
- Support for file-based and remote filesystems for jails
- Support for mounting host /usr, /bin, etc. in jails
- etc...

Поэтому я написал скрипт который, облегчает создание новых jail и fstab-файлов для них.

Alexey комментирует...

дисковое пространство сейчас де самый критичный параметр (это про монтирование из одного места).
зато jailctl нормально делает backup/restore, а также обновляет jail.
иметь один скрипт/тулзу с единой идеологией удобнуу чем набор разношерстных скриптов