FreeBSD‎ > ‎

jailで仮想環境を構築する

※このページの内容はコミックマーケット C80で販売する、「Block Device Magazine VOL.4」に含まれています。


jail概要

jail の仮想環境

jail の仮想環境はOS レベルの仮想環境です.VMWare 等,ホストOS とゲストOS が完全に分離されたタイプの仮想環境と比較すると,FreeBSD 以外のOS が使えない,ゲスト側の一部機能に制限がある等,機能に見劣りする点があります.しかし,軽量に動作し,構築が簡単という大きなメリットがあります.

jail では,ゲスト環境はホスト環境のプロセスの一部として扱われます.1 つのOS 上で複数の環境が動いている様に見えます.ゲスト環境上でhttpd が動作している状態をホスト環境上のpsコマンドで見てみます.

[root@server ~]# ps ax -o user,pid,jid,command
USER PID JID COMMAND ~略~
root 1971 3 /usr/local/sbin/httpd
www 11528 3 /usr/local/sbin/httpd
www 11529 3 /usr/local/sbin/httpd
www 11530 3 /usr/local/sbin/httpd
www 93785 3 /usr/local/sbin/httpd
www 93786 3 /usr/local/sbin/httpd
www 93787 3 /usr/local/sbin/httpd
www 93788 3 /usr/local/sbin/httpd
www 93789 3 /usr/local/sbin/httpd
www 93812 3 /usr/local/sbin/httpd
root 19511 0 grep httpd

ご覧の通り,ホスト環境のプロセスと区別なくリストされます.ただ,JID 欄にjail を区別するID が表示されます.また,ディスクマウントの結果も同様に,ホスト環境でdf を実行するとゲスト環境のマウント状態が出力されます.もちろん,ゲスト側から見るとホスト側の状態は全く見えません.
上記の通り,jail は,ホスト環境とハードウェアリソース,OS リソースを共有しつつ,ファイルシステム,プロセスを完全に分離している為,限られたリソースでセキュアな環境構築に向いていると言えます.

jail の特徴

ディレクトリツリー

jail 環境ではプロセスは指定されたルートディレクトリから外に出ることは出来ません.尚,似た機構にchroot がありますが,こちらはアクセス出来るファイルシステムを限定するのみであり,ユーザやネットワークはホスト環境と共有します.
プログラムのロジックによっては,プロセスはchroot されたディレクトリの外にアクセスすることが出来てしまいます.

ホスト名

jail では環境毎にホスト名を持つことが出来ます.
Web サーバやメールサーバではホスト名に依存する設定があり,ホスト側の環境に左右されることなくこれらのサービスを構築することが出来ます.

IP アドレス

jail では構築時にIP アドレスが割り当てられます.IP アドレスの割当は必須ではありませんが,割り当てられたIP アドレスはjail 環境から変えることは出来ません.

コマンド

ファイルシステムが分離される為,もちろんコマンドパスはjail 毎に全く異なります.
ports システムを使用した環境ではユーザ用コマンドは/usr/local/bin に配置されますが,コマンドパスを変えることが出来ます.

root ユーザ

Unix ではroot ユーザは特権ユーザとして全ての権限を持っています.
jail のゲスト環境でもroot ユーザは存在しますが,ホスト環境を破壊することが無いように,root ユーザであっても,一部の機能に制限事項があります.

jail の構築

jail 構築の基本

ベースシステムの構築

まずは,ベースシステムの構築とデバイスノードのマウントを行います.また,jail 環境用にネットワークインターフェースを作成します.この時,ネットワークインターフェースは物理インターフェースのエイリアスとして作成します.

●ソースからベースシステムを構築する
[root@server /opt/jails]# export JAIL_D=/opt/jails/C78
[root@server /opt/jails]# mkdir -p $JAIL_D
[root@server /opt/jails]# cd /usr/src/
[root@server /usr/src]# make -j 5 buildworld
[root@server /usr/src]# make installworld DESTDIR=$JAIL_D
[root@server /usr/src]# make distribution DESTDIR=$JAIL_D
● devfs をマウントする
[root@server /usr/src]# mount -t devfs devfs $JAIL_D/dev
●ネットワークインターフェースのエイリアスを作成する
[root@server /usr/src]# ifconfig re0 alias 192.168.1.247

起動

