2026年10月13日
2026年10月13日
chroot・jailでプロセスを隔離する方法と、その限界
chroot は、プロセスから見えるルートディレクトリを別の場所に差し替えて、それより上のファイルを見えなくする仕組みです。手軽に使える一方で、root 権限のプロセスに対しては防御として弱く、現在はSFTP専用ユーザーの閉じ込めなど用途を絞って使い、本格的な隔離は systemd のサンドボックス機能やコンテナ、FreeBSD なら jail に任せるのが一般的です。この記事では、chroot 環境の作り方と実用的な使い道、限界、より強い隔離の選び方を説明します。
chrootとjailは何が違うか
「jail(牢屋)」という言葉は、文脈によって指すものが違います。
- chroot jail: Linux などで chroot を使ってプロセスを特定のディレクトリに閉じ込めた状態の通称。隔離されるのはファイルシステムの見え方だけです
- FreeBSD の jail: FreeBSD の OS 機能で、ファイルシステムに加えてプロセス、ユーザー、ネットワーク(IP アドレス)も分けられます。Linux のコンテナに近い仕組みです
- Fail2ban の jail: ログ監視と遮断のルールの単位を jail と呼んでいるだけで、プロセス隔離とは関係ありません
この記事では主に Linux の chroot と、その代わりになる仕組みを扱います。
chrootの限界を先に知っておく
chroot はもともとセキュリティ機能として設計されたものではありません。次の点を理解したうえで使ってください。
- chroot の中のプロセスが root 権限を持っていると、外へ抜け出す手口が知られています。中で動かすプロセスは一般ユーザーの権限に落とすことが前提です
- 隔離されるのはファイルシステムの見え方だけで、プロセス一覧、ネットワーク、CPU やメモリの使用量は分かれません。中から外のプロセスにシグナルを送ったり、ネットワーク経由で他のサービスに接続したりできます
/procや/devをバインドマウントで持ち込むと、そこから外の情報が見えるようになります
つまり chroot は「見せるファイルを減らす」ための道具で、攻撃者が中で root を取った場合の防壁にはなりません。
最小のchroot環境を作ってみる
仕組みを理解するために、Debian/Ubuntu 系で最小限の環境を作る例です。debootstrap を使うと、ディレクトリの中に基本的なシステム一式を展開できます。
sudo apt install debootstrap
sudo mkdir -p /srv/chroot/demo
sudo debootstrap stable /srv/chroot/demo http://deb.debian.org/debian
中に入るときは、--userspec で一般ユーザーの権限に落としてから実行します。
sudo chroot --userspec=nobody:nogroup /srv/chroot/demo /bin/bash
中で ls / を実行すると、/srv/chroot/demo の中身がルートとして見えます。exit で抜けます。
自作のプログラムを入れる場合は、実行ファイルだけでなく、依存する共有ライブラリも chroot の中に置く必要があります。ldd /usr/bin/プログラム名 で必要なライブラリを調べられます。ここでつまずきやすいのは、名前解決(/etc/resolv.conf や /etc/nsswitch.conf)、タイムゾーン(/usr/share/zoneinfo)、乱数(/dev/urandom)といった、普段意識しないファイルです。「外では動くのに中では動かない」ときは、strace -f でどのファイルを開こうとして失敗しているかを見ると原因が分かります。
実用例1: SFTP専用ユーザーを閉じ込める
chroot が今もよく使われるのが、OpenSSH の ChrootDirectory で SFTP 利用者を特定のディレクトリに閉じ込める使い方です。制作会社にテーマ用のディレクトリだけを見せたい、といった場面で役立ちます。
# /etc/ssh/sshd_config.d/20-sftp-only.conf
Match Group sftponly
ChrootDirectory /srv/sftp/%u
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
internal-sftp は sshd に内蔵された SFTP サーバーなので、chroot の中にシェルやライブラリを置く必要がありません。
一番つまずきやすいのは所有者とパーミッションです。ChrootDirectory に指定するディレクトリと、そこに至る上位のすべてのディレクトリは、root 所有でグループや他人が書き込めない状態でなければならず、条件を満たさないと接続直後に切断されます。そのため、利用者が書き込む場所はその下にサブディレクトリとして作ります。
sudo groupadd sftponly
sudo useradd -g sftponly -s /usr/sbin/nologin -d / designer1
sudo mkdir -p /srv/sftp/designer1/upload
sudo chown root:root /srv/sftp/designer1
sudo chmod 755 /srv/sftp/designer1
sudo chown designer1:sftponly /srv/sftp/designer1/upload
sudo sshd -t && sudo systemctl reload ssh
RHEL 系ではサービス名が sshd です。WordPress のテーマディレクトリを直接編集させたい場合は、chroot の中へバインドマウントする方法がありますが、Web サーバーの実行ユーザーとの書き込み権限の兼ね合いが複雑になるため、まずはアップロード用ディレクトリで受け取り、反映は管理者が行う運用の方が安全です。
実用例2: PHP-FPMのchroot設定は慎重に
PHP-FPM にはプールごとに chroot を指定する設定があり、WordPress を動かすプロセスから他のサイトのファイルを見えなくできます。ただし WordPress で使うと、DNS 解決、SSL 証明書のストア、メール送信(sendmail)、一時ディレクトリなど多くのものを chroot の中に用意する必要があり、プラグインの更新や外部 API 連携が動かなくなる原因になりがちです。
複数サイトを同じサーバーで動かすなら、まずはサイトごとに PHP-FPM のプールと実行ユーザーを分け、ファイルの所有者で互いに読めないようにする方が、手間に対して効果が大きい方法です。chroot を試す場合は、ステージング環境でプラグイン更新や問い合わせフォームのメール送信まで動作を確かめてください。
より強い隔離: systemdのサンドボックス
自分で書いたバッチ処理や常駐プログラムを隔離したいなら、systemd のユニットにサンドボックス用の設定を加える方法が手軽です。chroot と違い、ファイルシステムの見え方に加えて、権限の昇格や一部のカーネル機能へのアクセスも制限できます。
# /etc/systemd/system/report-job.service
[Service]
User=reportjob
ExecStart=/opt/report-job/run.sh
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ReadWritePaths=/var/lib/report-job
ProtectSystem=strict でファイルシステム全体を読み取り専用にし、書き込みが必要な場所だけ ReadWritePaths で許可します。RootDirectory= を指定すれば chroot 相当の動きもできます。設定後は次のコマンドで、どの項目が未設定かを一覧で確認できます。
sudo systemctl daemon-reload
systemd-analyze security report-job.service
表示される点数はあくまで目安で、点数を上げるために必要な書き込みまで禁止するとプログラムが動かなくなります。項目を1つずつ足して、動作を確認しながら進めてください。使える項目は systemd のバージョンによって異なるため、man systemd.exec で手元の環境を確認します(2026年10月現在)。
コンテナやFreeBSD jailを選ぶ場面
プロセス、ネットワーク、リソース量まで分けたい場合は、Linux なら Docker や Podman などのコンテナ、FreeBSD なら jail が選択肢になります。コンテナは名前空間(namespace)と cgroup を組み合わせた仕組みで、unshare コマンドで名前空間を個別に試すこともできます。
ただしコンテナも、特権モード(--privileged)での起動や、ホストのディレクトリや Docker ソケットのマウントをすると隔離が大きく弱まります。中のプロセスを root 以外で動かすこと、必要な権限だけを与えることは、chroot と同じく基本になります。さらに強制アクセス制御(AppArmor や SELinux)を組み合わせると、隔離が破られた場合の被害を小さくできます。
まとめ
- chroot はファイルシステムの見え方を変えるだけで、中の root 権限に対する防壁にはならない
- 中のプロセスは
--userspecなどで一般ユーザーに落として動かす - 今でも実用的なのは OpenSSH の
ChrootDirectoryによる SFTP 専用ユーザーの閉じ込めで、chroot 先は root 所有・他人書き込み不可にする - WordPress の PHP-FPM を chroot すると依存ファイルの用意が大変なため、まずはサイトごとの実行ユーザー分離を優先する
- 自作プログラムの隔離は systemd のサンドボックス、より強い分離はコンテナや FreeBSD jail を検討する