魔術師見習いのノート

プロフィール

魔術師見習い
Author魔術師見習い-_-.
Twitter魔術師見習い

コンピュータ関係のメモを主に書きます.

MENU

jail

投稿日:
修正日:
タグ:

FreeBSDのjailの構築の度に「【FreeBSD】FreeBSDサーバ上に仮想サーバを構築する(jail)」に依存しているので、それを回避するためのメモ。なおメモの途中で"man jail.conf"のEXAMPLESに手順が書いてあることに気づいた。

構築の手順は大雑把には次の通りである。

  1. カーネルのインストールと設定
  2. jailの設定

なお本稿ではパスや名前に以下の環境変数を使用する。

環境変数値の例用途
JAIL_NAMEmyjail1jailの名前
JROOT_PATH/usr/jail/myjailjailのルートディレクトリ
もし2つ以上のjailを生成するならば、これらの変数の値を変えれば良い。

カーネルのインストール

FreeBSDのカーネルのソースは/usr/srcにある。

user% cd /usr/src

カーネルのビルドにはmakeコマンドを使用する。makeに与えるターゲット名や変数はMakefileを参照されたし。特にターゲットについては丁寧に記述されている。

  1. カーネルのビルド
    user% make buildworld
  2. カーネルのインストール
    user% make installworld DESTDIR=${JROOT_PATH}
  3. カーネルの設定ファイルのインストール
    user% cd /usr/src/etc
    user% make distribution DESTDIR=${JROOT_PATH}
  4. jailのdevfsをマウント
    user% mount -t devfs devfs ${JROOT_PATH}/dev
DESTDIRで指定するディレクトリはあらかじめmkdirで生成しておく必要がある。

カーネルのビルドとインストールは以下のようにまとめて行うこともできる。

user% make world DESTDIR=${JROOT_PATH}
また、一度カーネルのビルドを行えば、2つ目以降のjailの生成では省略できる。なおビルドの際の設定はmake.confを使用する。詳細は"man make.conf"を参照されたし。


${JROOT_PATH}/etc以下のファイルの修正

"make distribution"でインストールした設定ファイルは、そのままではjail用でない。それでも実行するのに支障はないが、ホストと複数のjail間での競合によるトラブルを回避したいならば、いくつかの設定ファイルを修正する必要がある。以下にいくつか紹介する。

  • カーネルのログ出力を抑止。syslogdの設定ファイル(${JROOT_PATH}/etc/syslog.conf)を修正(コメントアウト)。
    before
    *.err;kern.warning;auth.notice;mail.crit /dev/console
    after
    #*.err;kern.warning;auth.notice;mail.crit /dev/console
  • カーネルの時間を制御するための時間同期(adjkerntz)を抑止。crontabの設定ファイル(${JROOT_PATH}/etc/crontab)を修正。
    before
    1,31    0-5     *       *       *       root    adjkerntz    -a
    after
    #1,31    0-5     *       *       *       root    adjkerntz    -a
  • OS全体で使用するユーザidとグループidを重複させないように設定。jailの設定ファイル(${JROOT_PATH}/etc/pw.conf)及びホストの設定ファイル(/etc/pw.conf)を修正(コメントアウト)。以下に記述例を示す。
    minuid  1000
    maxuid  1999
    mingid  1000
    maxgid  1999
    
    このように設定すれば、ユーザIDとグループIDは1000から1999の範囲に限定される。同じ要領で他の環境も設定すれば、重複しないようにできる。pw.confの詳細は"man pw.conf"を参照されたし。
  • ホスト名のローカルデータベースの設定。自分が使用するホスト情報が/etc/hostsにあるならば、それをコピーした方が早い。
    user% cp /etc/hosts ${JROOT_PATH}/etc/.

ネットワークインタフェース

ネットワークインタフェースがホストやjail間で共有している場合(例えばホストでエイリアスしたものを使用している場合)、意図した相手と異なる相手にアクセスしてしまうことがありうる。それを回避する方法をいくつか紹介する。

  • sshサーバが受信する宛先IPアドレスを設定(${JROOT_PATH}/etc/ssh/sshd_configを修正)。以下に例を示す。
    before
    #ListenAddress 0.0.0.0
    after
    ListenAddress 192.168.1.2

jailはデフォルトでは、raw socketを利用したプログラムが正常に機能しない。これを回避するためには/etc/sysctl.confに次の行を追加する必要がある。

security.jail.allow_raw_sockets=1


jailの設定

jailの構築が終わったら、jailのルート以下のファイルの設定を行う。なお以下で紹介する処理のほとんどは、jailを動かすために必要不可欠という訳ではない。以下のいくつかについては"man jail.conf"のConfiguring the Jailを参照されたし。

jailのルートディレクトリ以下で作業をする場合、chrootを使えばルートディレクトリを変更できる。