次に,jail を起動します.第1 引数から順に,jail のベースシステムのパス,ホスト名,IP アドレス,コマンドです.この時,コマンドにrc スクリプトの実行を指定することで,通常FreeBSDをブートした時と同様に,rc.conf による設定やデーモンの起動が行われます.

[root@server /usr/src]# jail /opt/jails/C78 C78 192.168.1.247 /bin/sh /etc/rc
Loading configuration files.
/etc/rc: WARNING: $hostname is not set -- see rc.conf(5).
Creating and/or trimming log files:.
ln: /dev/log: Operation not permitted
Starting syslogd.
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
a.out ldconfig path: /usr/lib/aout /usr/lib/compat/aout
Clearing /tmp (X related).
Starting local daemons:.
Updating motd.
Starting cron.
Local package initialization:.
Sun Jul 25 02:12:20 UTC 2010
[root@server /usr/src]#

ログイン

いよいよjail 環境にログインします.jls コマンドを使用することで,起動しているjail の一覧を確認することが出来ます.
[root@server /usr/src]# jls
JID IP Address Hostname Path
22 192.168.1.247 C78 /opt/jails/C78
3 192.168.1.248 Balthasar /opt/jails/Balthasar
2 192.168.1.247 Casper /opt/jails/Casper
1 192.168.1.249 Melchior /opt/jails/Melchior
[root@server /usr/src]#

JID を確認しjexec コマンドを用いてログインします.FreeBSD ではtcsh がベースシステムに
含まれている為,これを使います.
[root@server /usr/src]# jexec 22 tcsh
C78# which tcsh
/bin/tcsh
C78#
C78#
C78# ps auxwww
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
root 37907 0.0 0.1 3160 1204 ?? SsJ 2:23AM 0:00.00 /usr/sbin/syslogd -s
root 37970 0.0 0.2 5812 3364 ?? SsJ 2:23AM 0:00.00 sendmail: accepting connections smmsp 37974 0.0 0.2 5812 3312 ?? IsJ 2:23AM 0:00.00 sendmail: Queue runner@00:30:00 root 37980 0.0 0.1 3188 1256 ?? SsJ 2:23AM 0:00.00 /usr/sbin/cron -s
root 38054 0.0 0.1 3452 2176 p1 SJ 2:26AM 0:00.01 tcsh
root 38081 0.0 0.1 3220 1036 p1 R+J 2:28AM 0:00.00 ps auxwww
C78# exit
exit
[root@server /usr/src]#

jail 環境から抜け出すには,exit コマンドを用います.

停止

jail を停止するにはkillall コマンドにオプション-j を使用し,jid を指定します.
[root@server /usr/src]# jls
JID IP Address Hostname Path
22 192.168.1.247 C78 /opt/jails/C78
3 192.168.1.248 Balthasar /opt/jails/Balthasar
2 192.168.1.247 Casper /opt/jails/Casper
1 192.168.1.249 Melchior /opt/jails/Melchior
[root@server /usr/src]# killall -j 22
[root@server /usr/src]# jls
JID IP Address Hostname Path
3 192.168.1.248 Balthasar /opt/jails/Balthasar
2 192.168.1.247 Casper /opt/jails/Casper
1 192.168.1.249 Melchior /opt/jails/Melchior
[root@server /usr/src]#

ezjail を用いた構築

さて,これまで紹介してきた基本的な構築方法は,ホスト環境のベースシステムをコピーして構築を行いました./ディレクトリを全てコピーする為,環境によってほぼ変更されることのない/usr/ports や/usr/share まで,jail を作成する毎にコピーされてしまいます.大量のjail 環境を構築する場合に,無駄にディスクスペースを使用してしまいます.そこで,ports に登録されているezjail では,nullfs を使用し,なるべくコピーするファイルを少なくし,かつテンプレート機構を使用することで,より簡単に無駄のないjail 環境が構築できます.

ezjail の初期設定

