Jailとは
FreeBSD環境上に仮想のFreeBSD環境を複数構築することが出来るしくみである。
jailはchrootを発展させたもので、ホスト環上(jailerと呼ぶ)に構築したjail環境(prisonerと呼ぶ)は、ホスト環境とは別に動作するFreeBSDマシンとして振舞う。
prisonerからはjailerおよび並列する別のprisonerに直接アタッチすることが出来ない。
jailの特徴
・エミュレーションではないため、高速に動作する
・prisonerごとにjailerとは別のIPアドレスを振ることができる
・jailerとprisonerで同一のファイルシステムが利用されるため、UID/GIDの割り当てに注意する必要がある
今回は、jailer(FreeBSD14.1)内に2つのprisoner(prisoner1、prisoner2)を構築する
Jailの構築
1.prisonerのベースディレクトリの作成
prisoner1、prisoner2のルートディレクトリになるディレクトリ(jail)を作成。今回は/homeに作成するが任意の場所でよい
1 2 3 |
# mkdir /home/jail # mkdir /home/jail/prisoner1 # mkdir /home/jail/prisoner2 |
2.ベースシステムのインストール
prisoner1、prisoner2にベースシステムをインストールする。 FreeBSDのレポジトリからbase.txzをダウンロードして、prisoner1 、prisoner2に展開する
1 2 3 4 |
# fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/amd64/14.1-RELEASE/base.txz # tar -zxpf base.txz -C /home/jail/prisoner1 # tar -zxpf base.txz -C /home/jail/prisoner2 # rm base.txz |
3./etc/resolv.confのコピー
prisoner1 、prisoner2で名前解決ができるよう「resolv.conf」を作成する。
「resolv.conf」の内容は、jailerと同じ設定で問題ないため、このファイルをjailer側からコピーする。
1 2 |
# cp -p /etc/resolv.conf /home/jail/prisoner1/etc/ # cp -p /etc/resolv.conf /home/jail/prisoner2/etc/ |
4.prisonerでのkernel関連のログ出力を抑止する
prisoner1、 prisoner2のログに、kernel関係の出力がされないよう、「syslog.conf」を編集して設定。
1 2 3 4 |
# vi /home/jail/prisoner1/etc/syslog.conf 7行目 : コメントアウト #*.err;kern.warning;auth.notice;mail.crit /dev/console |
1 2 3 4 |
# vi /home/jail/prisoner2/etc/syslog.conf 7行目 : コメントアウト #*.err;kern.warning;auth.notice;mail.crit /dev/console |
5.adjkerntzの停止
各prisonerのcronによってkernelのタイムゾーンが設定されないよう、crontabを編集する。
(kernelのタイムゾーン設定はjailer側のcronで定期的に行われるため、prisonerでのcronによる設定は不要。)
1 2 3 4 |
# vi /home/jail/prisoner1/etc/crontab 22行目 : コメントアウト #1,31 0-5 * * * root adjkerntz -a |
1 2 3 4 |
# vi /home/jail/prisoner2/etc/crontab 22行目 : コメントアウト #1,31 0-5 * * * root adjkerntz -a |
6.prisonerの名前解決のための設定
prisoner1 、prisoner2で、自身の名前を解決できるように「hosts」を編集する
prisoner1 、prisoner2に割り当てるIPアドレスとFQDNのペアを追記
1 2 3 4 |
# vi /home/jail/prisoner1/etc/hosts 最終行に追加 192.168.11.31 alma.korodes.com |
1 2 3 4 |
# vi /home/jail/prisoner2/etc/hosts 最終行に追加 192.168.11.32 rocky.korodes.com |
7.jailerとprisonerでUID/GIDを重複させないための設定
jailでは、jailerと各prisonerでひとつのファイルシステムを共有するので、jailer側で利用しているUID/GIDをそのままprisoner側で利用してしまうと、jailer側のユーザがprisoner側のユーザのファイルを自分のものとして扱えてしまうことになる。そのため、jailerと各prisonerで重複しないUID/GIDを振る必要がある。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# vi /etc/pw.conf defaultpasswd no minuid 10000 maxuid 19999 mingid 10000 maxgid 19999 # vi /home/jail/prisoner1/etc/pw.conf defaultpasswd no minuid 20000 maxuid 29999 mingid 20000 maxgid 29999 # vi /home/jail/prisoner2/etc/pw.conf defaultpasswd no minuid 30000 maxuid 39999 mingid 30000 maxgid 39999 |
※ ただし、「root」等の予め定義されているユーザ、および「pgsql」や「postfix」等のports経由で追加されるユーザについては、jailerとprisonerで同じUID/GIDが割り当てられる。
これらのユーザのUID/GIDを変更するには、「vipw」を利用して、直接UID/GIDを変更する。
(「vipw」でUID/GIDを変更しても、これらのユーザが所有者となっているファイルのオーナーのUID/GIDは自動的には更新されないのでchown/chgrpする必要がある)
8.prisoner1 、prisoner2のdevfsのマウント
各prisonerでデバイスが利用できるよう、各prisonerのdevをマウントする。
1 2 |
# mount -t devfs devfs /home/jail/prisoner1/dev # mount -t devfs devfs /home/jail/prisoner2/dev |
9.prisonerでの設定
「chroot」を利用してprisoner1 、prisoner2のルートディレクトリに移動し設定を行う。
(chrootしたディレクトリからjailer側に戻るときには「exit」を利用する)
1 2 3 4 5 |
# chroot /home/jail/prisoner1 # touch /etc/wall_cmos_clock # ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime # passwd root # exit |
1 2 3 4 5 |
# chroot /home/jail/prisoner2 # touch /etc/wall_cmos_clock # ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime # passwd root # exit |
それぞれの最後に、そのprisonerにおけるrootのパスワードを設定する(このパスワードはjailerのrootのパスワードとは区別される。)
10.jail環境の起動のための設定
jailer側でprisoner1 、prisoner2側に割り当てるIPアドレス、FQDN等を設定する。
「/etc/rc.conf」の最後に下記を追記する。em0は各自のインターフェース名に合わす
1 2 3 4 5 6 7 8 |
# vi /etc/rc.conf ifconfig_em0_alias0="inet 192.168.11.31 netmask 255.255.255.255" ifconfig_em0_alias1="inet 192.168.11.32 netmask 255.255.255.255" jail_enable="YES" jail_list="prisoner1 prisoner2 " #jail_sysvipc_allow="YES" |
「jail_sysvipc_allow=」は、prisoner上のプロセスからシェアドメモリにアクセスさせるか否かの設定。
セキュリティの観点から「NO」にしておくが、PostgreSQLなどのシェアドメモリを利用するソフトウェアを動かす際には「YES」に設定する。
prisoner1 、prisoner2の設定を下記の通り、「/etc/jail.conf」に記述する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# vi /etc/jail.conf prisoner1 { jid=1; path="/home/jail/prisoner1"; ip4.addr=192.168.11.31; host.hostname="alma.korodes.com"; allow.chflags=1; allow.raw_sockets=1; exec.start="/bin/sh /etc/rc"; exec.stop="/bin/sh /etc/rc.shutdown jail"; interface=em0; mount.devfs; devfs_ruleset=4; } prisoner2 { jid=2; path="/home/jail/prisoner2"; ip4.addr=192.168.11.32; host.hostname="rocky.korodes.com"; allow.chflags=1; allow.raw_sockets=1; exec.start="/bin/sh /etc/rc"; exec.stop="/bin/sh /etc/rc.shutdown jail"; interface=em0; mount.devfs; devfs_ruleset=4; } |
デフォルトでは、prisonerではtracerouteやping、bpfを利用したWIDE-DHCP等のraw socketを利用するプログラムが正常に動作しない。
これらのプログラムを利用するためには、「/etc/jail.conf」内の各prisoner設定内に、「allow.raw_sockets;」の設定を追記する。
システムを再起動
各prisonerを有効にする。
11.prisonerを削除
prisoner環境を再度一から構築しなおす場合には、以下のようにしてprisonerを削除し再構築する。
prisoner1を削除する場合
1 2 3 4 5 |
# /etc/rc.d/jail stop prisoner1 # chflags -R noschg /home/jail/prisoner1/* # rm -R /home/jail/prisoner1/* |
12.jailerで利用できるjail関連のコマンド
①稼動中のprisonerの一覧表示
1 2 3 4 |
# jls JID IP Address Hostname Path 1 192.168.11.31 alma.korodes.com /home/jail/prisoner1 2 192.168.11.32 rocky.korodes.com /home/jail/prisoner2 |
一番左側に表示される「JID」はprisonerに割り振られたIDで、後述する「jexec」で遷移するprisonerを特定する際に利用する
➁jailerからprisonerに遷移
JIDが「1」のprisonerに「/bin/csh」のシェルを利用して遷移する場合
1 |
# jexec 1 /bin/csh |
➂prisonerの起動/停止
1 2 3 4 5 6 7 8 9 10 11 |
全prisonerの停止 # /etc/rc.d/jail stop 全prisonerの開始 # /etc/rc.d/jail start 特定のprisonerを指定して開始 # /etc/rc.d/jail start prisoner1 特定のprisonerを指定して停止 # /etc/rc.d/jail stop prisoner1 |
13. jail からホストマシンへの ping
JIDが「1」のprisoner1に遷移して実行する
1 |
# jexec 1 /bin/csh |
ホストマシン(192.168.11.83)へ3回 ping
1 2 3 4 5 6 7 8 9 |
# ping -c 3 192.168.11.83 PING 192.168.11.83 (192.168.11.83): 56 data bytes 64 bytes from 192.168.11.83: icmp_seq=0 ttl=64 time=0.228 ms 64 bytes from 192.168.11.83: icmp_seq=1 ttl=64 time=0.306 ms 64 bytes from 192.168.11.83: icmp_seq=2 ttl=64 time=1.359 ms --- 192.168.11.83 ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.228/0.631/1.359/0.516 ms |