user% chroot ${JROOT_PATH}
ルートディレクトリを元に戻すにはexitで終了すれば良い。
  • DNSサーバの設定。エディタを起動して手動で設定するか、後述のようにホストのものをコピーするかすれば良い。
    user% vi /etc/resolv.conf
    ホストのresolv.confをコピーするには、ルートディレクトリを通常に戻った後に、次のように行えば良い。
    user% cp /etc/resolv.conf ${JROOT_PATH}/etc/.
  • jailのrootパスワードの設定
    passwd root
  • タイムゾーンの設定
    ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
  • 警告を防ぐために空の/etc/fstabを生成。
    touch /etc/fstab
  • adjkerntzは/etc/wall_cmos_clockがある場合、 CMOSクロックは(MS-DOSやMS-Windows互換モードの)ローカル時間を保持していることを意味する。
    touch /etc/wall_cmos_clock
    このファイルが無い場合、CMOSクロックはUTC時間を保持していることになる。
  • sendmailの警告を防ぐために次のコマンドを実行
    newaliases
  • 警告を防ぐためにインタフェースを無効化。 エディタを起動し、
    vi /etc/rc.conf
    次のパラメータを設定。
    network_interfaces=""
  • ポートマッパー(rpcbind)を無効化。rc.confに次のパラメータを設定。
    rpcbind_enable="NO"
  • デフォルトではrootしかいないので、必要であれば更にユーザの追加が必要。
    user% pw useradd -n user1
  • jailに導入したいパッケージをインストール

  • SSHサーバが受信する宛先IPアドレスを設定(前述の処理と同じようにすれば良い)。
  • FreeBSDではカーネルのようないくつかの重要なファイルのフラグがschg(システムの変更禁止フラグ)である。これがあると移動や削除ができない。これを解除するためには次のようなフラグの変更が必要。
    chflags noschg /sbin/init
  • dumpユーティリティというファイルシステムのバックアップのためのユーティリティがある。jailにとってファイルシステムの管理は不要であり、/etc/rmtのリンクを解除する。
    unlink /etc/rmt


jailの実行

jail機能を有効にするためには、/etc/rc.d/jailという起動スクリプトを使用する。しかしそのためには、rc.confの設定が必要である。

rc.conf

ホスト側のrc.confにはいくつかの設定が必要である。設定にはjail機能の設定と各jailの設定の2種類がある。 また、各jailが使用するネットワークインタフェースをホストのネットワークインタフェースのエイリアスしたものを使用するならばその設定も必要である。

使用するネットワークインタフェースが"re0"ならば次のようなコマンドを実行すれば良い。

user% ifconfig re0 alias 192.168.101 netmask 255.255.255.0
この処理を起動時に自動的に行うならば、以下のようにrc.confに記述すれば良い。
ifconfig_re0_alias0="inet 192.168.1.101 netmask 255.255.255.0"
ifconfig_re0_alias1="inet 192.168.1.102 netmask 255.255.255.0"

そしてjail機能や各jailの設定は次のように記述すれば良い。

jail_enable="YES"
jail_list="myjail1 myjail2"
jail_set_hostname_allow="NO"
jail_socket_unixiproute_only="YES"
jail_sysvipc_allow="YES"
jail_stop_jailer="NO"

jail_myjail1_rootdir="/home/jail/myjail1"
jail_myjail1_hostname="myjail1"
jail_myjail1_ip="192.168.1.101"
jail_myjail1_exec="/bin/sh /etc/rc"
jail_myjail1_devfs_enable="YES"
jail_myjail1_fdescfs_enable="NO"
jail_myjail1_procfs_enable="YES"

jail_myjail2_rootdir="/home/jail/myjail2"
jail_myjail2_hostname="myjail2"
jail_myjail2_ip="192.168.1.102"
jail_myjail2_exec="/bin/sh /etc/rc"
jail_myjail2_devfs_enable="YES"
jail_myjail2_fdescfs_enable="NO"
jail_myjail2_procfs_enable="YES"
各jailの設定は/etc/jail.confというものに書くことができるらしい(それを使った方が恐らく簡潔に記述できるはず)。 各jailの設定は/etc/jail.confというものに書くことができる。jail.confの記述例については後述する。

rc.confの設定が完了すれば、起動スクリプトで実行できる。

user% /etc/rc.d/jail start myjail1

jail.conf

jail.confで使用するパラメータ名はrc.confで使用したものと異なる場合が多い。それらの情報はmanで閲覧できる。

jail.confは次の2種類の文からなる。

  • 全てのjailの基となる設定
  • 各jail個別の設定
# shared rule
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
mount.devfs;

# myjail1's rule
myjail1 {
  path = "/home/jail/myjail1";
  host.hostname = "myjail1";
  ip4.addr = 192.168.1.101;
}

# myjail2's rule
myjail2 {
  path = "/home/jail/myjail2";
  host.hostname = "myjail2";
  ip4.addr = 192.168.1.102;
}

jail.confには変数が利用できる。変数には特別なものがありjail名などはnameという変数に格納される。それゆえ、前述のpathやhost.hostnameのように一部だけ違う場合は次のように記述できる。

# shared rule
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
mount.devfs;
path = "/home/jail/${name}";
host.hostname = "${name}";

# myjail1's rule
myjail1 {
  ip4.addr = 192.168.1.101;
}

# myjail2's rule
myjail2 {
  ip4.addr = 192.168.1.102;
}

jail関連コマンド

jailの制御には次のようなコマンドがある。

コマンド機能使用例
jlsjailの一覧を表示
user% jls
   JID  IP Address      Hostname     Path
     1  192.168.1.101    myjail1     /usr/jail/myjail1
     2  192.168.1.102    myjail2     /usr/jail/myjail2
jexecJIDを指定し、そのjailで指定したコマンドを実行 jexecでシェルを指定すればjail内で作業ができる。
user% jexec 2 sh
なおFreeBSD10では前述の引数ではエラーが返され、次のように名前を指定しなければならなかった。
user% jexec myjail2 sh

一覧