まずは,ports からezjail をインストールします.ezjail はsysutils/ezjail にあります.ports か
らのインストールは割愛します.また,ネットワークインターフェースのエイリアス作成も事前に
行います.
まずbasejail ベースシステムをインストールするディレクトリを設定ファイルに記述します.
#/usr/local/etc/ezjail.conf
ezjail_jaildir=/opt/jails-test
次に,ベースシステムをインストールします.
[root@server ~]# ezjail-admin install
上のezjail_jaildir で指定したディレクトリに,jail のベース環境が構築されます.
[root@server /opt/jails-test]# ll
total 6
drwxr-xr-x 9 root wheel 512 Jul 25 12:41 basejail/
drwxr-xr-x 3 root wheel 512 Jul 25 12:41 flavours/
drwxr-xr-x 12 root wheel 512 Jul 25 12:41 newjail/
[root@server /opt/jails-test]#
ここで作成されたディレクトリはそれぞれ役割を持っています.
  • basejail
FreeBSD のベースシステムがインストールされています./bin や/lib 等,普遍的なファイル群が保存されています.約150M ほどあるディレクトリですが,このディレクトリはnullfs で全てのjail でマウントされる為,jail 毎にこの容量が必要なわけではありません.全jailで共通の為,ベースシステムをアップデートする際は1 回で済みます.
  • flavours
jail 作成時のテンプレートです.create する時の-f オプションで適用できるflavoursを指定することが出来ます(favours/<-f オプションで指定するディレクトリ名>).このディレクトリのファイルがコピーされてから,jail が作成されます.また,flavours/<flavours ディレクトリ>/ezjail.flavour にスクリプトを記載することで事前に実行されます.
  • newjail
jail 作成時にコピーされるディレクトリです.jail 毎に作成されるファイル群がインストールされています.

jail の作成

jail を作成します.
# -f オプションでflavours を指定します
# ホスト名をC78 とします
# IP アドレスをエイリアスで作成したIP アドレスにします
[root@server ~]# ezjail-admin create -f default C78 192.168.1.247

各種設定

jail 環境を使用する上で必要な設定を行います.
●リゾルバの設定ファイル
[root@server ~]# cp -ip /etc/resolv.conf /opt/jails-test/C78/etc/
●タイムゾーンの設定(newjail ディレクトリにあらかじめ作成しておくと簡単)
[root@server ~]# ln -s ../usr/share/zoneinfo/Asia/Tokyo \
/opt/jails-test/C78/etc/localtime
● adjkerntz の停止
[root@server ~]# vi /opt/jails-test/C78/etc/crontab
下記行をコメントアウト
1,31 0-5 * * * root adjkerntz -a

ログイン

jail へのログインは,jexec をjid 指定で行っていましたが,ezjail-adminコマンドを使用するとjail 名を使用することが出来ます.

[root@server ~]# ezjail-admin list
STA JID IP Hostname Root Directory
--- ----- --------------- ---------------------------- -------------------------
DR 1 192.168.1.249 Melchior /opt/jails/Melchior
DR 9 192.168.1.247 C78 /opt/jails-test/C78
DR 2 192.168.1.248 Balthasar /opt/jails/Balthasar
[root@server ~]#
[root@server ~]# ezjail-admin console C78
C78# uname -n
C78
C78# ll
total 14
drwxr-xr-x 5 root wheel 512 Aug 8 01:54 .cpan
-rw-r--r-- 2 root wheel 794 Aug 8 00:43 .cshrc
-rw------- 1 root wheel 1528 Aug 8 01:53 .history
-rw-r--r-- 1 root wheel 151 Aug 8 00:43 .k5login
-rw-r--r-- 1 root wheel 299 Aug 8 00:43 .login
-rw-r--r-- 2 root wheel 261 Aug 8 00:43 .profile
drwx------ 2 root wheel 512 Aug 8 00:51 .ssh
C78#

Tips


flavour を用いると,jail 作成時にパッケージをあらかじめインストールすることが出来ます.これはflavours/default/ezjail.flavour スクリプトに定義されており,flavours/default/pkgディレクトリを作成し,中にパッケージを保存すると自動的にインストールされます.

例として、bash パッケージを自動インストールします.

● ports からパッケージを作成
[root@server /usr/ports/shells/bash]# make PACKAGES=/opt/jails-test/flavours/default/pkg/ package-recursive
[root@server /opt/jails-test/flavours/default/pkg]# ll
total 8
drwxr-xr-x 2 root wheel 512 Aug 8 02:35 All/
drwxr-xr-x 2 root wheel 512 Aug 8 02:35 Latest/
drwxr-xr-x 2 root wheel 512 Aug 8 02:35 converters/
drwxr-xr-x 2 root wheel 512 Aug 8 02:35 devel/
[root@server /opt/jails-test/flavours/default/pkg]#
●パッケージをpkg 直下へ移動し,不要なディレクトリを削除
[root@server /opt/jails-test/flavours/default/pkg]# mv All/* . && for f in ./*; do [ -d $f ] && rm -rf $f; done

