読者です 読者をやめる 読者になる 読者になる

Jailを作成したい

FreeBSD

FreeBSD7.0でJailの作成 - 英語とプログラミング気まぐれ日記で色々ためして(書き散らかして)少しjailの作成方法が分かったので、ここで復習の意味も兼ねて清書する。
※ ほぼezjailを使ってFreeBSD jailを効率よく管理する - mteramotoの日記劣化コピーです。。

jailホスト

$ hostname -a
FreeBSD test-freebsd.dip.jp 7.3-RELEASE-p2 FreeBSD 7.3-RELEASE-p2 #0: Mon Jul 12 19:04:04 UTC 2010     root@i386-builder.daemonology.net:/usr/obj/usr/src    /sys/GENERIC  i386

プロンプトの表記ルール

jailホストの場合は「$ 」
$ command

jail内の場合は「jail$ 」
jail$ command

ezjailのインストール/設定

ezjail - Jail administration framework

ezjailのインストール

portsからインストールする。

$ whereis ezjail
ezjail: /usr/ports/sysutils/ezjail
$ cd /usr/ports/sysutils/ezjail
$ sudo make install
ezjailの設定

設定ファイルの雛形をコピーして利用する。「ezjail_ftphost」だけは明示的に近いホストを指定したほうがよい。他は明示的に指定しなくても、デフォルトのままでよさそう。

$ sudo cp  /usr/local/etc/ezjail.conf.sample /usr/local/etc/ezjail.conf

$ sudo vim /usr/local/etc/ezjail.conf
ezjail_jaildir=/usr/jails
ezjail_ftphost=ftp.jp.freebsd.org

basejailの作成

basejailはezjailで管理するすべてのjailの元になるjail。

$ sudo ezjail-admin install

と言われても、自分の場合は最初はbasejailというものを全くイメージできなかった。。要はjail内のディレクトリにこのbasejailをマウントして、これから作成するどのjail内でもbasejailを参照するという考え方らしい。イメージは以下↓

ezjailでjailを作成する度に、「${ezjail_jaildir}/basejail」が作成したjailの「${ezjail_jaildir}/jailname/basejail」にマウントされる
$ df | grep basejail
/usr/jails/basejail   6204520 3123852 2584308    55%    /usr/jails/jail1/basejail
/usr/jails/basejail   6204520 3123852 2584308    55%    /usr/jails/jail2/basejail

jail内ではマウントされたbasejailへのシムリンクが適切に作成される(以下は一例)
(jailからはbsejailがjailホストでマウントされたディレクトリであることは分からない)
jail$ ls -l / | grep basejail
drwxr-xr-x   9 root  wheel   512 Dec 26 15:47 basejail
lrwxrwxrwx   1 root  wheel    13 Dec 29 19:52 bin -> /basejail/bin
lrwxrwxrwx   1 root  wheel    14 Dec 29 19:52 boot -> /basejail/boot
lrwxrwxrwx   1 root  wheel    13 Dec 29 19:52 lib -> /basejail/lib
lrwxrwxrwx   1 root  wheel    17 Dec 29 19:52 libexec -> /basejail/libexec
lrwxrwxrwx   1 root  wheel    16 Dec 29 19:52 rescue -> /basejail/rescue
lrwxrwxrwx   1 root  wheel    14 Dec 29 19:52 sbin -> /basejail/sbin

jail$ ls -l /usr/ports
lrwxrwxrwx  1 root  wheel  19 Dec 29 19:52 /usr/ports -> /basejail/usr/ports

basejailをupdateする

同じリリース内でセキュリティパッチレベルを上げるために使用するコマンドであるfreebsd-updateを利用する。

$ sudo mkdir /usr/jails/freebsd-update

$ sudo freebsd-update -b /usr/jails/basejail -d /usr/jails/freebsd-update fetch
$ sudo freebsd-update -b /usr/jails/basejail -d /usr/jails/freebsd-update install
Installing updates... done.

jail用のalias IPアドレスの付与

$ sudo ifconfig le0  192.168.11.5 netmask 255.255.255.255 alias192.168.11.5の部分はjailに割りあてるIPアドレス

設定の永続化

$ sudo vim /etc/rc.conf
ifconfig_le0_alias0="inet 192.168.11.5 netmask 255.255.255.255"

jailの作成

$ sudo ezjail-admin create jailname 192.168.11.5
...
Warning: Some services already seem to be listening on all IP, (including 192.168.11.5)
  This may cause some confusion, here they are:
root     sshd       651   4  tcp4   *:22                  *:*
root     syslogd    541   7  udp4   *:514                 *:*

jail作成時に上記のような「Warning」が出ることがある。jailホストでIPアドレスを指定しないでListenしているサービス(上記ではsshdとsyslogd)があると警告してくれる。(jail内で同じサービスを起動しようとしたときにListenできなくなってしまうため)
jailホストではjailホスト自身のIPアドレスを明示的に指定してListenするように設定する:

syslog
$ sudo vim /etc/rc.conf
yslogd_flags="-b 192.168.11.4"
※ jailホストのIPアドレスを指定する。ここでは192.168.11.4。

sshd
$ sudo vim /etc/ssh/sshd_config
ListenAddress 192.168.11.4

jailの起動