ezjailでjailを構築した後に,jail へログインし,パッケージ情報を確認します.

C78# bash
[root@C78 ~]#
[root@C78 ~]# pkg_info
bash-4.0.33 The GNU Project's Bourne Again SHell
bison-2.4.1,1 A parser generator from FSF, (mostly) compatible with Yacc
gettext-0.17_1 GNU gettext package
libiconv-1.13.1 A character set conversion library
libtool-2.2.6a Generic shared library support script
m4-1.4.13,1 GNU m4
[root@C78 ~]#

jail の構築【応用編】

詳説ezjail-admin コマンド

本項ではezjali で使用するコマンド、ezjail-admin コマンドについて解説します。
ここではFreeBSD 8.2 RELEASE に含まれるコマンドを使用します。

【install】
ezjail 環境のインストールをFreeBSD を配布しているFTP サーバから行います。
デフォルトでは、/usr/jails ディレクトリを使用しますが、ezjail の設定ファイル(/usr/local/etc/ezjail.conf) のezjail_jaildir を変更することにより、インストール先のディレクトリを変更することが出来ます。
  • manpage のインストール
-m オプションを付与することで、manpage をインストールします。
約10MB 使用します。
# ezjail-admin istall -m

  • FreeBSD ソースのインストール
FreeBSD ソースのインストール-s オプションを付与することで、FreeBSD のソースをインストールします。約400MB 使用します。
# ezjail-admin istall -s

  • ports
-p オプションを付与することで、ports をインストールします。jail 環境の/usr/portsにPorts tree を構築します。約475MB 使用します。
# ezjail-admin istall -p

  • リリースバージョンを指定したインストール
-r オプションを付与することで、リリースバージョンを指定してjail をインストールします。7.3-RELEASE、8.1-RELEASE などが指定できます。
尚、jail 環境下でuname -r をした場合でも、ホスト環境のバージョンが出力されます。ライブラリ、コマンドが指定されたバージョンでインストールされます。
# ezjail-admin install -r 7.3-RELEASE
  • ZFS へのインストール
ZFS へのインストールezjail ではZFS へのインストールをサポートしています。ZFS へのinstall、create を有効にするには、ezjail.conf へ以下の設定が必要です。
# ZFS へのインストールを有効にする
ezjail_use_zfs="YES"
# ZFS のボリューム名を指定する
ezjail_jailzfs="tank/ezjail"
尚、既にZFS を使用していないezjail を構築(install) している場合であっても、create により、jail のゲスト毎にZFS を使用することが可能です。

【create】
jail 環境を構築します。

  • md デバイスへのezjail 構築
-i オプションを付与することで、md デバイスを用い、img ファイルにjail のゲスト環境を構築します。
# ezjail-admin create -i -s 100M -f example C78 192.168.1.250
# ll /opt/jails/
total 102488
drwxr-xr-x 2 root wheel 512 Jul 26 01:50 C78
-rw-r--r-- 1 root wheel 104857600 Jul 26 01:50 C78.img
drwxr-xr-x 9 root wheel 512 Jul 26 00:59 basejail
drwxr-xr-x 3 root wheel 512 Jul 26 00:59 flavours
drwxr-xr-x 12 root wheel 512 Jul 26 00:59 newjail

  • 他のファイルシステムへのezjail 構築
【eli デバイスを用い、暗号化されたimg ファイルにjailのゲスト環境を構築します。eli デバイスを使用した場合、パスフレーズの入力を求められます。
# ezjail-admin create -c eli -s 100M -f example C78 192.168.1.250
以下コマンドでは、ZFS へjail のゲスト環境を構築します。
# ezjail-admin create -c zfs -s 300M C78 192.168.1.250

  • 構築済みのゲスト環境がある場合
delete を-w オプションを付けずに削除した場合等、既に構築済みのゲスト環境がある場合、-x オプションを付与することで、ezjail へ認識させることが出来ます。
# zjail-admin create -x C78 192.168.1.250

  • ezjail のアーカイブから構築する
archive オプションによりjail 環境のアーカイブを作成している場合、このアーカイブから環境を構築することが可能です。以下例では、事前に作成したアーカイブファイル名を指定しています。
# ezjail-admin create -a C78-201107270119.27.tar.gz C78 192.168.1.250

【console】
ゲスト環境へログインします。
# ezjail-admin console C78

-f オプションを付与することで、停止状態のゲスト環境を起動した後に、ログインすることが出来ます。
但し、このオプションにはバグがあり、付与しない場合でも、-f を指定した動作と同様の動作となります。
# このバグについて、ezjailの作成者を報告しました。CVSへの反映は行われています。

また、-e オプションを付与することで、指定したコマンドを実行することが出来ます。
デフォルトでは、ログインに/usr/bin/login -f root が使用されますが、bash 等、シェルコマンドを渡すことで、ログイン直後にbash を起動することが出来ます。

【list】
jail 環境を一覧で出力します。

[root@Melchior ~]# ezjail-admin list
STA JID  IP              Hostname                       Root Directory
--- ---- --------------- ------------------------------ ------------------------
DS  N/A  192.168.1.250   C78                            /opt/jails/C78

STA の列にはjail のステータスが出力されています。それぞれのアルファベットは以下の状態を表します。

  • D
    ディレクトリベースで構築されたjail。
  • I
    md ファイルイメージベースで構築されたjail。
  • B
    bde デバイスで構築されたjail。
  • E
    eli デバイスで構築されたjail。
  • R
    起動状態のjail。
  • A
    bde デバイス、eli デバイスにおいて、attach されているjail。
  • S
    停止状態のjail。
  • N
    config オプションにより、disable 状態となっているjail。

【config】
構築済みのjail 環境の設定を行います。

  • disable 状態の切り替え
-r オプションのrun、norun により、disable/enable 状態を切り替えることが出来ます。
disable 状態となったjail は、start 時に起動しません。
複数のjail 環境が存在する場合に、特定のjail 環境を起動させたくない場合に使用します。
# ezjail-admin config -r norun C78

  • jail 名の変更
-n オプションでjail 名を変更することが出来ます。
-nオプションの直後に新しいjail名を指定します。
# ezjail-admin config -n C80 C78

  • 使用するCPU の変更
CPU が複数個ある場合、jail を動作させるCPU を指定することが出来ます。内部的にcpuset(1) を使用しています。
以下では、CPU1 にjail を割り当てています。
-c 0-4 や-c 0,3 とすることで、複数のCPU を割り当てることが出来ます。
# ezjail-admin config -c 1 C80

【delete】
jail のゲスト環境を削除します。-w オプションにより、ファイルの削除を行います。ZFS を使用していた場合はデータセットも含め削除します。 

# ezjail-admin delete -w C80

【archive】
jail 環境のバックアップを作成します。
-a オプションで作成後のファイル名、-d オプションで作成先のディレクトリパスを指定します。
デフォルトではjail のルートディレクトリに、jail 名をファイル名として作成されます。
# ezjail-admin archive C78
また、-A オプションを使用することで全てのjail のバックアップを作成することが出来ます。

【restore】
archive オプションによって作成したバックアップから復元します。
# ezjail-admin restore C78

【restart】
jail 環境を再起動します。jail 名を指定することが出来ます。
# ezjail-admin restart C78

【stop】
jail 環境を停止します。jail 名を指定することが出来ます。
# ezjail-admin stop C78

【start】
jail 環境を起動します。jail 名を指定することが出来ます。
# ezjail-admin start C78

【update】
jail 環境を更新します。ソースツリーをコンパイルし、最新の状態にします。
ベースシステムを更新するため、実行する際は注意が必要です。
-p オプションでコンパイルは行わず、コピーのみを行います。また、-P オプションでは、Portsの更新のみを行います。

Tips

【マウントポイントの設定】
jail のマウントポイントはホスト環境の/etc/fstab.<jail 名>に記述されています。
内容は、ホスト環境のfstab と同様です。

【dmesg の不可視化】
jail 環境でセキュアな環境を構築する場合、ハードウェアやカーネルログを出力するdmesg コマンドを実行できるのは好ましくないでしょう。sysctl により、ゲスト環境でdmesgを実行しても、メッセージを出力しないようにします。

以下をゲスト環境のsysctl.conf に追記します。
security.bsd.unprivileged_read_msgbuf=0


Comments