jailの起動
$ sudo /usr/local/etc/rc.d/ezjail.sh forcestart jailname

jailの起動確認
$ jls 
   JID  IP Address      Hostname                      Path
     1  192.168.11.5    jailname           /usr/jails/jailname

jailに入れるか確認
$ sudo ezjail-admin console jailname
または以下
$ sudo jexec 1 /bin/sh

jailがboot時に自動起動されるように設定しておく

jailが無事に起動されることを確認できたら、jailホストの起動時にjailも起動されるように設定しておく。

$ sudo vim /etc/rc.conf
ezjail_enable="YES"

jail内でportsを使えるようにしておく

$ sudo ezjail-admin update -P

内部ではportsnapを利用している模様
初回(/usr/jails/basejail/usr/portsが存在しない場合)は以下が実行される
$ sudo portsnap fetch
$ sudo portsnap -p /usr/jails/basejail/usr/ports extract

次回(/usr/jails/basejail/usr/portsが存在する場合)は以下が実行される
$ sudo portsnap fetch
$ sudo portsnap -p /usr/jails/basejail/usr/ports update

jailの作成は完了したが…

以上でjailの作成が完了したが、真っ新な状態なので、当然だが、自分のアカウントも無ければ/etc/resolv.confなど、諸々の設定もされていない。毎回jailを作成する度にこれらの設定を手動で行うのはバカらしい。というかしんどい…。そこでezjailに用意されている「Flavour」という仕組みを利用する。


Flavourで具体的に何が実行されるかというと…
1. ${ezjail_jaildir}/flavours/ ディレクトリ以下のファイル(ディレクトリ含む)が ${ezjail_rootdir} ディレクトリ以下にコピーされる(ディレクトリは再帰的にコピーされる)
ezjail-admin のコードでいうと、以下のようなコマンドが実行されるイメージ:

ezjail_flavours_dir=/usr/jails/flavours/
ezjail_flavour="flavour01" # 「ezjail-admin create -f "flavour01" hostname jailip」とした場合
cd "${ezjail_flavours_dir}/${ezjail_flavour}" && find . | cpio -p -u -v "${ezjail_rootdir}" > /dev/null

flavourは「-f "flavour01 flavour02"」のように複数指定できる。
2. ${ezjail_rootdir}/ezjail.flavour が作成したjailの初回起動時にのみ実行される
初回起動時の実行が完了したら自分で自分を消す処理が挿入されているので、次からは起動されない。

Flavourの設定

雛形をコピーする
$ sudo cp -R /usr/jails/flavours/example /usr/jails/flavours/basic
sudoers

sudoが実行できるようにしておく。

$ sudo vim /usr/jails/flavours/basic/usr/local/etc/sudoers
username        ALL=(ALL) ALL
make.conf

portsがjail内で使えるようにしておく。

$ sudo vim /usr/jails/flavours/basic/etc/make.conf
WRKDIRPREFIX=           /var/tmp
DISTDIR=                /var/tmp/usr/ports/distfiles
WITHOUT_IPV6=           yes

#PACKAGES=               /usr/ports/packages
#INDEXDIR=               /usr/ports
resolve.conf
$ sudo vim /usr/jails/flavours/basic/etc/resolv.conf
nameserver 192.168.11.1
sysctl.conf
$ sudo vim /usr/jails/flavours/basic/etc/sysctl.conf
# $FreeBSD: src/etc/sysctl.conf,v 1.8.36.1 2010/02/10 00:26:20 kensmith Exp $
#
#  This file is read when going to multi-user and its contents piped thru
#  ``sysctl'' to adjust kernel values.  ``man 5 sysctl.conf'' for details.
#

# Uncomment this to prevent users from seeing information about processes that
# are being run under another UID.
#security.bsd.see_other_uids=0

security.jail.allow_raw_sockets=1
rc.conf
# Pretuned by German Engineers

# No network interfaces in jails
network_interfaces=""

# Prevent rpc
rpcbind_enable="NO"

# Prevent loads of jails doing their cron jobs at the same time
cron_flags="$cron_flags -J 15"

# Prevent syslog to open sockets
syslogd_flags="-ss"

# Prevent sendmail to try to connect to localhost
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"

# Bring up sshd, it takes some time and uses some entropy on first startup
sshd_enable="YES"

defaultrouter="192.168.11.1"
timezoneの設定

参考: 「man 8 adjkerntz」、シリコンバレー 24時: FreeBSDにおけるタイムゾーンの手動設定方法

$ sudo touch /usr/jails/flavours/basic/etc/wall_cmos_clock

$ sudo cp /usr/share/zoneinfo/Asia/Tokyo /usr/jails/flavours/basic/etc/localtime
ezjail.flavour
#!/bin/sh
#
# BEFORE: DAEMON
#


# Users
########
#
echo -n 'encrypted_password' | pw useradd -n username -u 1001 -s /bin/sh -m -d /home/username -G wheel -c 'comment' -H 0
mkdir /home/username/.ssh && echo -n 'public_key' > /home/username/.ssh/authorized_keys && chmod 400 /home/username/.ssh/authorized_keys
chown -R username /home/username/

書きかけ。
sudoとか使えるようにするためにパッケージまたはportsのインストールも入れておきたい。
あとtinderbox調べる。